I am in the process of creating a plugin to integrate a Weeder board WDTIO like this one : https://weedtech.com/digital-in.html
Here it is :
Code: Select all
# Weeder Plugin
#
# Author: Sergio
#
#
# Plugin parameter definition below will be parsed during startup and copied into Manifest.xml, this will then drive the user interface in the Hardware web page
#
"""
<plugin key="Weeder" name="Weeder WDTIO Board" author="serge" version="0.0.1" externallink="http://www.weedtech.com/">
<description>
Weeder Board <br/><br/>
"Inputs" and "Outputs" need to have '|' delimited letters of inputs and outputs<br/>
</description>
<params>
<param field="SerialPort" label="Serial Port" width="150px" required="true" default="/dev/tty/weeder"/>
<param field="Mode4" label="Inputs (Zone letter seperated by | )" width="550px" required="false" default="A|B|C|D|E|F"/>
<param field="Mode5" label="Outputs (Zone letter seperated by | )" width="550px" required="false" default="G|H|I|J|K|L"/>
<param field="Mode6" label="Debug" width="100px">
<options>
<option label="True" value="Debug"/>
<option label="False" value="Normal" default="true" />
<option label="Logging" value="File"/>
</options>
</param>
</params>
</plugin>
"""
import Domoticz
import os
import time
enabled = False
serialBuffer = ""
class BasePlugin:
SerialConn = None
outputs = []
inputs = []
def __init__(self):
return
def onStart(self):
Domoticz.Log("onStart called")
if (Parameters["Mode6"] != "Normal"):
Domoticz.Debugging(1)
DumpConfigToLog()
self.inputs = Parameters["Mode4"].split('|')
self.outputs = Parameters["Mode5"].split('|')
Domoticz.Log("Discovered inputs : " + str (len(self.inputs)) + "Discovered outputs : "+ str (len(self.outputs)))
LogMessage("Discovered inputs : " + str (len(self.inputs)) + "Discovered outputs : "+ str (len(self.outputs)))
if (len(Devices) ==0):
createDevices()
self.SerialConn = Domoticz.Connection(Name="Weeder", Transport="Serial", Protocol="line", Address=Parameters["SerialPort"], Baud=9600)
self.SerialConn.Connect()
self.SerialConn.Send("AX0\r",Delay=2)
Domoticz.Heartbeat(30)
initialize()
Domoticz.Log("Plugin has (on start)" + str(len(Devices)) + " devices associated with it.")
LogMessage("Plugin has (on start)" + str(len(Devices)) + " devices associated with it.")
return
def createDevices(self):
LogMessage("Create devices called")
for zone in range (0,len(self.inputs)):
Domoticz.Log("Created input "+self.inputs[zone])
LogMessage("Created input "+self.inputs[zone])
Domoticz.Device(Name= "Input Zone "+ self.inputs[zone],Unit=zone+1,TypeName="Switch").Create()
for out in range (0,len(self.outputs)):
LogMessage("Created output "+self.outputs[out])
Domoticz.Log("Created output "+self.outputs[out])
Domoticz.Device(Name= "Output Zone "+ self.outputs[out],Unit=len(self.inputs)+out+1,TypeName="Switch").Create()
def onStop(self):
Domoticz.Log("onStop called")
LogMessage("onStop called")
def onConnect(self, Connection, Status, Description):
Domoticz.Log("onConnect called")
LogMessage("onStop called")
if (Status == 0):
Domoticz.Log("Connected successfully to: "+Parameters["SerialPort"])
LogMessage("Connected successfully to: "+Parameters["SerialPort"])
else:
Domoticz.Log("Failed to connect ("+str(Status)+") to: "+Parameters["SerialPort"])
LogMessage("Failed to connect ("+str(Status)+") to: "+Parameters["SerialPort"]+" with error: "+Description)
return True
def onMessage(self, Connection, Data):
global serialBuffer
serialBuffer += Data.decode("ascii")
messages = serialBuffer.split("\r")
i=0
while (i < len(messages) - 1):
strData = messages[i]
#if ("A!" in strData):
if (len(strData) != 3):
LogMessage("Weeder Board A reset")
LogMessage("Received [{0}] handling ...".format(strData.replace("\r", "<cr>")))
os.system("sudo monit restart all")
else:
board = strData[0]
zone = strData[1]
state = strData[2]
LogMessage("Received [{0}] handling ...".format(strData.replace("\r", "<cr>")))
if (state == "L"):
LogMessage("Weeder Zone "+zone+" state: "+state)
updateDevice(zoneAlphaToDecimal(zone),0,"Ferme")
elif (state == "H"):
LogMessage("Weeder Zone "+zone+" state: "+state)
updateDevice(zoneAlphaToDecimal(zone),1,"Ouvert")
i += 1
serialBuffer = messages[len(messages) - 1]
return
def initialize(self):
LogMessage("Initialize called")
for zone in range (0,len(self.inputs)): # Zone A-N
LogMessage("Initialized input "+self.inputs[zone])
self.SerialConn.Send("AS"+self.inputs[zone]+"\r",Delay=5)
#time.sleep(5)
def updateDevice(self,Unit,nValue,sValue):
if (Unit in Devices):
if (Devices[Unit].nValue != nValue) or (Devices[Unit].sValue != sValue):
Devices[Unit].Update(nValue, str(sValue))
LogMessage("Update "+str(nValue)+":'"+str(sValue)+"' ("+Devices[Unit].Name+")")
Domoticz.Log("Update "+str(nValue)+":'"+str(sValue)+"' ("+Devices[Unit].Name+")")
return
def onCommand(self, Unit, Command, Level, Hue):
Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
LogMessage("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
newstate=1 if Command=="On" else 0
newstateName="On" if Command=="On" else "Off"
if (Command == "On" and zoneDecimalToAlpha(Unit) in self.outputs):
self.SerialConn.Send("AH"+zoneDecimalToAlpha(Unit)+"\r",Delay=1)
Devices[Unit].Update(nValue=newstate, sValue=newstateName)
if (Command == "Off" and zoneDecimalToAlpha(Unit) in self.outputs):
self.SerialConn.Send("AL"+zoneDecimalToAlpha(Unit)+"\r",Delay=1)
Devices[Unit].Update(nValue=newstate, sValue=newstateName)
def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)
LogMessage("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile)
def onDisconnect(self, Connection):
Domoticz.Log("onDisconnect called")
LogMessage("onDisconnect called")
self.SerialConn.Disconnect
for Device in Devices:
Devices[Device].Update(nValue=Devices[Device].nValue, sValue=Devices[Device].sValue, TimedOut=1)
Domoticz.Log("Connection '"+Connection.Name+"' disconnected.")
return
def onHeartbeat(self):
# if (self.SerialConn.Connected()):
# Domoticz.Debug("onHeartbeat called")
# else:
# Domoticz.Log("onHeartbeat called reconnect")
# SerialConn.Connect()
return True
global _plugin
_plugin = BasePlugin()
def onStart():
global _plugin
_plugin.onStart()
def initialize():
global _plugin
_plugin.initialize()
def createDevices():
global _plugin
_plugin.createDevices()
def updateDevice(Unit,nValue,sValue):
global _plugin
_plugin.updateDevice(Unit,nValue,sValue)
def onStop():
global _plugin
_plugin.onStop()
def onConnect(Connection, Status, Description):
global _plugin
_plugin.onConnect(Connection, Status, Description)
def onMessage(Connection, Data):
global _plugin
_plugin.onMessage(Connection, Data)
def onCommand(Unit, Command, Level, Hue):
global _plugin
_plugin.onCommand(Unit, Command, Level, Hue)
def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
global _plugin
_plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)
def onDisconnect(Connection):
global _plugin
_plugin.onDisconnect(Connection)
def onHeartbeat():
global _plugin
_plugin.onHeartbeat()
# Generic helper functions
def DumpConfigToLog():
for x in Parameters:
if Parameters[x] != "":
LogMessage( "'" + x + "':'" + str(Parameters[x]) + "'")
LogMessage("Device count: " + str(len(Devices)))
for x in Devices:
LogMessage("Device: " + str(x) + " - " + str(Devices[x]))
LogMessage("Device ID: '" + str(Devices[x].ID) + "'")
LogMessage("Device Name: '" + Devices[x].Name + "'")
LogMessage("Device nValue: " + str(Devices[x].nValue))
LogMessage("Device sValue: '" + Devices[x].sValue + "'")
LogMessage("Device LastLevel: " + str(Devices[x].LastLevel))
return
def LogMessage(Message):
if Parameters["Mode6"] == "File":
f = open(Parameters["HomeFolder"]+"weederplugin.log","a")
f.write(Message+"\r\n")
f.close()
Domoticz.Debug(Message)
def zoneAlphaToDecimal(Alpha):
switcher = {
"A" : 1,
"B" : 2,
"C" : 3,
"D" : 4,
"E" : 5,
"F" : 6,
"G" : 7,
"H" : 8,
"I" : 9,
"J" : 10,
"K" : 11,
"L" : 12,
"M" : 13,
"N" : 14
}
return switcher.get(Alpha, "invalid")
def zoneDecimalToAlpha(Decimal):
switcher = {
1 : "A",
2 : "B",
3 : "C",
4 : "D",
5 : "E",
6 : "F",
7 : "G",
8 : "H",
9 : "I",
10 : "J",
11 : "K",
12 : "L",
13 : "M",
14 : "N"
}
return switcher.get(Decimal, "invalid")
Code: Select all
def initialize(self):
LogMessage("Initialize called")
for zone in range (0,len(self.inputs)): # Zone A-N
LogMessage("Initialized input "+self.inputs[zone])
self.SerialConn.Send("AS"+self.inputs[zone]+"\r",Delay=5)
#time.sleep(5)
The same thing happens if I introduce a sleep:
Code: Select all
time.sleep(5)
I know it is not recommended, it was for a test, but it does not work either. My commands are all issued at the same time, and the board does not respond to 100% of my commands.
It is my first plugin, comments are more than welcome
Thank you!