tydom2MQTT addon :D - Delta Dore Tydom to MQTT Broker

Hello guys! @WiwiWillou I made some modification to take into account device_id and endpoint_id in covers. Here is the patch i made:

From 476db1afd56cb07d794fb8d0d296f1ec8bda7485 Mon Sep 17 00:00:00 2001
From: Max013
Date: Wed, 8 Apr 2020 13:57:49 +0200
Subject: [PATCH] Add endpoint_id and device_id in cover instead of id

---
 cover.py               | 51 ++++++++++++++++++++++--------------------
 forever.py             |  4 ++--
 mqtt_client.py         | 10 +++++++--
 tydomMessagehandler.py | 26 ++++++++++++---------
 tydom_websocket.py     |  8 +++----
 5 files changed, 57 insertions(+), 42 deletions(-)

diff --git a/cover.py b/cover.py
index 97c875c..3f96d9a 100644
--- a/cover.py
+++ b/cover.py
@@ -3,11 +3,11 @@ import time
 from datetime import datetime
 from sensors import sensor
 
-cover_command_topic = "cover/tydom/{id}/set_positionCmd"
-cover_config_topic = "homeassistant/cover/tydom/{id}/config"
-cover_position_topic = "cover/tydom/{id}/current_position"
-cover_set_postion_topic = "cover/tydom/{id}/set_position"
-cover_attributes_topic = "cover/tydom/{id}/attributes"
+cover_command_topic = "cover/tydom/{device_id}_{endpoint_id}/set_positionCmd"
+cover_config_topic = "homeassistant/cover/tydom/{device_id}_{endpoint_id}/config"
+cover_position_topic = "cover/tydom/{device_id}_{endpoint_id}/current_position"
+cover_set_postion_topic = "cover/tydom/{device_id}_{endpoint_id}/set_position"
+cover_attributes_topic = "cover/tydom/{device_id}_{endpoint_id}/attributes"
 
 
 class Cover:
@@ -15,7 +15,8 @@ class Cover:
         
         self.attributes = tydom_attributes
 
-        self.id = self.attributes['id']
+        self.device_id = self.attributes['device_id']
+        self.endpoint_id = self.attributes['endpoint_id']
         self.name = self.attributes['cover_name']
         self.current_position = self.attributes['position']
         self.set_position = set_position
@@ -41,17 +42,19 @@ class Cover:
         self.device['manufacturer'] = 'Delta Dore'
         self.device['model'] = 'Volet'
         self.device['name'] = self.name
-        self.device['identifiers'] = self.id
+        self.device['identifiers'] = self.device_id
 
-        self.config_topic = cover_config_topic.format(id=self.id)
+        self.config_topic = cover_config_topic.format(device_id=self.device_id, endpoint_id=self.endpoint_id)
         self.config = {}
         self.config['name'] = self.name
-        self.config['unique_id'] = self.id
+        self.config['unique_id'] = self.device_id
+        self.config['device_id'] = self.device_id
+        self.config['endpoint_id'] = self.endpoint_id
         # self.config['attributes'] = self.attributes
-        self.config['command_topic'] = cover_command_topic.format(id=self.id)
-        self.config['set_position_topic'] = cover_set_postion_topic.format(id=self.id)
-        self.config['position_topic'] = cover_position_topic.format(id=self.id)
-        self.config['json_attributes_topic'] = cover_attributes_topic.format(id=self.id)
+        self.config['command_topic'] = cover_command_topic.format(device_id=self.device_id, endpoint_id=self.endpoint_id)
+        self.config['set_position_topic'] = cover_set_postion_topic.format(device_id=self.device_id, endpoint_id=self.endpoint_id)
+        self.config['position_topic'] = cover_position_topic.format(device_id=self.device_id, endpoint_id=self.endpoint_id)
+        self.config['json_attributes_topic'] = cover_attributes_topic.format(device_id=self.device_id, endpoint_id=self.endpoint_id)
 
         self.config['payload_open'] = "UP"
         self.config['payload_close'] = "DOWN"
@@ -75,13 +78,13 @@ class Cover:
             print(e)
 
 
-        self.position_topic = cover_position_topic.format(id=self.id, current_position=self.current_position)
+        self.position_topic = cover_position_topic.format(device_id=self.device_id, endpoint_id=self.endpoint_id, current_position=self.current_position)
         
         if (self.mqtt != None):
             self.mqtt.mqtt_client.publish(self.position_topic, self.current_position, qos=0, retain=True)
             # self.mqtt.mqtt_client.publish('homeassistant/sensor/tydom/last_update', str(datetime.fromtimestamp(time.time())), qos=1, retain=True)
             self.mqtt.mqtt_client.publish(self.config['json_attributes_topic'], self.attributes, qos=0)
-        print("Cover created / updated : ", self.name, self.id, self.current_position)
+        print("Cover created / updated : ", self.name, self.device_id, self.current_position)
 
         # update_pub = '(self.position_topic, self.current_position, qos=0, retain=True)'
         # return(update_pub)
