From 5a2611967bbcb0e20c78f1f221465281583dec72 Mon Sep 17 00:00:00 2001 From: James Muscat Date: Sun, 11 Aug 2024 14:48:56 +0100 Subject: [PATCH] Move MQTT discovery information into devices.json. We inject some "magic" overrides when `devices.json` is created, rather than at runtime; this means that users can update the discovery information directly in their `devices.json` configuration rather than in the code. This way, they can change existing or add new discovery information without needing a code change. --- HADiscovery.py | 33 +++++++++++++++++++++++---------- hc-login.py | 3 ++- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/HADiscovery.py b/HADiscovery.py index 01b3c9d..cb9e378 100644 --- a/HADiscovery.py +++ b/HADiscovery.py @@ -12,8 +12,14 @@ def decamelcase(str): HA_DISCOVERY_PREFIX = "homeassistant" +# These "magic overrides" provide HA MQTT autodiscovery data that is injected +# into devices.json when `hc-login.py` is run; the data is then read from +# devices.json at runtime. +# +# Note: keys should be integer (not string) taken from a device's feature +# mapping. MAGIC_OVERRIDES = { - "BackendConnected": { + 5: { # BSH.Common.Status.BackendConnected "component_type": "binary_sensor", "payload_values": { "device_class": "connectivity", @@ -21,14 +27,14 @@ MAGIC_OVERRIDES = { "payload_off": False } }, - "SoftwareUpdateAvailable": { + 21: { # BSH.Common.Event.SoftwareUpdateAvailable "component_type": "binary_sensor", "payload_values": { "device_class": "update", "payload_on": "Present" } }, - "DoorState": { + 527: { # BSH.Common.Status.DoorState "component_type": "binary_sensor", "payload_values": { "device_class": "door", @@ -36,41 +42,41 @@ MAGIC_OVERRIDES = { "payload_off": "Closed" } }, - "PowerState": { + 539: { # BSH.Common.Setting.PowerState "component_type": "binary_sensor", "payload_values": { "device_class": "power" } }, - "RinseAidLack": { + 4612: { # Dishcare.Dishwasher.Event.WaterheaterCalcified "component_type": "binary_sensor", "payload_values": { "device_class": "problem", "payload_on": "Present" } }, - "SaltLack": { + 5624: { # Dishcare.Dishwasher.Event.SaltLack "component_type": "binary_sensor", "payload_values": { "device_class": "problem", "payload_on": "Present" } }, - "RinseAidNearlyEmpty": { + 5625: { # Dishcare.Dishwasher.Event.RinseAidLack "component_type": "binary_sensor", "payload_values": { "device_class": "problem", "payload_on": "Present" } }, - "SaltNearlyEmpty": { + 4626: { # Dishcare.Dishwasher.Event.SaltNearlyEmpty "component_type": "binary_sensor", "payload_values": { "device_class": "problem", "payload_on": "Present" } }, - "WaterheaterCalcified": { + 5627: { # Dishcare.Dishwasher.Event.RinseAidNearlyEmpty "component_type": "binary_sensor", "payload_values": { "device_class": "problem", @@ -80,6 +86,13 @@ MAGIC_OVERRIDES = { } +def augment_device_features(features): + for id, feature in features.items(): + if id in MAGIC_OVERRIDES: + feature["discovery"] = MAGIC_OVERRIDES[id] + return features + + def publish_ha_discovery(device, client, mqtt_topic): print(f"{now()} Publishing HA discovery for {device}") @@ -117,7 +130,7 @@ def publish_ha_discovery(device, client, mqtt_topic): default_component_type = "binary_sensor" if feature_type == "Event" else "sensor" # TODO use more appropriate types - overrides = MAGIC_OVERRIDES.get(name, {}) + overrides = feature.get("discovery", {}) component_type = overrides.get("component_type", default_component_type) diff --git a/hc-login.py b/hc-login.py index b43e9d5..7779bcd 100755 --- a/hc-login.py +++ b/hc-login.py @@ -17,6 +17,7 @@ from Crypto.Hash import SHA256 from Crypto.Random import get_random_bytes from HCxml2json import xml2json +from HADiscovery import augment_device_features # These two lines enable debugging at httplib level (requests->urllib3->http.client) # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA. @@ -310,6 +311,6 @@ for app in account["data"]["homeAppliances"]: machine = xml2json(features, description) config["description"] = machine["description"] - config["features"] = machine["features"] + config["features"] = augment_device_features(machine["features"]) print(json.dumps(configs, indent=4))