From afd09cddbc183cb34249d2db2ba5ba6f555ddee9 Mon Sep 17 00:00:00 2001 From: SebClem Date: Sat, 12 Mar 2022 22:06:40 +0100 Subject: [PATCH] :hammer: Add missing files --- .idea/git_toolbox_prj.xml | 15 ++++ .idea/misc.xml | 2 +- .idea/screen_status_to_mqtt.iml | 6 +- app_path.py | 3 + mqtt_client.py | 155 ++++++++++++++++++++++++++++++++ 5 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 app_path.py create mode 100644 mqtt_client.py diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index dc9ea49..30ac528 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/screen_status_to_mqtt.iml b/.idea/screen_status_to_mqtt.iml index d0876a7..9ecb3a7 100644 --- a/.idea/screen_status_to_mqtt.iml +++ b/.idea/screen_status_to_mqtt.iml @@ -1,8 +1,10 @@ - - + + + + \ No newline at end of file diff --git a/app_path.py b/app_path.py new file mode 100644 index 0000000..400da95 --- /dev/null +++ b/app_path.py @@ -0,0 +1,3 @@ +base_pash = 'C:/Program Files/ScreenStatusToMQTT/' +log_path = base_pash + "service.log" +config_path = base_pash + "config.yml" diff --git a/mqtt_client.py b/mqtt_client.py new file mode 100644 index 0000000..0188da9 --- /dev/null +++ b/mqtt_client.py @@ -0,0 +1,155 @@ +import json +import logging +import socket +import subprocess +import sys +from os import path +from time import sleep + +import paho.mqtt.client as mqtt +import yaml +from yaml import SafeLoader + +import app_path + +logger = logging.getLogger("MqttClient") + +configLocation = app_path.config_path + +ha_objects = [ + { + "component": "sensor", + "unique_id": "display", + "name": "Display", + "category": "diagnostic", + "icon": "mdi:monitor-shimmer", + "additional_data": None, + "init_payload": "On" + }, + { + "component": "binary_sensor", + "unique_id": "monitor", + "name": "Monitor", + "category": "diagnostic", + "icon": "mdi:monitor", + "additional_data": None, + "init_payload": "ON" + } +] + + +class MqttClient: + prefix = None + discovery_prefix = None + device_name = None + device_id = None + host = None + port = None + username = None + password = None + + def __init__(self, client_name) -> None: + super().__init__() + self.client = mqtt.Client(client_name) + self.client.enable_logger(logging.getLogger("MqttLib")) + self.client.user_data_set({"self": self}) + + def init_connection(self): + if not path.exists(app_path.config_path): + self._generate_default_conf() + self._load_conf() + self.client.username_pw_set(self.username, self.password) + self.client.connect(self.host, port=self.port) + self.client.on_connect = MqttClient.__on_connect + self.client.loop_start() + + def disconnect(self): + message = self.client.publish(f"{self.prefix}/mqtt", payload="offline") + message.wait_for_publish(timeout=10) + self.client.disconnect() + + def publish_status(self, sensor, payload): + return self.client.publish(f"{self.prefix}/{sensor}/state", payload=payload) + + def _publish_home_assistant_discovery(self): + for ha_object in ha_objects: + self._send_discovery_payload_for(ha_object["component"], ha_object["unique_id"], ha_object["name"], + + ha_object["category"], ha_object["icon"], ha_object["additional_data"]) + + def _publish_init_payload(self): + for ha_object in ha_objects: + self.publish_status(ha_object["unique_id"], ha_object["init_payload"]) + + @staticmethod + def __on_connect(client, userdata, flag, rc): + logger.info("Connected to MQTT: " + mqtt.connack_string(rc)) + self: MqttClient = userdata['self'] + client.publish(f"{self.prefix}/mqtt", payload="online") + self._publish_init_payload() + self._publish_home_assistant_discovery() + self._publish_init_payload() + + def _send_discovery_payload_for(self, component, unique_id, name, category, icon, additional_data=None): + topic = f"{self.discovery_prefix}/{component}/{self.device_id}/{self.device_id}_sensor_{unique_id}/config" + safe_name = self.device_name.lower().replace(' ', '_').encode('ascii', "ignore").decode() + payload = { + "state_topic": f"{self.prefix}/{unique_id}/state", + "availability": { + "topic": f"{self.prefix}/mqtt" + }, + "device": { + "identifiers": [ + self.device_id + ], + "name": self.device_name + }, + "entity_category": category, + "icon": icon, + "name": name, + "unique_id": self.device_id + "_" + unique_id, + "object_id": safe_name + "_" + unique_id + } + if additional_data: + payload.update(additional_data) + + self.client.publish(topic, json.dumps(payload)) + + def _generate_default_conf(self): + logger.warning("Generate default conf") + current_machine_id = subprocess.check_output('wmic csproduct get uuid').split()[1].decode("utf-8") + default = { + "mqtt_host": "exemple.local", + "mqtt_port": 1883, + "mqtt_username": "username", + "mqtt_password": "password", + "mqtt_prefix": socket.gethostname(), + "discovery_prefix": "homeassistant", + "device_name": socket.gethostname(), + "device_id": current_machine_id + } + + with open(app_path.config_path, "w") as stream: + yaml.dump(default, stream) + + def _load_conf(self): + with open(app_path.config_path, "r") as stream: + conf = yaml.load(stream, Loader=SafeLoader) + keys = ["mqtt_host", "mqtt_username", "mqtt_password"] + + if all(key in conf for key in keys): + current_machine_id = subprocess.check_output('wmic csproduct get uuid').split()[1].decode("utf-8") + self.prefix = conf.get("mqtt_prefix", "screen_status") + self.discovery_prefix = conf.get("discovery_prefix", "homeassistant") + self.device_name = conf.get("device_name", socket.gethostname()) + self.device_id = conf.get("device_id", current_machine_id) + self.host = conf.get("mqtt_host") + self.port = conf.get("mqtt_port", 1883) + self.username = conf.get("mqtt_username") + self.password = conf.get("mqtt_password") + + else: + logger.critical("CONFIG FILE INVALID.") + logger.critical("Delete the config file dans restart the service if you want to restore the default " + "config.") + sys.exit(1)