@@ -92,7 +95,7 @@ class Cover:
         for i, j in self.attributes.items():
             # sensor_name = "tydom_alarm_sensor_"+i
             # print("name "+sensor_name, "elem_name "+i, "attributes_topic_from_device ",self.config['json_attributes_topic'], "mqtt",self.mqtt)
-            if not i == 'device_type' or not i == 'id':
+            if not i == 'device_type' or not i == 'device_id':
                 new_sensor = None
                 new_sensor = sensor(elem_name=i, tydom_attributes_payload=self.attributes, attributes_topic_from_device=self.config['json_attributes_topic'], mqtt=self.mqtt)
                 await new_sensor.update()
@@ -103,24 +106,24 @@ class Cover:
 
 
 
-    async def put_position(tydom_client, cover_id, position):
-        print(cover_id, 'position', position)
+    async def put_position(tydom_client, device_id, endpoint_id, position):
+        print(device_id, endpoint_id, 'position', position)
         if not tydom_client.connection.open:
             print('MQTT req : Websocket not opened, reconnect...')
             await tydom_client.connect()
-            await tydom_client.put_devices_data(cover_id, 'position', position)
+            await tydom_client.put_devices_data(device_id, endpoint_id, 'position', position)
 
         else:
             if not (position == ''):
-                await tydom_client.put_devices_data(cover_id, 'position', position)
+                await tydom_client.put_devices_data(device_id, endpoint_id, 'position', position)
 
-    async def put_positionCmd(tydom_client, cover_id, positionCmd):
-        print(cover_id, 'positionCmd', positionCmd)
+    async def put_positionCmd(tydom_client, device_id, endpoint_id, positionCmd):
+        print(device_id, endpoint_id, 'positionCmd', positionCmd)
         if not tydom_client.connection.open:
             print('MQTT req : Websocket not opened, reconnect...')
             await tydom_client.connect()
-            await tydom_client.put_devices_data(cover_id, 'positionCmd', positionCmd)
+            await tydom_client.put_devices_data(device_id, endpoint_id, 'positionCmd', positionCmd)
 
         else:
             if not (positionCmd == ''):
-                await tydom_client.put_devices_data(cover_id, 'positionCmd', positionCmd)
+                await tydom_client.put_devices_data(device_id, endpoint_id, 'positionCmd', positionCmd)
diff --git a/forever.py b/forever.py
index abc45dd..5fba71e 100644
--- a/forever.py
+++ b/forever.py
@@ -6,8 +6,8 @@ import sys
 filename = sys.argv[1]
 while True:
     print("\nStarting " + filename)
-    p = Popen("python3 " + filename, shell=True)
+    p = Popen("python3 -u " + filename, shell=True)
     p.wait()
 
 
-    #thanks https://ep.gnt.md/index.php/how-to-restart-python-script-after-exception-and-run-it-forever/
\ No newline at end of file
+    #thanks https://ep.gnt.md/index.php/how-to-restart-python-script-after-exception-and-run-it-forever/
diff --git a/mqtt_client.py b/mqtt_client.py
index 27be75c..df0bde7 100644
--- a/mqtt_client.py
+++ b/mqtt_client.py
@@ -111,7 +111,10 @@ class MQTT_Hassio():
             value = str(payload).strip('b').strip("'")
             get_id = (topic.split("/"))[2] #extract id from mqtt
             print(str(get_id), 'positionCmd', value)
-            await Cover.put_positionCmd(tydom_client=self.tydom, cover_id=get_id, positionCmd=str(value))
+            get_id = get_id.split("_")
+            device_id = get_id[0]
+            endpoint_id = get_id[1]
+            await Cover.put_positionCmd(tydom_client=self.tydom, device_id=device_id, endpoint_id=endpoint_id, positionCmd=str(value))
 
         elif ('set_position' in str(topic)) and not ('set_positionCmd'in str(topic)):
             
@@ -119,7 +122,10 @@ class MQTT_Hassio():
             value = json.loads(payload)
             print(value)
             get_id = (topic.split("/"))[2] #extract id from mqtt
-            await Cover.put_position(tydom_client=self.tydom, cover_id=get_id, position=str(value))
+            get_id = get_id.split("_")
+            device_id = get_id[0]
+            endpoint_id = get_id[1]
+            await Cover.put_position(tydom_client=self.tydom, device_id=device_id, endpoint_id=endpoint_id, position=str(value))
 
 
 
