class Thermometer_Daemon(IMqttConnector): def __init__(self, topic, location): super().__init__() self.__location = location self.__topic = topic self.__mqtt = MqttClient( self, "homebridge.local", [ self.__topic, ], "Thermometer_Daemon_" + self.__location, ) self.__temperature = 0.0 self.__now = datetime.utcnow().isoformat() self.__packet = "" def Receive(self, server, topic: str, payload: bytes): self.__client = InfluxDBClient("homebridge.local", port=8086) self.__client.switch_database("HomeKit") self.__now = datetime.utcnow().isoformat() print("[MQTT] " + topic) self.__packet = payload.decode("utf-8") print(self.__packet) self.__temperature = float(self.__packet) self.__jsonBody = [ { "measurement": "Environment", "tags": { "Location": self.__location, }, "time": self.__now, "fields": { "Temperature": self.__temperature, }, }, ] self.__client.write_points(self.__jsonBody) self.__client.close() def Send(self, topic, msg): self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("")
class HumiditySensor(IMqttConnector): def __init__(self, ID, topicToPublish): super().__init__() # switch properties self.__uniqueID = ID # packet payload self.__packet = "" self.__RSSI = 0 self.__humidity = 0 # Topics # Set self.__setRelativeHumidity = topicToPublish # Bridge enOcean self.__topicEnocean = "enocean/device/id/{}".format(self.__uniqueID) print("[HumiditySensor] with uniqueID {} opened".format( self.__uniqueID)) # Instanciate MQTT Client self.__mqtt = MqttClient(self, "127.0.0.1", [ self.__topicEnocean, ], "HumiditySensor-" + self.__uniqueID) def Receive(self, server, topic: str, payload: bytes): print("[MQTT] " + topic) self.__packet = payload.decode("utf-8") msg = json.loads(self.__packet) print("[MQTT] " + str(msg['packet'])) self.__humidity = int(str(msg['packet']["data"]["DB2"]), 16) * 100 / 250 self.Send(self.__setRelativeHumidity, str(self.__humidity)) def Send(self, topic, msg): self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("[HumiditySensor] with uniqueID {} closed".format( self.__uniqueID))
class Switch(IMqttConnector): def __init__(self, ID, device, channel="", dimmable=False): super().__init__() # switch properties self.__uniqueID = ID self.__device = device self.__dimmable = dimmable self.__channel = channel self.__deviceStatus = "" self.__dimmerValue: int # packet payload self.__state = "" self.__packet = "" self.__RSSI = 0 self.__timestamp1 = None self.__timestamp2 = None self.__deltaTime = None self.__formatDate = "%d/%m/%y %H:%M:%S.%f" # Topics # Get self.__topicResult = "stat/{}/RESULT".format(self.__device) # Set self.__topicsCmndDeviceDimmer = "cmnd/{}/dimmer".format(self.__device) self.__topicsCmndDevice = "cmnd/{}/power{}".format( self.__device, self.__channel) # Bridge enOcean self.__topicEnocean = "enocean/device/id/{}".format(self.__uniqueID) print("[Switch] with uniqueID {} opened".format(self.__uniqueID)) # Instanciate MQTT Client self.__mqtt = MqttClient(self, "127.0.0.1", [ self.__topicResult, self.__topicEnocean],"Switch-"+self.__uniqueID) self.getStatus() def Receive(self, server, topic: str, payload: bytes): print("[MQTT] " + topic) # RESULT if topic == self.__topicResult: try: dimmerValues = payload.decode("utf-8") msg = json.loads(dimmerValues) self.__dimmerValue = int(msg['Dimmer']) print("[MQTT] Dimmer : " + str(self.__dimmerValue)) except: pass try: deviceStatus = payload.decode("utf-8") msg = json.loads(deviceStatus) # powerChannel = "POWER{}".format(self.__channel) self.__deviceStatus = (msg['POWER{}'.format(self.__channel)]) print("[MQTT] Status : " + str(self.__deviceStatus)) except: pass if topic == self.__topicEnocean: self.__packet = payload.decode("utf-8") msg = json.loads(self.__packet) print("[MQTT] " + str(msg['packet'])) self.__RSSI = int(msg['packet']['optionalData']['dBm'], 16) self.__state = msg['packet']['data']['status'] if self.__state == "30": self.__timestamp1 = datetime.strptime( datetime.now().strftime("%d/%m/%y %H:%M:%S.%f"), self.__formatDate) else: self.__timestamp2 = datetime.strptime( datetime.now().strftime("%d/%m/%y %H:%M:%S.%f"), self.__formatDate) print("[INFO] Button pressed then released !") self.__deltaTime = self.__timestamp2 - self.__timestamp1 if self.__dimmable == True: if self.__dimmerValue == 0: if self.__deltaTime < timedelta(milliseconds=250): print("[INFO] less than 250ms press") self.Send(self.__topicsCmndDeviceDimmer, "25") if timedelta(milliseconds=250) < self.__deltaTime < timedelta(milliseconds=500): print("[INFO] press between 250 & 500ms") self.Send(self.__topicsCmndDeviceDimmer, "50") if timedelta(milliseconds=500) < self.__deltaTime < timedelta(milliseconds=750): print("[INFO] press between 500 & 750ms") self.Send(self.__topicsCmndDeviceDimmer, "75") if self.__deltaTime > timedelta(milliseconds=750): print("[INFO] press longer than 750ms") self.Send(self.__topicsCmndDeviceDimmer, "100") print("[INFO] DeltaTime : " + str(self.__deltaTime)) else: self.Send(self.__topicsCmndDevice, "OFF") self.Send(self.__topicsCmndDeviceDimmer, "0") else: self.invertStatus() def Send(self, topic, msg): self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("[Switch] with uniqueID {} closed".format(self.__uniqueID)) def getStatus(self): self.Send(self.__topicsCmndDevice, "") self.Send(self.__topicsCmndDeviceDimmer, "") def invertStatus(self): if self.__deviceStatus == "ON": self.Send(self.__topicsCmndDevice, "OFF") if self.__deviceStatus == "OFF": self.Send(self.__topicsCmndDevice, "ON")
class ParticuleSensor_Daemon(IMqttConnector): def __init__(self, topic, location): super().__init__() self.__location = location self.__topic = topic self.__mqtt = MqttClient( self, "homebridge.local", [ self.__topic, ], "ParticuleSensor_Daemon" + self.__location, ) self.__PM10 = 0.0 self.__PM2_5 = 0.0 self.__PM1 = 0.0 self.__rawDatas = "" self.__now = datetime.utcnow().isoformat() self.__packet = "" self.__formattedData = [] def rawDatas2PM10(self, H_D3, L_D3): PM10 = (H_D3 * 256) + L_D3 print("PM10 : " + str(PM10) + " ug/m3") self.__PM10 = PM10 def rawDatas2PM2_5(self, H_D2, L_D2): PM2_5 = (H_D2 * 256) + L_D2 print("PM2.5 : " + str(PM2_5) + " ug/m3") self.__PM2_5 = PM2_5 def rawDatas2PM1(self, H_D1, L_D1): PM1 = (H_D1 * 256) + L_D1 print("PM1 : " + str(PM1) + " ug/m3") self.__PM1 = PM1 def checkCS(self, datas): CS = sum() if datas["datas"]["CS"] == CS: return True else: return False def Receive(self, server, topic: str, payload: bytes): self.__client = InfluxDBClient("homebridge.local", port=8086) self.__client.switch_database("HomeKit") self.__now = datetime.utcnow().isoformat() print("[MQTT] " + topic) self.__packet = payload.decode("utf-8") self.__packet = json.loads(self.__packet) self.__bytearrayDatas = bytearray.fromhex( self.__packet["SerialReceived"]) self.__formattedData = [{ "headers": { "Head1": self.__bytearrayDatas[0], "Head2": self.__bytearrayDatas[1], }, "datas": { "H_Lenght": self.__bytearrayDatas[2], "L_Lenght": self.__bytearrayDatas[3], "H_D1": self.__bytearrayDatas[4], "L_D1": self.__bytearrayDatas[5], "H_D2": self.__bytearrayDatas[6], "L_D2": self.__bytearrayDatas[7], "H_D3": self.__bytearrayDatas[8], "L_D3": self.__bytearrayDatas[9], "H_D4": self.__bytearrayDatas[10], "L_D4": self.__bytearrayDatas[11], "H_D5": self.__bytearrayDatas[12], "L_D5": self.__bytearrayDatas[13], "H_D6": self.__bytearrayDatas[14], "L_D6": self.__bytearrayDatas[15], "H_D7": self.__bytearrayDatas[16], "L_D7": self.__bytearrayDatas[17], "H_D8": self.__bytearrayDatas[18], "L_D8": self.__bytearrayDatas[19], "H_D9": self.__bytearrayDatas[20], "L_D9": self.__bytearrayDatas[21], "H_D10": self.__bytearrayDatas[22], "L_D10": self.__bytearrayDatas[23], "H_D11": self.__bytearrayDatas[24], "L_D11": self.__bytearrayDatas[25], "H_D12": self.__bytearrayDatas[26], "L_D12": self.__bytearrayDatas[27], "H_D13": self.__bytearrayDatas[28], "L_D13": self.__bytearrayDatas[29], "H_CS": self.__bytearrayDatas[30], "L_CS": self.__bytearrayDatas[31], }, }] self.rawDatas2PM10( self.__formattedData[0]["datas"]["H_D3"], self.__formattedData[0]["datas"]["L_D3"], ) self.rawDatas2PM2_5( self.__formattedData[0]["datas"]["H_D2"], self.__formattedData[0]["datas"]["L_D2"], ) self.rawDatas2PM1( self.__formattedData[0]["datas"]["H_D1"], self.__formattedData[0]["datas"]["L_D1"], ) self.__jsonBody = [ { "measurement": "Environment", "tags": { "Location": self.__location, }, "time": self.__now, "fields": { "PM10": self.__PM10, "PM2.5": self.__PM2_5, "PM1": self.__PM1, }, }, ] self.__client.write_points(self.__jsonBody) self.__client.close() def Send(self, topic, msg): self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("[{}] closed".format("ParticuleSensor_Daemon" + self.__location))
class QueryParticuleSensor(IMqttConnector): def __init__(self, topic, location): super().__init__() self.__location = location self.__topic = topic self.__mqtt = MqttClient( self, "homebridge.local", [], "QueryParticuleSensor_Daemon" + self.__location, ) self.__queryPM10 = 'SELECT mean("PM10") FROM "Environment" WHERE ("Location" = \'Bedroom\') AND time >= now() - 1h GROUP BY time(15m) LIMIT 1' self.__queryPM2_5 = 'SELECT mean("PM2.5") FROM "Environment" WHERE ("Location" = \'Bedroom\') AND time >= now() - 1h GROUP BY time(15m) LIMIT 1' self.__bind_params = {"location": self.__location} self.__PM10 = 0 self.__PM2_5 = 0 self.__airQualityValues = [ "excellent-value", "good-value", "fair-value", "inferior-value", "poor-value", "unknown-value", ] self.__topicPM10 = "getPM10Density" self.__topicPM2_5 = "getPM2_5Density" self.__topicAirQualityValues = "getAirQuality" def Receive(self, server, topic: str, payload: bytes): print("Receive") def Send(self, topic, msg): print(topic) self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("[{}] closed".format("ParticuleSensor_Daemon" + self.__location)) def queryPM10(self): self.__client = InfluxDBClient("homebridge.local", 8086) self.__client.switch_database("HomeKit") result = self.__client.query(self.__queryPM10, bind_params=self.__bind_params) self.__PM10 = int(result.raw["series"][0]["values"][0][1]) self.__client.close() print("PM10 : " + str(self.__PM10)) self.Send( self.__topic + self.__topicPM10, self.__PM10, ) time.sleep(1) def queryPM2_5(self): self.__client = InfluxDBClient("homebridge.local", 8086) self.__client.switch_database("HomeKit") result = self.__client.query(self.__queryPM2_5, bind_params=self.__bind_params) self.__PM2_5 = int(result.raw["series"][0]["values"][0][1]) self.__client.close() print("PM2.5 : " + str(self.__PM2_5)) self.Send( self.__topic + self.__topicPM2_5, self.__PM2_5, ) time.sleep(1) def sendAirQualityValues(self): if (0 < self.__PM10 and self.__PM10 < 50 and 0 < self.__PM2_5 and self.__PM2_5 < 30): print(self.__airQualityValues[0]) self.Send( self.__topic + self.__topicAirQualityValues, self.__airQualityValues[0], ) else: if (51 < self.__PM10 and self.__PM10 < 100 and 31 < self.__PM2_5 and self.__PM2_5 < 60): print(self.__airQualityValues[1]) self.Send( self.__topic + self.__topicAirQualityValues, self.__airQualityValues[1], ) else: if (101 < self.__PM10 and self.__PM10 < 250 and 61 < self.__PM2_5 and self.__PM2_5 < 90): print(self.__airQualityValues[2]) self.Send( self.__topic + self.__topicAirQualityValues, self.__airQualityValues[2], ) else: if (251 < self.__PM10 and self.__PM10 < 350 and 91 < self.__PM2_5 and self.__PM2_5 < 120): print(self.__airQualityValues[3]) self.Send( self.__topic + self.__topicAirQualityValues, self.__airQualityValues[3], ) else: if (351 < self.__PM10 and self.__PM10 < 430 and 121 < self.__PM2_5 and self.__PM2_5 < 250): print(self.__airQualityValues[4]) self.Send( self.__topic + self.__topicAirQualityValues, self.__airQualityValues[4], ) else: print(self.__airQualityValues[5]) self.Send( self.__topic + self.__topicAirQualityValues, self.__airQualityValues[5], ) time.sleep(1) def halt(self): self.__mqtt.Halt()
class Receiver(Thread, IMqttConnector): def __init__(self, handle): super().__init__() self.__running = True self.__handle: Serial = handle # MQTT self.__mqtt = MqttClient(self, "127.0.0.1", [], "UART") self.__topic = "" # enOcean packet self.__packet = {} self.__rawPacket = [] self.__syncByte = "55" self.__byte = "" self.__uniqueID = "00:00:00:00" self.__dataLength = 0 self.__RORG = "f6" self.start() def Receive(self, server, topic: str, payload: bytes): pass def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Send(self, topics, msg): if msg[6] == "f6": jsonMsg = { 'packet': { 'header': { 'syncByte': msg[0], 'dataLength': msg[1] + msg[2], 'optionalDataLength': msg[3], 'packetType': msg[4], 'CRC8H': msg[5] }, 'data': { 'RORG': msg[6], 'data': msg[7], 'senderID': msg[8] + msg[9] + msg[10] + msg[11], 'status': msg[12] }, 'optionalData': { 'subTelNum': msg[13], 'destinationID': msg[14] + msg[15] + msg[16] + msg[17], 'dBm': msg[18], 'securityLevel': msg[19], 'CRC8D': msg[20] } } } if msg[6] == "a5": jsonMsg = { 'packet': { 'header': { 'syncByte': msg[0], 'dataLength': msg[1] + msg[2], 'optionalDataLength': msg[3], 'packetType': msg[4], 'CRC8H': msg[5] }, 'data': { 'RORG': msg[6], 'DB3': msg[7], 'DB2': msg[8], 'DB1': msg[9], 'DB0': msg[10], 'senderID': msg[11] + msg[12] + msg[13] + msg[14], 'status': msg[15] }, 'optionalData': { 'subTelNum': msg[16], 'destinationID': msg[17] + msg[18] + msg[19] + msg[20], 'dBm': msg[21], 'securityLevel': msg[22], 'CRC8D': msg[23] } } } # print(jsonMsg) jsonMsg = json.dumps(jsonMsg) self.__mqtt.sendMessage(self.__topic, jsonMsg) def run(self) -> None: while self.__running: self.__byte = (self.__handle.read(1).hex()) # Check for SyncByte if self.__byte == self.__syncByte: # Start saving packet with sync byte self.__rawPacket.append(self.__byte) # Add the header of the packet for x in range(0, 5): self.__rawPacket.append(self.__handle.read(1).hex()) self.__dataLength = int( self.__rawPacket[1] + self.__rawPacket[2], 16) for x in range(0, self.__dataLength): self.__rawPacket.append(self.__handle.read(1).hex()) self.__RORG = self.__rawPacket[6] for x in range(0, 8): self.__rawPacket.append(self.__handle.read(1).hex()) # Extract uniqueID for packet if self.__RORG == "f6": self.__uniqueID = self.__rawPacket[8] self.__uniqueID += self.__rawPacket[9] self.__uniqueID += self.__rawPacket[10] self.__uniqueID += self.__rawPacket[11] if self.__RORG == "a5": self.__uniqueID = self.__rawPacket[11] self.__uniqueID += self.__rawPacket[12] self.__uniqueID += self.__rawPacket[13] self.__uniqueID += self.__rawPacket[14] print("[UART] Receiving enOcean packet from : " + self.__uniqueID) self.__topic = "enocean/device/id/{}".format( self.__uniqueID) # Send packet to topics with uniqueID self.Send(self.__topic, self.__rawPacket) self.__rawPacket.clear() def Stop(self): print("[UART] Serial line closed") self.__running = False self.__handle.cancel_read()
class GasSensor_Daemon(IMqttConnector): def __init__(self, topic, location): super().__init__() self.__location = location self.__topic = topic self.__TVOC = 0 self.__eCO2 = 0 self.__mqtt = MqttClient( self, "homebridge.local", [ self.__topic, ], "GasSensor_Daemon-" + self.__location, ) self.__now = datetime.utcnow().isoformat() self.__packet = "" def Receive(self, server, topic: str, payload: bytes): self.__client = InfluxDBClient("homebridge.local", port=8086) self.__client.switch_database("HomeKit") self.__now = datetime.utcnow().isoformat() print("[MQTT] " + topic) self.__packet = payload.decode("utf-8") print(self.__packet) data = json.loads(self.__packet) print(data) self.__TVOC = data["CCS811"]["TVOC"] self.__eCO2 = data["CCS811"]["eCO2"] self.__jsonBody = [ { "measurement": "Environment", "tags": { "Location": self.__location, }, "time": self.__now, "fields": { "eCO2": self.__eCO2, "TVOC": self.__TVOC }, }, ] print(self.__jsonBody) self.__client.write_points(self.__jsonBody) self.__client.close() def Send(self, topic, msg): self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("[{}] closed".format("GasSensor_Daemon-" + self.__location))
class Switch(IMqttConnector): def __init__(self, enOceanID, deviceProperties: dict): super().__init__() # switch properties self.__enOceanID = enOceanID self.__deviceProperties = deviceProperties self.__topicDevices = {} self.__dimmerValue = 0 self.__channel = "" self.__enOceanTopic = "enocean/device/id/{}".format(self.__enOceanID) self.__timestamp1 = None self.__timestamp2 = None self.__deltaTime = None self.__formatDate = "%d/%m/%y %H:%M:%S.%f" self.createDictOfTopics(self.__deviceProperties) print("[Switch] with uniqueID {} opened".format(self.__enOceanID)) # Instanciate MQTT Client self.__mqtt = MqttClient(self, "127.0.0.1", [ self.__enOceanTopic, self.__topicDevices], "Switch-"+self.__enOceanID) def createDictOfTopics(self, deviceProperties): for x in self.__deviceProperties["device"]: powerTopics = "cmnd/{}/power{}".format( self.__deviceProperties["device"][x]["MQTTName"], self.__deviceProperties["device"][x]["channel"]) if self.__deviceProperties["device"][x]["dimmable"] == True: dimmerTopics = "cmnd/{}/dimmer".format( self.__deviceProperties["device"][x]["MQTTName"]) self.__topicDevices[str(x)] = { "power": powerTopics, "dimmer": dimmerTopics} else: self.__topicDevices[str(x)] = { "power": powerTopics} def sendBrightness(self, topics): print(topics) if self.__deltaTime < timedelta(milliseconds=250): print("[INFO] less than 250ms press") self.Send(topics, "25") if timedelta(milliseconds=250) < self.__deltaTime < timedelta(milliseconds=500): print("[INFO] press between 250 & 500ms") self.Send(topics, "50") if timedelta(milliseconds=500) < self.__deltaTime < timedelta(milliseconds=750): print("[INFO] press between 500 & 750ms") self.Send(topics, "75") if self.__deltaTime > timedelta(milliseconds=750): print("[INFO] press longer than 750ms") self.Send(topics, "100") print("[INFO] DeltaTime : " + str(self.__deltaTime)) def Receive(self, server, topic: str, payload: bytes): self.__packet = payload.decode("utf-8") msg = json.loads(self.__packet) # print("[MQTT] " + str(msg['packet'])) self.__RSSI = int(msg['packet']['optionalData']['dBm'], 16) self.__state = msg['packet']['data']['status'] if self.__state == "30": self.__channel = msg['packet']['data']['data'] print("[INFO] Pressed on channel {}".format(self.__channel)) self.__timestamp1 = datetime.strptime( datetime.now().strftime("%d/%m/%y %H:%M:%S.%f"), self.__formatDate) else: # print("[INFO] Released on channel {}".format(self.__channel)) self.__timestamp2 = datetime.strptime( datetime.now().strftime("%d/%m/%y %H:%M:%S.%f"), self.__formatDate) self.__deltaTime = self.__timestamp2 - self.__timestamp1 if self.__channel == "10": if self.__deviceProperties["device"]["0"]["dimmable"] == True: self.sendBrightness(self.__topicDevices["0"]["dimmer"]) else: self.Send(self.__topicDevices["0"]["power"], "TOGGLE") if self.__channel == "30": if self.__deviceProperties["device"]["1"]["dimmable"] == True: self.sendBrightness(self.__topicDevices["1"]["dimmer"]) else: self.Send(self.__topicDevices["1"]["power"], "TOGGLE") if self.__channel == "50": if self.__deviceProperties["device"]["2"]["dimmable"] == True: self.sendBrightness(self.__topicDevices["2"]["dimmer"]) else: self.Send(self.__topicDevices["2"]["power"], "TOGGLE") if self.__channel == "70": if self.__deviceProperties["device"]["3"]["dimmable"] == True: self.sendBrightness(self.__topicDevices["3"]["dimmer"]) else: self.Send(self.__topicDevices["3"]["power"], "TOGGLE") def Send(self, topic, msg): self.__mqtt.sendMessage(topic, msg) def Connected(self, server): pass def Acknowledge(self, server, messageId: int): pass def Stop(self): print("[Switch] with uniqueID {} closed".format(self.__enOceanID))