Start publishing HA auto-discovery information.
This commit is contained in:
66
HADiscovery.py
Normal file
66
HADiscovery.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import json
|
||||||
|
import re
|
||||||
|
|
||||||
|
from HCSocket import now
|
||||||
|
|
||||||
|
|
||||||
|
def decamelcase(str):
|
||||||
|
split = re.findall(r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))', str)
|
||||||
|
return f"{split[0]} {' '.join(split[1:]).lower()}".strip()
|
||||||
|
|
||||||
|
|
||||||
|
HA_DISCOVERY_PREFIX = "homeassistant"
|
||||||
|
|
||||||
|
|
||||||
|
def publish_ha_states(state, client, mqtt_topic):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def publish_ha_discovery(device, client, mqtt_topic):
|
||||||
|
print(f"{now()} Publishing HA discovery for {device}")
|
||||||
|
|
||||||
|
device_ident = device["host"]
|
||||||
|
device_name = device["name"]
|
||||||
|
device_description = device.get("description", {})
|
||||||
|
|
||||||
|
version_parts = filter(
|
||||||
|
lambda d : d is not None,
|
||||||
|
[
|
||||||
|
device_description.get("version"),
|
||||||
|
device_description.get("revision")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
device_info = {
|
||||||
|
"identifiers": [device_ident],
|
||||||
|
"name": device_name,
|
||||||
|
"manufacturer": device_description.get("brand"),
|
||||||
|
"model": device_description.get("model"),
|
||||||
|
"sw_version": ".".join(version_parts)
|
||||||
|
}
|
||||||
|
|
||||||
|
for feature in device["features"].values():
|
||||||
|
access = feature.get("access", "none")
|
||||||
|
available = feature.get("available", False)
|
||||||
|
if available and (access == "read" or access == "readWrite"):
|
||||||
|
name_parts = feature["name"].split(".")
|
||||||
|
name = name_parts[-1]
|
||||||
|
feature_type = name_parts[-2]
|
||||||
|
|
||||||
|
component_type = "sensor" # TODO use appropriate types
|
||||||
|
|
||||||
|
discovery_topic = f"{HA_DISCOVERY_PREFIX}/{component_type}/hcpy/{device_ident}_{name}/config"
|
||||||
|
state_topic = f"{mqtt_topic}/{feature_type}/{name}"
|
||||||
|
# print(discovery_topic, state_topic)
|
||||||
|
|
||||||
|
discovery_payload = json.dumps({
|
||||||
|
"name": decamelcase(name),
|
||||||
|
"device": device_info,
|
||||||
|
"state_topic": state_topic,
|
||||||
|
"object_id": f"{device_ident}_{name}",
|
||||||
|
"unique_id": f"{device_ident}_{name}",
|
||||||
|
})
|
||||||
|
print(discovery_topic)
|
||||||
|
# print(discovery_payload)
|
||||||
|
|
||||||
|
client.publish(discovery_topic, discovery_payload, retain=False) # TODO make retain=True when stable
|
||||||
15
hc2mqtt.py
15
hc2mqtt.py
@@ -13,6 +13,7 @@ import paho.mqtt.client as mqtt
|
|||||||
|
|
||||||
from HCDevice import HCDevice
|
from HCDevice import HCDevice
|
||||||
from HCSocket import HCSocket, now
|
from HCSocket import HCSocket, now
|
||||||
|
from HADiscovery import publish_ha_states, publish_ha_discovery
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@@ -29,6 +30,7 @@ from HCSocket import HCSocket, now
|
|||||||
@click.option("--mqtt_clientname", default="hcpy1")
|
@click.option("--mqtt_clientname", default="hcpy1")
|
||||||
@click.option("--domain_suffix", default="")
|
@click.option("--domain_suffix", default="")
|
||||||
@click.option("--debug/--no-debug", default=False)
|
@click.option("--debug/--no-debug", default=False)
|
||||||
|
@click.option("--ha-discovery", is_flag=True)
|
||||||
@click_config_file.configuration_option()
|
@click_config_file.configuration_option()
|
||||||
def hc2mqtt(
|
def hc2mqtt(
|
||||||
devices_file: str,
|
devices_file: str,
|
||||||
@@ -44,6 +46,7 @@ def hc2mqtt(
|
|||||||
mqtt_clientname: str,
|
mqtt_clientname: str,
|
||||||
domain_suffix: str,
|
domain_suffix: str,
|
||||||
debug: bool,
|
debug: bool,
|
||||||
|
ha_discovery: bool
|
||||||
):
|
):
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
def on_connect(client, userdata, flags, rc):
|
||||||
@@ -74,6 +77,8 @@ def hc2mqtt(
|
|||||||
now(), device["name"], f"program topic: {mqtt_selected_program_topic}"
|
now(), device["name"], f"program topic: {mqtt_selected_program_topic}"
|
||||||
)
|
)
|
||||||
client.subscribe(mqtt_selected_program_topic)
|
client.subscribe(mqtt_selected_program_topic)
|
||||||
|
if ha_discovery:
|
||||||
|
publish_ha_discovery(device, client, mqtt_topic)
|
||||||
else:
|
else:
|
||||||
print(now(), f"ERROR MQTT connection failed: {rc}")
|
print(now(), f"ERROR MQTT connection failed: {rc}")
|
||||||
|
|
||||||
@@ -117,7 +122,7 @@ def hc2mqtt(
|
|||||||
f"Hello {devices_file=} {mqtt_host=} {mqtt_prefix=} "
|
f"Hello {devices_file=} {mqtt_host=} {mqtt_prefix=} "
|
||||||
f"{mqtt_port=} {mqtt_username=} {mqtt_password=} "
|
f"{mqtt_port=} {mqtt_username=} {mqtt_password=} "
|
||||||
f"{mqtt_ssl=} {mqtt_cafile=} {mqtt_certfile=} {mqtt_keyfile=} {mqtt_clientname=}"
|
f"{mqtt_ssl=} {mqtt_cafile=} {mqtt_certfile=} {mqtt_keyfile=} {mqtt_clientname=}"
|
||||||
f"{domain_suffix=} {debug=}"
|
f"{domain_suffix=} {debug=} {ha_discovery=}"
|
||||||
)
|
)
|
||||||
|
|
||||||
with open(devices_file, "r") as f:
|
with open(devices_file, "r") as f:
|
||||||
@@ -146,9 +151,9 @@ def hc2mqtt(
|
|||||||
client.connect(host=mqtt_host, port=mqtt_port, keepalive=70)
|
client.connect(host=mqtt_host, port=mqtt_port, keepalive=70)
|
||||||
|
|
||||||
for device in devices:
|
for device in devices:
|
||||||
mqtt_topic = mqtt_prefix + device["name"]
|
mqtt_topic = mqtt_prefix + device["host"]
|
||||||
thread = Thread(
|
thread = Thread(
|
||||||
target=client_connect, args=(client, device, mqtt_topic, domain_suffix, debug)
|
target=client_connect, args=(client, device, mqtt_topic, domain_suffix, debug, ha_discovery)
|
||||||
)
|
)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
@@ -159,7 +164,7 @@ global dev
|
|||||||
dev = {}
|
dev = {}
|
||||||
|
|
||||||
|
|
||||||
def client_connect(client, device, mqtt_topic, domain_suffix, debug):
|
def client_connect(client, device, mqtt_topic, domain_suffix, debug, ha_discovery):
|
||||||
host = device["host"]
|
host = device["host"]
|
||||||
name = device["name"]
|
name = device["name"]
|
||||||
|
|
||||||
@@ -193,6 +198,8 @@ def client_connect(client, device, mqtt_topic, domain_suffix, debug):
|
|||||||
msg = json.dumps(state)
|
msg = json.dumps(state)
|
||||||
print(now(), name, f"publish to {mqtt_topic} with {msg}")
|
print(now(), name, f"publish to {mqtt_topic} with {msg}")
|
||||||
client.publish(f"{mqtt_topic}/state", msg, retain=True)
|
client.publish(f"{mqtt_topic}/state", msg, retain=True)
|
||||||
|
if ha_discovery:
|
||||||
|
publish_ha_states(state, client, mqtt_topic)
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
now(),
|
now(),
|
||||||
|
|||||||
Reference in New Issue
Block a user