diff --git a/tydomMessagehandler.py b/tydomMessagehandler.py
index 3434fbf..7149080 100644
--- a/tydomMessagehandler.py
+++ b/tydomMessagehandler.py
@@ -17,7 +17,8 @@ deviceCoverKeywords = ['position','onFavPos','thermicDefect','obstacleDefect','i
 deviceCoverDetailsKeywords = ['onFavPos','thermicDefect','obstacleDefect','intrusion','battDefect']
 
 # Device dict for parsing
-device_dict = dict()
+device_name = dict()
+device_endpoint = dict()
 
 climateKeywords = ['temperature', 'authorization', 'hvacMode', 'setpoint']
 
@@ -201,12 +202,13 @@ class TydomMessageHandler():
             # Get list of shutter
             if i["last_usage"] == 'shutter':
                 # print('{} {}'.format(i["id_endpoint"],i["name"]))
-                # device_dict[i["id_endpoint"]] = i["name"]
-                device_dict[i["id_device"]] = i["name"]
+                # device_name[i["id_endpoint"]] = i["name"]
+                device_name[i["id_device"]] = i["name"]
+                device_endpoint[i["id_device"]] = i["id_endpoint"]
                 # TODO get other device type
             if i["last_usage"] == 'alarm':
                 # print('{} {}'.format(i["id_endpoint"], i["name"]))
-                device_dict[i["id_endpoint"]] = "Tyxal Alarm"
+                device_name[i["id_endpoint"]] = "Tyxal Alarm"
         print('Configuration updated')
         
     async def parse_devices_data(self, parsed):
@@ -221,13 +223,14 @@ class TydomMessageHandler():
                     for elem in i["endpoints"][0]["data"]:
                         
                         endpoint_id = None
+                        device_id = None
                         elementName = None
                         elementValue = None
                         elementValidity = None
 
                         # Get full name of this id
                         # endpoint_id = i["endpoints"][0]["id"]
-                        endpoint_id = i["id"] # thanks @azrod
+                        device_id = i["id"] # thanks @azrod
                         # Element name
                         elementName = elem["name"]
                         # Element value
@@ -249,13 +252,16 @@ class TydomMessageHandler():
                             # */
                             #TODO : Sensors with everything
                             print_id = None
-                            name_of_id = self.get_name_from_id(endpoint_id)
+                            name_of_id = self.get_name_from_id(device_id)
                             if len(name_of_id) != 0:
                                 print_id = name_of_id
+                                endpoint_id = device_endpoint[device_id]
                             else:
-                                print_id = endpoint_id
+                                print_id = device_id
+                                endpoint_id = device_id
 
-                            attr_cover['id'] = i["id"]
+                            attr_cover['device_id'] = device_id
+                            attr_cover['endpoint_id'] = endpoint_id
                             attr_cover['cover_name'] = print_id
                             attr_cover['name'] = print_id
                             attr_cover['device_type'] = 'cover'
@@ -390,8 +396,8 @@ class TydomMessageHandler():
     # Get pretty name for a device id
     def get_name_from_id(self, id):
         name = ""
-        if len(device_dict) != 0:
-            name = device_dict[id]
+        if len(device_name) != 0:
+            name = device_name[id]
         return(name)
 
 
diff --git a/tydom_websocket.py b/tydom_websocket.py
index d610472..006ef2f 100644
--- a/tydom_websocket.py
+++ b/tydom_websocket.py
@@ -216,7 +216,7 @@ class TydomWebSocketClient():
         return 0
 
     # Give order (name + value) to endpoint
-    async def put_devices_data(self, endpoint_id, name, value):
+    async def put_devices_data(self, device_id, endpoint_id, name, value):
         if not self.connection.open:
 
             print('Connection closed on PUT trial, exiting to ensure restart....')
@@ -227,7 +227,7 @@ class TydomWebSocketClient():
         # For shutter, value is the percentage of closing
         body="[{\"name\":\"" + name + "\",\"value\":\""+ value + "\"}]"
         # endpoint_id is the endpoint = the device (shutter in this case) to open.
-        str_request = self.cmd_prefix + "PUT /devices/{}/endpoints/{}/data HTTP/1.1\r\nContent-Length: ".format(str(endpoint_id),str(endpoint_id))+str(len(body))+"\r\nContent-Type: application/json; charset=UTF-8\r\nTransac-Id: 0\r\n\r\n"+body+"\r\n\r\n"
+        str_request = self.cmd_prefix + "PUT /devices/{}/endpoints/{}/data HTTP/1.1\r\nContent-Length: ".format(str(device_id),str(endpoint_id))+str(len(body))+"\r\nContent-Type: application/json; charset=UTF-8\r\nTransac-Id: 0\r\n\r\n"+body+"\r\n\r\n"
         a_bytes = bytes(str_request, "ascii")
         print(a_bytes)
         await self.connection.send(a_bytes)
@@ -384,9 +384,9 @@ class TydomWebSocketClient():
         await self.get_devices_data()
 
     # Give order to endpoint
-    async def get_device_data(self, id):
+    async def get_device_data(self, device_id, endpoint_id):
         # 10 here is the endpoint = the device (shutter in this case) to open.
-        str_request = self.cmd_prefix + "GET /devices/{}/endpoints/{}/data HTTP/1.1\r\nContent-Length: 0\r\nContent-Type: application/json; charset=UTF-8\r\nTransac-Id: 0\r\n\r\n".format(str(id),str(id))
+        str_request = self.cmd_prefix + "GET /devices/{}/endpoints/{}/data HTTP/1.1\r\nContent-Length: 0\r\nContent-Type: application/json; charset=UTF-8\r\nTransac-Id: 0\r\n\r\n".format(str(device_id),str(endpoint_id))
         a_bytes = bytes(str_request, "ascii")
         await self.connection.send(a_bytes)
         # name = await websocket.recv()
-- 
2.25.1.windows.1