[pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
This commit is contained in:
196
HADiscovery.py
196
HADiscovery.py
@@ -5,7 +5,7 @@ from HCSocket import now
|
|||||||
|
|
||||||
|
|
||||||
def decamelcase(str):
|
def decamelcase(str):
|
||||||
split = re.findall(r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))', str)
|
split = re.findall(r"[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))", str)
|
||||||
return f"{split[0]} {' '.join(split[1:]).lower()}".strip()
|
return f"{split[0]} {' '.join(split[1:]).lower()}".strip()
|
||||||
|
|
||||||
|
|
||||||
@@ -21,39 +21,27 @@ HA_DISCOVERY_PREFIX = "homeassistant"
|
|||||||
MAGIC_OVERRIDES = {
|
MAGIC_OVERRIDES = {
|
||||||
3: { # BSH.Common.Setting.AllowBackendConnection
|
3: { # BSH.Common.Setting.AllowBackendConnection
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
5: { # BSH.Common.Status.BackendConnected
|
5: { # BSH.Common.Status.BackendConnected
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {
|
||||||
"device_class": "connectivity",
|
"device_class": "connectivity",
|
||||||
"payload_on": True,
|
"payload_on": True,
|
||||||
"payload_off": False
|
"payload_off": False,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
21: { # BSH.Common.Event.SoftwareUpdateAvailable
|
21: { # BSH.Common.Event.SoftwareUpdateAvailable
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "update", "payload_on": "Present"},
|
||||||
"device_class": "update",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
517: { # BSH.Common.Status.RemoteControlStartAllowed
|
517: { # BSH.Common.Status.RemoteControlStartAllowed
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
523: { # BSH.Common.Status.RemoteControlActive
|
523: { # BSH.Common.Status.RemoteControlActive
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
524: { # BSH.Common.Setting.ChildLock
|
524: { # BSH.Common.Setting.ChildLock
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
@@ -61,183 +49,104 @@ MAGIC_OVERRIDES = {
|
|||||||
"device_class": "lock",
|
"device_class": "lock",
|
||||||
"payload_on": False, # Lock "on" means "unlocked" to HA
|
"payload_on": False, # Lock "on" means "unlocked" to HA
|
||||||
"payload_off": True, # Lock "off" means "locked"
|
"payload_off": True, # Lock "off" means "locked"
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
525: { # BSH.Common.Event.AquaStopOccured
|
525: { # BSH.Common.Event.AquaStopOccured
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
527: { # BSH.Common.Status.DoorState
|
527: { # BSH.Common.Status.DoorState
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "door", "payload_on": "Open", "payload_off": "Closed"},
|
||||||
"device_class": "door",
|
|
||||||
"payload_on": "Open",
|
|
||||||
"payload_off": "Closed"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
539: { # BSH.Common.Setting.PowerState
|
539: { # BSH.Common.Setting.PowerState
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "power"},
|
||||||
"device_class": "power"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
542: { # BSH.Common.Option.ProgramProgress
|
|
||||||
"payload_values": {
|
|
||||||
"unit_of_measurement": "%"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
542: {"payload_values": {"unit_of_measurement": "%"}}, # BSH.Common.Option.ProgramProgress
|
||||||
543: { # BSH.Common.Event.LowWaterPressure
|
543: { # BSH.Common.Event.LowWaterPressure
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
544: { # BSH.Common.Option.RemainingProgramTime
|
544: { # BSH.Common.Option.RemainingProgramTime
|
||||||
"payload_values": {
|
"payload_values": {"unit_of_measurement": "s", "device_class": "duration"}
|
||||||
"unit_of_measurement": "s",
|
|
||||||
"device_class": "duration"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
549: { # BSH.Common.Option.RemainingProgramTimeIsEstimated
|
549: { # BSH.Common.Option.RemainingProgramTimeIsEstimated
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
558: { # BSH.Common.Option.StartInRelative
|
558: { # BSH.Common.Option.StartInRelative
|
||||||
"payload_values": {
|
"payload_values": {"unit_of_measurement": "s", "device_class": "duration"}
|
||||||
"unit_of_measurement": "s",
|
|
||||||
"device_class": "duration"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4101: { # Dishcare.Dishwasher.Status.SilenceOnDemandRemainingTime
|
4101: { # Dishcare.Dishwasher.Status.SilenceOnDemandRemainingTime
|
||||||
"payload_values": {
|
"payload_values": {"unit_of_measurement": "s", "device_class": "duration"}
|
||||||
"unit_of_measurement": "s",
|
|
||||||
"device_class": "duration"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4103: { # Dishcare.Dishwasher.Status.EcoDryActive
|
4103: { # Dishcare.Dishwasher.Status.EcoDryActive
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4382: { # Dishcare.Dishwasher.Status.SilenceOnDemandDefaultTime
|
4382: { # Dishcare.Dishwasher.Status.SilenceOnDemandDefaultTime
|
||||||
"payload_values": {
|
"payload_values": {"unit_of_measurement": "s", "device_class": "duration"}
|
||||||
"unit_of_measurement": "s",
|
|
||||||
"device_class": "duration"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4384: { # Dishcare.Dishwasher.Setting.SpeedOnDemand
|
4384: { # Dishcare.Dishwasher.Setting.SpeedOnDemand
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4608: { # Dishcare.Dishwasher.Event.InternalError
|
4608: { # Dishcare.Dishwasher.Event.InternalError
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4609: { # Dishcare.Dishwasher.Event.CheckFilterSystem
|
4609: { # Dishcare.Dishwasher.Event.CheckFilterSystem
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4610: { # Dishcare.Dishwasher.Event.DrainingNotPossible
|
4610: { # Dishcare.Dishwasher.Event.DrainingNotPossible
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4611: { # Dishcare.Dishwasher.Event.DrainPumpBlocked
|
4611: { # Dishcare.Dishwasher.Event.DrainPumpBlocked
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4612: { # Dishcare.Dishwasher.Event.WaterheaterCalcified
|
4612: { # Dishcare.Dishwasher.Event.WaterheaterCalcified
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4613: { # Dishcare.Dishwasher.Event.LowVoltage
|
4613: { # Dishcare.Dishwasher.Event.LowVoltage
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4624: { # Dishcare.Dishwasher.Event.SaltLack
|
4624: { # Dishcare.Dishwasher.Event.SaltLack
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4625: { # Dishcare.Dishwasher.Event.RinseAidLack
|
4625: { # Dishcare.Dishwasher.Event.RinseAidLack
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4626: { # Dishcare.Dishwasher.Event.SaltNearlyEmpty
|
4626: { # Dishcare.Dishwasher.Event.SaltNearlyEmpty
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4627: { # Dishcare.Dishwasher.Event.RinseAidNearlyEmpty
|
4627: { # Dishcare.Dishwasher.Event.RinseAidNearlyEmpty
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"device_class": "problem", "payload_on": "Present"},
|
||||||
"device_class": "problem",
|
|
||||||
"payload_on": "Present"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
5121: { # Dishcare.Dishwasher.Option.ExtraDry
|
5121: { # Dishcare.Dishwasher.Option.ExtraDry
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
5124: { # Dishcare.Dishwasher.Option.HalfLoad
|
5124: { # Dishcare.Dishwasher.Option.HalfLoad
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
5127: { # Dishcare.Dishwasher.Option.VarioSpeedPlus
|
5127: { # Dishcare.Dishwasher.Option.VarioSpeedPlus
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
5136: { # Dishcare.Dishwasher.Option.SilenceOnDemand
|
5136: { # Dishcare.Dishwasher.Option.SilenceOnDemand
|
||||||
"component_type": "binary_sensor",
|
"component_type": "binary_sensor",
|
||||||
"payload_values": {
|
"payload_values": {"payload_on": True, "payload_off": False},
|
||||||
"payload_on": True,
|
|
||||||
"payload_off": False
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,11 +168,8 @@ def publish_ha_discovery(device, client, mqtt_topic):
|
|||||||
device_description = device.get("description", {})
|
device_description = device.get("description", {})
|
||||||
|
|
||||||
version_parts = filter(
|
version_parts = filter(
|
||||||
lambda d : d is not None,
|
lambda d: d is not None,
|
||||||
[
|
[device_description.get("version"), device_description.get("revision")],
|
||||||
device_description.get("version"),
|
|
||||||
device_description.get("revision")
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
device_info = {
|
device_info = {
|
||||||
@@ -271,7 +177,7 @@ def publish_ha_discovery(device, client, mqtt_topic):
|
|||||||
"name": device_name,
|
"name": device_name,
|
||||||
"manufacturer": device_description.get("brand"),
|
"manufacturer": device_description.get("brand"),
|
||||||
"model": device_description.get("model"),
|
"model": device_description.get("model"),
|
||||||
"sw_version": ".".join(version_parts)
|
"sw_version": ".".join(version_parts),
|
||||||
}
|
}
|
||||||
|
|
||||||
for feature in device["features"].values():
|
for feature in device["features"].values():
|
||||||
@@ -281,12 +187,24 @@ def publish_ha_discovery(device, client, mqtt_topic):
|
|||||||
access = feature.get("access", "none")
|
access = feature.get("access", "none")
|
||||||
available = feature.get("available", False)
|
available = feature.get("available", False)
|
||||||
|
|
||||||
if (feature_type == "Setting" and available and (access == "read" or access == "readWrite")) or \
|
if (
|
||||||
(feature_type == "Status" and available and (access == "read" or access == "readWrite")) or \
|
(
|
||||||
feature_type == "Event" or \
|
feature_type == "Setting"
|
||||||
feature_type == "Option":
|
and available
|
||||||
|
and (access == "read" or access == "readWrite")
|
||||||
|
)
|
||||||
|
or (
|
||||||
|
feature_type == "Status"
|
||||||
|
and available
|
||||||
|
and (access == "read" or access == "readWrite")
|
||||||
|
)
|
||||||
|
or feature_type == "Event"
|
||||||
|
or feature_type == "Option"
|
||||||
|
):
|
||||||
|
|
||||||
default_component_type = "binary_sensor" if feature_type == "Event" else "sensor" # TODO use more appropriate types
|
default_component_type = (
|
||||||
|
"binary_sensor" if feature_type == "Event" else "sensor"
|
||||||
|
) # TODO use more appropriate types
|
||||||
|
|
||||||
overrides = feature.get("discovery", {})
|
overrides = feature.get("discovery", {})
|
||||||
|
|
||||||
@@ -294,7 +212,9 @@ def publish_ha_discovery(device, client, mqtt_topic):
|
|||||||
|
|
||||||
extra_payload_values = overrides.get("payload_values", {})
|
extra_payload_values = overrides.get("payload_values", {})
|
||||||
|
|
||||||
discovery_topic = f"{HA_DISCOVERY_PREFIX}/{component_type}/hcpy/{device_ident}_{name}/config"
|
discovery_topic = (
|
||||||
|
f"{HA_DISCOVERY_PREFIX}/{component_type}/hcpy/{device_ident}_{name}/config"
|
||||||
|
)
|
||||||
# print(discovery_topic, state_topic)
|
# print(discovery_topic, state_topic)
|
||||||
|
|
||||||
discovery_payload = {
|
discovery_payload = {
|
||||||
@@ -305,7 +225,7 @@ def publish_ha_discovery(device, client, mqtt_topic):
|
|||||||
"value_template": "{{value_json." + name + " | default('unavailable')}}",
|
"value_template": "{{value_json." + name + " | default('unavailable')}}",
|
||||||
"object_id": f"{device_ident}_{name}",
|
"object_id": f"{device_ident}_{name}",
|
||||||
"unique_id": f"{device_ident}_{name}",
|
"unique_id": f"{device_ident}_{name}",
|
||||||
**extra_payload_values
|
**extra_payload_values,
|
||||||
}
|
}
|
||||||
|
|
||||||
if component_type == "binary_sensor":
|
if component_type == "binary_sensor":
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ from bs4 import BeautifulSoup
|
|||||||
from Crypto.Hash import SHA256
|
from Crypto.Hash import SHA256
|
||||||
from Crypto.Random import get_random_bytes
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
||||||
from HCxml2json import xml2json
|
|
||||||
from HADiscovery import augment_device_features
|
from HADiscovery import augment_device_features
|
||||||
|
from HCxml2json import xml2json
|
||||||
|
|
||||||
# These two lines enable debugging at httplib level (requests->urllib3->http.client)
|
# 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.
|
# You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ import click
|
|||||||
import click_config_file
|
import click_config_file
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
|
|
||||||
|
from HADiscovery import publish_ha_discovery
|
||||||
from HCDevice import HCDevice
|
from HCDevice import HCDevice
|
||||||
from HCSocket import HCSocket, now
|
from HCSocket import HCSocket, now
|
||||||
from HADiscovery import publish_ha_discovery
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@@ -46,7 +46,7 @@ def hc2mqtt(
|
|||||||
mqtt_clientname: str,
|
mqtt_clientname: str,
|
||||||
domain_suffix: str,
|
domain_suffix: str,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
ha_discovery: bool
|
ha_discovery: bool,
|
||||||
):
|
):
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
def on_connect(client, userdata, flags, rc):
|
||||||
|
|||||||
Reference in New Issue
Block a user