diff --git a/config.schema.yml b/config.schema.yml index 08754333fae2b8a461e25e865da655b4890781f9..6170543ba12758ed461cd57f77c4ef59ecdde941 100644 --- a/config.schema.yml +++ b/config.schema.yml @@ -55,6 +55,15 @@ mqtt: type: string required: no default: dead + discovery: + type: boolean + required: no + default: no + discovery_prefix: + type: string + required: no + default: "homeassistant" + coerce: rstrip_slash tls: type: dict required: no diff --git a/pi_mqtt_gpio/__init__.py b/pi_mqtt_gpio/__init__.py index 05f7f2da3d1573c16285517ea6e9d58154519048..4f9b174522ca54e0f0dfc6cae8f5fe6523d0828b 100644 --- a/pi_mqtt_gpio/__init__.py +++ b/pi_mqtt_gpio/__init__.py @@ -58,6 +58,15 @@ mqtt: type: string required: no default: dead + discovery: + type: boolean + required: no + default: no + discovery_prefix: + type: string + required: no + default: "homeassistant" + coerce: rstrip_slash tls: type: dict required: no diff --git a/pi_mqtt_gpio/server.py b/pi_mqtt_gpio/server.py index 9767c9b63e33ffda13a024f82bfa089e25b0600e..bdc5c8ad92f3d705534ac46a551898a35c1cc107 100644 --- a/pi_mqtt_gpio/server.py +++ b/pi_mqtt_gpio/server.py @@ -1,4 +1,5 @@ import argparse +import json import logging import logging.config import yaml @@ -357,6 +358,12 @@ def init_mqtt(config, digital_outputs): client.publish( status_topic, config["status_payload_running"], qos=1, retain=True ) + # HASS + if config["discovery"]: + for in_conf in digital_inputs: + hass_announce_digital_input(in_conf, topic_prefix, config) + for out_conf in digital_outputs: + hass_announce_digital_output(out_conf, topic_prefix, config) elif rc == 1: _LOG.fatal("Incorrect protocol version used to connect to MQTT broker.") sys.exit(1) @@ -641,7 +648,75 @@ def gpio_interrupt_callback(module, pin): ) +def hass_announce_digital_input(in_conf, topic_prefix, mqtt_config): + """ + Announces digital input as binary_sensor to HomeAssistant. + :param in_conf: Input config + :type in_conf: dict + :return: None + :rtype: NoneType + """ + device_id = "pi-mqtt-gpio-%s" % sha1(topic_prefix.encode("utf8")).hexdigest()[:8] # TODO: Unify with MQTT Client ID + sensor_name = in_conf["name"] + sensor_config = { + "name": sensor_name, + "unique_id": "%s_%s_input_%s" % (device_id, in_conf["module"], sensor_name), + "state_topic": "%s/%s/%s" % (topic_prefix, INPUT_TOPIC, in_conf["name"]), + "availability_topic": "%s/%s" % (topic_prefix, mqtt_config["status_topic"]), + "payload_available": mqtt_config["status_payload_running"], + "payload_not_available": mqtt_config["status_payload_dead"], + "payload_on": in_conf["on_payload"], + "payload_off": in_conf["off_payload"], + "device": { + "manufacturer": "MQTT GPIO", + "identifiers": ["mqtt-gpio", device_id], + "name": "MQTT GPIO" + } + } + + client.publish( + "%s/%s/%s/%s/config" % (mqtt_config["discovery_prefix"], "binary_sensor", device_id, sensor_name), + payload=json.dumps(sensor_config), + retain=True, + ) + + +def hass_announce_digital_output(out_conf, topic_prefix, mqtt_config): + """ + Announces digital output as switch to HomeAssistant. + :param out_conf: Output config + :type out_conf: dict + :return: None + :rtype: NoneType + """ + device_id = "pi-mqtt-gpio-%s" % sha1(topic_prefix.encode("utf8")).hexdigest()[:8] # TODO: Unify with MQTT Client ID + sensor_name = out_conf["name"] + sensor_config = { + "name": sensor_name, + "unique_id": "%s_%s_output_%s" % (device_id, out_conf["module"], sensor_name), + "state_topic": "%s/%s/%s" % (topic_prefix, OUTPUT_TOPIC, out_conf["name"]), + "command_topic": "%s/%s/%s/%s" % (topic_prefix, OUTPUT_TOPIC, out_conf["name"], SET_TOPIC), + "availability_topic": "%s/%s" % (topic_prefix, mqtt_config["status_topic"]), + "payload_available": mqtt_config["status_payload_running"], + "payload_not_available": mqtt_config["status_payload_dead"], + "payload_on": out_conf["on_payload"], + "payload_off": out_conf["off_payload"], + "device": { + "manufacturer": "MQTT GPIO", + "identifiers": ["mqtt-gpio", device_id], + "name": "MQTT GPIO" + } + } + + client.publish( + "%s/%s/%s/%s/config" % (mqtt_config["discovery_prefix"], "switch", device_id, sensor_name), + payload=json.dumps(sensor_config), + retain=True, + ) + + def main(args): + global digital_inputs global digital_outputs global client global scheduler @@ -667,6 +742,7 @@ def main(args): sensor_inputs = config["sensor_inputs"] client = init_mqtt(config["mqtt"], config["digital_outputs"]) + topic_prefix = config["mqtt"]["topic_prefix"] # Install modules for GPIOs for gpio_config in config["gpio_modules"]: @@ -729,7 +805,6 @@ def main(args): scheduler = Scheduler() - topic_prefix = config["mqtt"]["topic_prefix"] try: # Starting the sensor thread (if there are sensors configured) if sensor_inputs: