diff --git a/doc/nefit/mqtt.py b/doc/nefit/mqtt.py
new file mode 100644
index 000000000..21ddc42a5
--- /dev/null
+++ b/doc/nefit/mqtt.py
@@ -0,0 +1,113 @@
+# Based on https://github.com/emontnemery/domoticz_mqtt_discovery
+import Domoticz
+import time
+
+class MqttClient:
+ Address = ""
+ Port = ""
+ mqttConn = None
+ isConnected = False
+ mqttConnectedCb = None
+ mqttDisconnectedCb = None
+ mqttPublishCb = None
+
+ def __init__(self, destination, port, mqttConnectedCb, mqttDisconnectedCb, mqttPublishCb, mqttSubackCb):
+ Domoticz.Debug("MqttClient::__init__")
+ self.Address = destination
+ self.Port = port
+ self.mqttConnectedCb = mqttConnectedCb
+ self.mqttDisconnectedCb = mqttDisconnectedCb
+ self.mqttPublishCb = mqttPublishCb
+ self.mqttSubackCb = mqttSubackCb
+ self.Open()
+
+ def __str__(self):
+ Domoticz.Debug("MqttClient::__str__")
+ if (self.mqttConn != None):
+ return str(self.mqttConn)
+ else:
+ return "None"
+
+ def Open(self):
+ Domoticz.Debug("MqttClient::Open")
+ if (self.mqttConn != None):
+ self.Close()
+ self.isConnected = False
+ self.mqttConn = Domoticz.Connection(Name=self.Address, Transport="TCP/IP", Protocol="MQTT", Address=self.Address, Port=self.Port)
+ self.mqttConn.Connect()
+
+ def Connect(self):
+ Domoticz.Debug("MqttClient::Connect")
+ if (self.mqttConn == None):
+ self.Open()
+ else:
+ ID = 'Domoticz_'+str(int(time.time()))
+ Domoticz.Log("MQTT CONNECT ID: '" + ID + "'")
+ self.mqttConn.Send({'Verb': 'CONNECT', 'ID': ID})
+
+ def Ping(self):
+ Domoticz.Debug("MqttClient::Ping")
+ if (self.mqttConn == None or not self.isConnected):
+ self.Open()
+ else:
+ self.mqttConn.Send({'Verb': 'PING'})
+
+ def Publish(self, topic, payload, retain = 0):
+ Domoticz.Log("MqttClient::Publish " + topic + " (" + payload + ")")
+ if (self.mqttConn == None or not self.isConnected):
+ self.Open()
+ else:
+ self.mqttConn.Send({'Verb': 'PUBLISH', 'Topic': topic, 'Payload': bytearray(payload, 'utf-8'), 'Retain': retain})
+
+ def Subscribe(self, topics):
+ Domoticz.Debug("MqttClient::Subscribe")
+ subscriptionlist = []
+ for topic in topics:
+ subscriptionlist.append({'Topic':topic, 'QoS':0})
+ if (self.mqttConn == None or not self.isConnected):
+ self.Open()
+ else:
+ self.mqttConn.Send({'Verb': 'SUBSCRIBE', 'Topics': subscriptionlist})
+
+ def Close(self):
+ Domoticz.Log("MqttClient::Close")
+ #TODO: Disconnect from server
+ self.mqttConn = None
+ self.isConnected = False
+
+ def onConnect(self, Connection, Status, Description):
+ Domoticz.Debug("MqttClient::onConnect")
+ if (Status == 0):
+ Domoticz.Log("Successful connect to: "+Connection.Address+":"+Connection.Port)
+ self.Connect()
+ else:
+ Domoticz.Log("Failed to connect to: "+Connection.Address+":"+Connection.Port+", Description: "+Description)
+
+ def onDisconnect(self, Connection):
+ Domoticz.Log("MqttClient::onDisonnect Disconnected from: "+Connection.Address+":"+Connection.Port)
+ self.Close()
+ # TODO: Reconnect?
+ if self.mqttDisconnectedCb != None:
+ self.mqttDisconnectedCb()
+
+ def onMessage(self, Connection, Data):
+ topic = ''
+ if 'Topic' in Data:
+ topic = Data['Topic']
+ payloadStr = ''
+ if 'Payload' in Data:
+ payloadStr = Data['Payload'].decode('utf8','replace')
+ payloadStr = str(payloadStr.encode('unicode_escape'))
+
+ if Data['Verb'] == "CONNACK":
+ self.isConnected = True
+ if self.mqttConnectedCb != None:
+ self.mqttConnectedCb()
+
+ if Data['Verb'] == "SUBACK":
+ if self.mqttSubackCb != None:
+ self.mqttSubackCb()
+
+ if Data['Verb'] == "PUBLISH":
+ if self.mqttPublishCb != None:
+ self.mqttPublishCb(topic, Data['Payload'])
\ No newline at end of file
diff --git a/doc/nefit/plugin.py b/doc/nefit/plugin.py
new file mode 100644
index 000000000..d9f4d7515
--- /dev/null
+++ b/doc/nefit/plugin.py
@@ -0,0 +1,169 @@
+"""
+
+
+ Plugin to control Nefit EMS-ESP with ' Proddy' firmware
+
+ Automatically creates Domoticz devices for connected device.
+ Do not forget to "Accept new Hardware Devices" on first run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"""
+
+import Domoticz
+import json
+import time
+from mqtt import MqttClient
+
+class Thermostat:
+ def checkDevices(self):
+ if 1 not in Devices:
+ Domoticz.Debug("Create Temperature Device")
+ Domoticz.Device(Name="Woonkamer", Unit=1, Type=80, Subtype=5).Create()
+ if 2 not in Devices:
+ Domoticz.Debug("Create System Pressure Device")
+ Domoticz.Device(Name="System Pressure", Unit=2, Type=243, Subtype=9).Create()
+ if 3 not in Devices:
+ Domoticz.Debug("Create Thermostat Device")
+ Domoticz.Device(Name="Nefit", Unit=3, Type=242, Subtype=1).Create()
+
+ def onMqttMessage(self, topic, payload):
+ if "sysPress" in payload:
+ pressure=payload["sysPress"]
+ Domoticz.Debug("System Pressure: {}".format(pressure))
+ Devices[2].Update(nValue=1, sValue=str(pressure))
+
+ if "currtemp" in payload:
+ temp=round(float(payload["currtemp"]),1)
+ Domoticz.Debug("Current temp: {}".format(temp))
+ if Devices[1].sValue != temp:
+ Devices[1].Update(nValue=1, sValue=str(temp))
+ if "seltemp" in payload:
+ temp=payload["seltemp"]
+ Domoticz.Debug("Temp setting: {}".format(temp))
+ if Devices[3].sValue != temp:
+ Devices[3].Update(nValue=1, sValue=str(temp))
+
+ def onCommand(self, mqttClient, unit, command, level, color):
+ topic = "ems-esp/thermostat_cmd"
+ if (command == "Set Level"):
+ #MQTT command syntax for setting the temperature: {"cmd":"temp", "data":, "hc":1}
+ cmdstr = chr(123) + chr(34) + "cmd" +chr(34) + ":" + chr(34) + "temp" + chr(34) + ", " #that's {"cmd":"temp",
+ cmdstr = cmdstr + chr(34) + "data" + chr(34) + ":" + str(level) +", " #that adds "data":,
+ cmdstr = cmdstr + chr(34) + "hc" + chr(34) + ":1" + chr(125) #that adds "hc":1}
+ mqttClient.Publish(topic, cmdstr)
+
+class BasePlugin:
+ mqttClient = None
+
+ def onStart(self):
+ self.debugging = Parameters["Mode6"]
+
+ if self.debugging == "Verbose+":
+ Domoticz.Debugging(2+4+8+16+64)
+ if self.debugging == "Verbose":
+ Domoticz.Debugging(2+4+8+16+64)
+ if self.debugging == "Debug":
+ Domoticz.Debugging(2+4+8)
+
+ self.controller = Thermostat()
+
+ self.controller.checkDevices()
+
+ self.topics = list(["ems-esp/thermostat_data1", "ems-esp/boiler_data", "ems-esp/STATE"])
+ self.mqttserveraddress = Parameters["Address"].replace(" ", "")
+ self.mqttserverport = Parameters["Port"].replace(" ", "")
+ self.mqttClient = MqttClient(self.mqttserveraddress, self.mqttserverport, self.onMQTTConnected, self.onMQTTDisconnected, self.onMQTTPublish, self.onMQTTSubscribed)
+
+ def checkDevices(self):
+ Domoticz.Log("checkDevices called")
+
+ def onStop(self):
+ Domoticz.Log("onStop called")
+
+ def onCommand(self, Unit, Command, Level, Color):
+ Domoticz.Debug("Command: " + Command + " (" + str(Level))
+ self.controller.onCommand(self.mqttClient, Unit, Command, Level, Color)
+
+ def onConnect(self, Connection, Status, Description):
+ self.mqttClient.onConnect(Connection, Status, Description)
+
+ def onDisconnect(self, Connection):
+ self.mqttClient.onDisconnect(Connection)
+
+ def onMessage(self, Connection, Data):
+ self.mqttClient.onMessage(Connection, Data)
+
+ def onHeartbeat(self):
+ Domoticz.Debug("Heartbeating...")
+
+ # Reconnect if connection has dropped
+ if self.mqttClient.mqttConn is None or (not self.mqttClient.mqttConn.Connecting() and not self.mqttClient.mqttConn.Connected() or not self.mqttClient.isConnected):
+ Domoticz.Debug("Reconnecting")
+ self.mqttClient.Open()
+ else:
+ self.mqttClient.Ping()
+
+ def onMQTTConnected(self):
+ Domoticz.Debug("onMQTTConnected")
+ self.mqttClient.Subscribe(self.topics)
+
+ def onMQTTDisconnected(self):
+ Domoticz.Debug("onMQTTDisconnected")
+
+ def onMQTTSubscribed(self):
+ Domoticz.Debug("onMQTTSubscribed")
+
+ def onMQTTPublish(self, topic, rawmessage):
+ Domoticz.Debug("MQTT message: " + topic + " " + str(rawmessage))
+
+ message = ""
+ try:
+ message = json.loads(rawmessage.decode('utf8'))
+ except ValueError:
+ message = rawmessage.decode('utf8')
+
+ if (topic in self.topics):
+ self.controller.onMqttMessage(topic, message)
+
+global _plugin
+_plugin = BasePlugin()
+
+def onStart():
+ global _plugin
+ _plugin.onStart()
+
+def onStop():
+ global _plugin
+ _plugin.onStop()
+
+def onConnect(Connection, Status, Description):
+ global _plugin
+ _plugin.onConnect(Connection, Status, Description)
+
+def onDisconnect(Connection):
+ global _plugin
+ _plugin.onDisconnect(Connection)
+
+def onMessage(Connection, Data):
+ global _plugin
+ _plugin.onMessage(Connection, Data)
+
+def onCommand(Unit, Command, Level, Color):
+ global _plugin
+ _plugin.onCommand(Unit, Command, Level, Color)
+
+def onHeartbeat():
+ global _plugin
+ _plugin.onHeartbeat()