Hi all,
I am using my simple plugin for WeMo Switch for some time, now I am releasing in publicly. Feel free to test it and send me a comments etc. Plugin and Readme is available on GitHub:
https://github.com/milanvo/domoticz-plu ... emo-switch
Plugin - WeMo Switch
Python and python framework
Moderator: leecollings
-
- Posts: 80
- Joined: Friday 21 April 2017 8:58
- Target OS: Raspberry Pi / ODroid
- Domoticz version: beta
- Location: Czechia
- Contact:
Plugin - WeMo Switch
My toys:
Raspberry Pi 3 + UPS PIco HV3.0 A Stack
Minibian (Raspbian Jessie) + Domoticz beta
RFLink 433 Gateway, 1wire DS18B20 temp sensors (GPIO)
RaZberry module + 2x Comet Z-Wave + Z-wave socket
---
Plugins: WeMo Switch, UPS PIco HV3.0A on GitHub
Raspberry Pi 3 + UPS PIco HV3.0 A Stack
Minibian (Raspbian Jessie) + Domoticz beta
RFLink 433 Gateway, 1wire DS18B20 temp sensors (GPIO)
RaZberry module + 2x Comet Z-Wave + Z-wave socket
---
Plugins: WeMo Switch, UPS PIco HV3.0A on GitHub
-
- Posts: 46
- Joined: Tuesday 14 March 2017 13:10
- Target OS: Raspberry Pi / ODroid
- Domoticz version: 3.7243
- Contact:
Re: Plugin - WeMo Switch
@mivo
Thanks for the plugin. It works very well.
(Rasp B + v3.8153 and Rasp V2 v3.8312).
In the future can change the plugin to add new Wemo devices (similar to Ping device)?
Thanks for the plugin. It works very well.
(Rasp B + v3.8153 and Rasp V2 v3.8312).
In the future can change the plugin to add new Wemo devices (similar to Ping device)?
-
- Posts: 80
- Joined: Friday 21 April 2017 8:58
- Target OS: Raspberry Pi / ODroid
- Domoticz version: beta
- Location: Czechia
- Contact:
Re: Plugin - WeMo Switch
Hi,
thank you for feedback. I thought about more addresses for WeMo switches, Python plugins has limited options for configuration parameters. Ping hardware has sub-page for setup - native device in C++ code. Do you have more WeMo for testing ? I have only one
. I will try to add option to specify more addresses in field, comma separated.
thank you for feedback. I thought about more addresses for WeMo switches, Python plugins has limited options for configuration parameters. Ping hardware has sub-page for setup - native device in C++ code. Do you have more WeMo for testing ? I have only one

My toys:
Raspberry Pi 3 + UPS PIco HV3.0 A Stack
Minibian (Raspbian Jessie) + Domoticz beta
RFLink 433 Gateway, 1wire DS18B20 temp sensors (GPIO)
RaZberry module + 2x Comet Z-Wave + Z-wave socket
---
Plugins: WeMo Switch, UPS PIco HV3.0A on GitHub
Raspberry Pi 3 + UPS PIco HV3.0 A Stack
Minibian (Raspbian Jessie) + Domoticz beta
RFLink 433 Gateway, 1wire DS18B20 temp sensors (GPIO)
RaZberry module + 2x Comet Z-Wave + Z-wave socket
---
Plugins: WeMo Switch, UPS PIco HV3.0A on GitHub
-
- Posts: 7
- Joined: Friday 10 November 2017 4:09
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: Plugin - WeMo Switch
Hi
I tried this out and it seems to work, however I have error in my log
When I turn off I get this:
2017-11-13 14:45:47.025 Error: (xxxxxxx) Except updStatus: 0|1510551709|236|2059|357681|1209600|83|55680|1194829|473422122
When I turn on I get this:
2017-11-13 14:46:25.091 Error: (xxxxxxx) Except updStatus: 8|1510551947|236|2059|357681|1209600|48|0|1194829|473422122
Icon changes after onHeartbeat it seems.
2017-11-13 14:46:39.336 (zzzzzzzz) Updating device from 0:'0' to have values 1:'100'.
2017-11-13 14:46:39.347 (xxxxxxx) Updated to: 1
How can I fix it?
I tried this out and it seems to work, however I have error in my log
When I turn off I get this:
2017-11-13 14:45:47.025 Error: (xxxxxxx) Except updStatus: 0|1510551709|236|2059|357681|1209600|83|55680|1194829|473422122
When I turn on I get this:
2017-11-13 14:46:25.091 Error: (xxxxxxx) Except updStatus: 8|1510551947|236|2059|357681|1209600|48|0|1194829|473422122
Icon changes after onHeartbeat it seems.
2017-11-13 14:46:39.336 (zzzzzzzz) Updating device from 0:'0' to have values 1:'100'.
2017-11-13 14:46:39.347 (xxxxxxx) Updated to: 1
How can I fix it?
-
- Posts: 7
- Joined: Friday 10 November 2017 4:09
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: Plugin - WeMo Switch
Ok I fixed it...and I additionally added dirty support for WeMo insight switch.
It seems that WeMo is only sending extended status back when turning on/off the switch,
I turn on the relay on every heartbeat if it is already switched on to receive the energy data.
Normally it seems it feeds with upnp, but I have no clue how to grab it on python.
You could probably use this and create a script to update via API:
https://github.com/timonreinhard/wemo-client (check the test directory)
While researching I found this:
https://ouimeaux.readthedocs.io/en/latest/wemo.html
http://moderntoil.com/?p=839
I didn't look deeply inside but maybe I could have used this aswell:
https://github.com/mgsg/domoticz-sonos-plugin
anyway here is the code..
I'm pretty new to python and Domoticz so maybe there are some mistakes you guys can correct...
This script will add a "Insight" True/False switch to Hardware and if you change it to True and restart domoticz
it will create a counter device if not done already, and updates every heartbeat with the latest energy consumption.
Don't forget to enable it.
It seems that WeMo is only sending extended status back when turning on/off the switch,
I turn on the relay on every heartbeat if it is already switched on to receive the energy data.
Normally it seems it feeds with upnp, but I have no clue how to grab it on python.
You could probably use this and create a script to update via API:
https://github.com/timonreinhard/wemo-client (check the test directory)
While researching I found this:
https://ouimeaux.readthedocs.io/en/latest/wemo.html
http://moderntoil.com/?p=839
I didn't look deeply inside but maybe I could have used this aswell:
https://github.com/mgsg/domoticz-sonos-plugin
anyway here is the code..
I'm pretty new to python and Domoticz so maybe there are some mistakes you guys can correct...
This script will add a "Insight" True/False switch to Hardware and if you change it to True and restart domoticz
it will create a counter device if not done already, and updates every heartbeat with the latest energy consumption.
Don't forget to enable it.
- Spoiler: show
Code: Select all
#!/usr/bin/python3 # # Domoticz Python Plugin for WeMo Switch by Belkin # Added support for WeMo Insight switch - r3wt3d 2017/11/16 # Based on code from: # https://gist.github.com/pruppert/af7d38cb7b7ca75584ef # https://github.com/pdumoulin/blinky # # Author: mivo # """ <plugin key="wemo-switch" name="WeMo Switch (plugin)" author="mivo" version="0.1" wikilink="http://www.domoticz.com/wiki/plugins" externallink="https://github.com/milanvo/domoticz-plugins"> <params> <param field="Address" label="IP Address" width="200px" required="true"/> <param field="Port" label="Port" width="50px" required="true" default="49153"/> <param field="Mode1" label="Insight" width="50px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode6" label="Debug" width="75px"> <options> <option label="True" value="Debug"/> <option label="False" value="Normal" default="true"/> </options> </param> </params> </plugin> """ import Domoticz import urllib.request class wemoSwitch: ip = None ports = [49153, 49152, 49154, 49151, 49155] def __init__(self, switch_ip=None, switch_port=None): self.ip = switch_ip if switch_port: self.ports = [switch_port] def action(self, action): value = None if action == 'on': method, obj, value = ('Set', 'BinaryState', 1) elif action == 'off': method, obj, value = ('Set', 'BinaryState', 0) elif action == 'status': method, obj = ('Get', 'BinaryState') elif action == 'name': method, obj = ('Get', 'FriendlyName') elif action == 'signal': method, obj = ('Get', 'SignalStrength') return self._send(method, obj, value) def on(self): return self.action('on') def off(self): return self.action('off') def status(self): return self.action('status') def name(self): return self.action('name') def signal(self): return self.action('signal') def _get_header_xml(self, method, obj): method = method + obj return '"urn:Belkin:service:basicevent:1#%s"' % method def _get_body_xml(self, method, obj, value=0): method = method + obj return '<u:%s xmlns:u="urn:Belkin:service:basicevent:1"><%s>%s</%s></u:%s>' % (method, obj, value, obj, method) def _send(self, method, obj, value=None): body_xml = self._get_body_xml(method, obj, value) header_xml = self._get_header_xml(method, obj) for port in self.ports: result = self._try_send(self.ip, port, body_xml, header_xml, obj) if result is not None: self.ports = [port] return result raise Exception("_send TimeoutOnAllPorts") def _try_send(self, ip, port, body, header, data): try: request = urllib.request.Request('http://%s:%s/upnp/control/basicevent1' % (ip, port)) request.add_header('Content-type', 'text/xml; charset="utf-8"') request.add_header('SOAPACTION', header) request_body = '<?xml version="1.0" encoding="utf-8"?>' request_body += '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' request_body += '<s:Body>%s</s:Body></s:Envelope>' % body request.data = request_body.encode() result = urllib.request.urlopen(request, timeout=3) return self._extract(result.read().decode(), data) except Exception as e: # except: # raise print(str(e)) return None def _get_request_data(self, method, obj, value=None): body_xml = self._get_body_xml(method, obj, value) header_xml = self._get_header_xml(method, obj) headers = dict() url = '/upnp/control/basicevent1' headers['Content-type'] = 'text/xml; charset="utf-8"' headers['SOAPACTION'] = header_xml body = '<?xml version="1.0" encoding="utf-8"?>' \ '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' body += '<s:Body>%s</s:Body></s:Envelope>' % body_xml headers['Content-Length'] = "%d"%(len(body)) return dict(url=url, headers=headers, body=body) def _extract(self, XML, tagName): #print('XML:', XML) #print('tagName:', tagName) startTag = '<%s>' % (tagName) endTag = '</%s>' % (tagName) startPos = XML.find(startTag) endPos = XML.find(endTag, startPos+1) #print('start end:', startPos, endPos) if ((startPos == -1) or (endPos == -1)): print("'"+tagName+"' not found in supplied XML") raise Exception("_extract" + "'"+tagName+"' not found in supplied XML") return False #if ((startPos == -1) or (endPos == -1)): Domoticz.Error("'"+tagName+"' not found in supplied XML") #print('vystup:', XML[startPos+len(startTag):endPos]) return XML[startPos+len(startTag):endPos] global switch switch = wemoSwitch() def onStart(): global switch if Parameters["Mode6"] == "Debug": Domoticz.Debugging(1) if (len(Devices) == 0): Domoticz.Device(Name="Switch 1", Unit=1, TypeName="Switch").Create() Domoticz.Log("Device created.") if (2 not in Devices and Parameters["Mode1"] == "YES"): Domoticz.Device(Name="Power", Unit=2, TypeName="kWh").Create() Domoticz.Log("kWh Device created.") Domoticz.Heartbeat(30) switch.ip = Parameters["Address"] switch.port = Parameters["Port"] try: status = switch.status() except Exception as e: Domoticz.Error('Except onStart: ' + str(e)) return updStatus(status) DumpConfigToLog() def onStop(): Domoticz.Log("Plugin is stopping.") def onCommand(Unit, Command, Level, Hue): global switch try: if (Command.upper() == 'ON'): status = switch.on() else: status = switch.off() except Exception as e: Domoticz.Error('Except onCommand: ' + str(e)) return updStatus(status) def onHeartbeat(): global switch try: status = switch.status() except Exception as e: Domoticz.Error('Except onHeartbeat: ' + str(e)) return Domoticz.Debug(str(status)) if int(status[0:1]) == 1 and Parameters["Mode1"] == "YES": power = str(switch.on()).split('|') kwh = str(int(power[7])/1000) Domoticz.Debug(kwh) Devices[2].Update(0,kwh) if int(status[0:1]) == 0 and Parameters["Mode1"] == "YES": Devices[2].Update(0,"0.000") updStatus(status) def updStatus(status): if not status: Domoticz.Error('False updStatus: ' + str(status)) return try: istatus = int(status[0:1]) except ValueError: Domoticz.Error('Except updStatus: ' + str(status)) return Domoticz.Debug('Status: ' + str(status) + ' iStatus: ' + str(istatus)) if istatus == 1: if (1 in Devices): if Devices[1].nValue == 0: #if Devices[1].sValue == "Off": Devices[1].Update(1,"On") Domoticz.Debug('Updated to: ' + str(istatus)) elif istatus == 0: if (1 in Devices): if Devices[1].nValue == 1: #if Devices[1].sValue == "On": Devices[1].Update(0,"Off") Domoticz.Debug('Updated to: ' + str(istatus)) elif istatus == 8: if (1 in Devices): if Devices[1].nValue == 0: Devices[1].Update(1,"On") Domoticz.Debug('Updated to: ' + str(istatus)) #DumpConfigToLog() # Generic helper functions def DumpConfigToLog(): for x in Parameters: if Parameters[x] != "": Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'") Domoticz.Debug("Device count: " + str(len(Devices))) for x in Devices: Domoticz.Debug("Device: " + str(x) + " - " + str(Devices[x])) Domoticz.Debug("Device ID: '" + str(Devices[x].ID) + "'") Domoticz.Debug("Device Name: '" + Devices[x].Name + "'") Domoticz.Debug("Device nValue: " + str(Devices[x].nValue)) Domoticz.Debug("Device sValue: '" + Devices[x].sValue + "'") Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel)) return def main(): import argparse parser = argparse.ArgumentParser(description='WeMo Switch control module for Python') parser.add_argument('action', choices=['on', 'off', 'status', 'name', 'signal'], help='Action') parser.add_argument('ip', help='IP address') parser.add_argument('port', nargs='?', default='49153', help='Port') args = parser.parse_args() IP=args.ip PORT=args.port switch = wemoSwitch(IP, PORT) if args.action: print(switch.action(args.action)) if __name__ == '__main__': main()
-
- Posts: 10
- Joined: Tuesday 21 March 2017 20:45
- Target OS: Raspberry Pi / ODroid
- Domoticz version: beta
- Contact:
Re: Plugin - WeMo Switch
Hi, I have taken the liberty of using your and mivo's code and adjusted it a bit for the Wemo Insight. Still working on it to see if i can get the standby status and info in a bit better...
I will include the code, maybe anyone has some additional ideas and pointers.
I will include the code, maybe anyone has some additional ideas and pointers.
- Spoiler: show
-
Code: Select all
#!/usr/bin/python3 # # Domoticz Python Plugin for WeMo Insight by Belkin # Modifications for WeMo Insight switch and rename to wemo-insight - huey 2018/04/16 # Added support for WeMo Insight switch - r3wt3d 2017/11/16 # Based on code from: # https://gist.github.com/pruppert/af7d38cb7b7ca75584ef # https://github.com/pdumoulin/blinky # # Author: mivo # """ <plugin key="wemo-insight" name="WeMo Insight (plugin)" author="huey, with thx to mivo and r3wt3d" version="0.1" wikilink="http://www.domoticz.com/wiki/plugins" > <params> <param field="Address" label="IP Address" width="200px" required="true"/> <param field="Port" label="Port" width="50px" required="true" default="49153"/> <param field="Mode1" label="Power" width="75px"> <options> <option label="True" value="YES" default="true"/> <option label="False" value="NO"/> </options> </param> <param field="Mode2" label="OnFor Usage" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode3" label="OnToday Usage" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode4" label="Summary" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode6" label="Debug" width="75px"> <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 urllib.request import datetime class wemoInsight: ip = None ports = [49153, 49152, 49154, 49151, 49155] def __init__(self, insight_ip=None, insight_port=None): self.ip = insight_ip if insight_port: self.ports = [insight_port] def action(self, action): value = None if action == 'on': event, method, obj, value = ('basicevent', 'Set', 'BinaryState', 1) return self._send(event, method, obj, value) elif action == 'off': event, method, obj, value = ('basicevent', 'Set', 'BinaryState', 0) return self._send(event, method, obj, value) elif action == 'status': event, method, obj = ('basicevent', 'Get', 'BinaryState') return self._send(event, method, obj, value) elif action == 'name': event, method, obj = ('basicevent', 'Get', 'FriendlyName') return self._send(event, method, obj, value) elif action == 'signal': event, method, obj = ('basicevent', 'Get', 'SignalStrength') return self._send(event, method, obj, value) elif action == 'params': event, method, obj = ('insight', 'Get', 'InsightParams') return self._send(event, method, obj, value) elif action == 'autopowerthreshold': event, method, obj = ('insight', 'SetAuto', 'PowerThreshold') return self._send(event, method, obj, value) elif action == 'setpowerthreshold': event, method, obj = ('insight', 'Set', 'PowerThreshold', value) return self._send(event, method, obj, value) elif action == 'resetpowerthreshold': event, method, obj = ('insight', 'Reset', 'PowerThreshold') return self._send(event, method, obj, value) def on(self): return self.action('on') def off(self): return self.action('off') def status(self): return self.action('status') def name(self): return self.action('name') def signal(self): return self.action('signal') def params(self): return self.action('params') def autopowerthreshold(self): return self.action('autopowerthreshold') def setpowerthreshold(self): return self.action('setpowerthreshold') def resetpowerthreshold(self): return self.action('resetpowerthreshold') def _get_header_xml(self, event, method, obj): method = method + obj return '"urn:Belkin:service:%s:1#%s"' % (event, method) def _get_body_xml(self, event, method, obj, value=0): method = method + obj return '<u:%s xmlns:u="urn:Belkin:service:%s:1"><%s>%s</%s></u:%s>' % (method, event, obj, value, obj, method) def _send(self, event, method, obj, value=None): body_xml = self._get_body_xml(event, method, obj, value) header_xml = self._get_header_xml(event, method, obj) for port in self.ports: result = self._try_send(self.ip, port, body_xml, header_xml, obj, event) if result is not None: self.ports = [port] return result raise Exception("_send TimeoutOnAllPorts") def _try_send(self, ip, port, body, header, data, event): try: request = urllib.request.Request('http://%s:%s/upnp/control/%s1' % (ip, port, event)) request.add_header('Content-type', 'text/xml; charset="utf-8"') request.add_header('SOAPACTION', header) request_body = '<?xml version="1.0" encoding="utf-8"?>' request_body += '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' request_body += '<s:Body>%s</s:Body></s:Envelope>' % body request.data = request_body.encode() result = urllib.request.urlopen(request, timeout=3) return self._extract(result.read().decode(), data) except Exception as e: # except: # raise print(str(e)) return None #huey: not sure what this is for, seems unused to me. # def _get_request_data(self, event, method, obj, value=None): # body_xml = self._get_body_xml(event, method, obj, value) # header_xml = self._get_header_xml(event, method, obj) # headers = dict() # # url = '/upnp/control/%s1' % event # headers['Content-type'] = 'text/xml; charset="utf-8"' # headers['SOAPACTION'] = header_xml # # body = '<?xml version="1.0" encoding="utf-8"?>' \ # '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' # body += '<s:Body>%s</s:Body></s:Envelope>' % body_xml # # headers['Content-Length'] = "%d"%(len(body)) # # return dict(url=url, headers=headers, body=body) def _extract(self, XML, tagName): #Domoticz.Debug('XML: ' + XML) #Domoticz.Debug('tagName: ' + tagName) startTag = '<%s>' % (tagName) endTag = '</%s>' % (tagName) startPos = XML.find(startTag) endPos = XML.find(endTag, startPos+1) #Domoticz.Debug('start end: ' + str(startPos) + ' ' + str(endPos)) if ((startPos == -1) or (endPos == -1)): raise Exception("_extract" + "'"+tagName+"' not found in supplied XML") return False #if ((startPos == -1) or (endPos == -1)): Domoticz.Error("'"+tagName+"' not found in supplied XML") #print('vystup:', XML[startPos+len(startTag):endPos]) return XML[startPos+len(startTag):endPos] global insight insight = wemoInsight() def onStart(): global insight Domoticz.Log("* Plugin is starting *") if Parameters["Mode6"] == "Debug": Domoticz.Debugging(1) DumpConfigToLog() #huey: can not get external imports to work... #Domoticz.Log("Debugger started, use 'telnet 0.0.0.0 4444' to connect") #import rpdb #rpdb.set_trace() # if 'WeMoInsightLogo' not in Images: Domoticz.Image('wemo-insight.zip').Create() if (len(Devices) == 0): Domoticz.Device(Name="Switch", Unit=1, TypeName="Switch", Used=1).Create() Domoticz.Log("Switch Device created.") if (2 not in Devices and Parameters["Mode1"] == "YES"): Domoticz.Device(Name="Power", Unit=2, TypeName="kWh", Used=1).Create() Domoticz.Log("kWh Device created.") if (3 not in Devices and Parameters["Mode2"] == "YES"): Domoticz.Device(Name="OnFor", Unit=3, TypeName="Custom", Options = { "Custom" : "1;seconds"}, Used=0).Create() UpdateImage(3, 'WeMoInsightLogo') Domoticz.Log("OnFor Custom Device created.") if (4 not in Devices and Parameters["Mode3"] == "YES"): Domoticz.Device(Name="OnTodayFor", Unit=4, TypeName="Custom", Options = { "Custom" : "1;seconds"}, Used=0).Create() UpdateImage(4, 'WeMoInsightLogo') Domoticz.Log("OnToday Custom Device created.") if (5 not in Devices and Parameters["Mode4"] == "YES"): Domoticz.Device(Name="Summary", Unit=5, TypeName="Text", Used=0).Create() Domoticz.Log("Summary Text Device created.") # if 3 in Devices: # UpdateImage(3, 'WeMoInsightLogo') # if 4 in Devices: # UpdateImage(4, 'WeMoInsightLogo') # Domoticz.Heartbeat(30) Domoticz.Heartbeat(60) insight.ip = Parameters["Address"] insight.port = Parameters["Port"] def onStop(): Domoticz.Log("* Plugin is stopping *") def onCommand(Unit, Command, Level, Hue): global insight Domoticz.Debug("onCommand called") try: if (Command.upper() == 'ON'): status = insight.on() else: status = insight.off() except Exception as e: Domoticz.Error('Except onCommand: ' + str(e)) return updStatus(status) def onHeartbeat(): global insight Domoticz.Debug("* onHeartBeat called *") try: params = insight.params() except Exception as e: Domoticz.Error('Except onHeartbeat: ' + str(e)) return Domoticz.Debug('DebugParams: ' + str(params)) if params is None: Domoticz.Log('ERROR Params is undefined') else: state = int(params[0:1]) Domoticz.Debug('DebugState : ' + str(state)) power = str(insight.params()).split('|') #if state >= 1: updStatus(params) if Parameters["Mode2"] == "YES": Domoticz.Debug("* Device 3 update called *") onfor = int(power[2]) Domoticz.Debug('DebugOnFor: ' + str(onfor)) Devices[3].Update(0,str(onfor)) if Parameters["Mode3"] == "YES": Domoticz.Debug("* Device 4 update called *") ontoday = int(power[3]) Domoticz.Debug('DebugOnToday: ' + str(ontoday)) Devices[4].Update(0,str(ontoday)) if Parameters["Mode4"] == "YES": Domoticz.Debug("* Device 5 update called *") lastchange = datetime.datetime.fromtimestamp(int(power[1])) Domoticz.Debug('DebugLastChange: ' + str(lastchange)) onfortext = datetime.timedelta(seconds=int(power[2])) Domoticz.Debug('DebugOnForText: ' + str(onfortext)) ontodaytext = datetime.timedelta(seconds=int(power[3])) Domoticz.Debug('DebugOnTodayText: ' + str(ontodaytext)) ontotal = int(power[4]) Domoticz.Debug('DebugOnTotal: ' + str(ontotal)) ontotaltext = datetime.timedelta(seconds=int(power[4])) Domoticz.Debug('DebugOnTotalText: ' + str(ontotaltext)) totalmw = int(float(power[9]))/1000 Domoticz.Debug('DebugTotalkWh: ' + str(totalmw)) threshold = int(power[10])/1000 Domoticz.Debug('DebugThreshold: ' + str(threshold)) Devices[5].Update(0,"On for: "+ str(onfortext) + "<br>" + "On today: " + str(ontodaytext) + "<br>" + "On total: " + str(ontotaltext) + "<br>" + "Total kWh: " + str(totalmw) + "<br>" + "Standby threshold: " + str(threshold) + "<br>" + "Last change: " + str(lastchange)) def updStatus(status): Domoticz.Debug("* updStatus called *") if not status: Domoticz.Error('False updStatus: ' + str(status)) return try: istate = int(status[0:1]) except ValueError: Domoticz.Error('Except updStatus: ' + str(status)) return Domoticz.Debug('DebugStatus: ' + str(status) + ' iState: ' + str(istate)) Domoticz.Debug("* Device 1 update called *") if istate == 1: if (1 in Devices): if Devices[1].nValue == 0: #if Devices[1].sValue == "Off": Devices[1].Update(1,"On") Domoticz.Debug('Updated to: ' + str(istate)) elif istate == 0: if (1 in Devices): if Devices[1].nValue == 1: #if Devices[1].sValue == "On": Devices[1].Update(0,"Off") Domoticz.Debug('Updated to: ' + str(istate)) elif istate == 8: if (1 in Devices): if Devices[1].nValue == 0: Devices[1].Update(1,"On") Domoticz.Debug('Updated to: ' + str(istate)) if Parameters["Mode1"] == "YES": Domoticz.Debug("* Device 2 update called *") # power = str(insight.params()).split('|') power = status.split('|') if Parameters["Mode1"] == "YES": currentmw = int(power[7])/1000 Domoticz.Debug('DebugkWh: ' + str(currentmw)) todaymw = int(power[8])/1000 Domoticz.Debug('DebugtoDay: ' + str(todaymw)) Devices[2].Update(0,str(currentmw) + "; " + str(todaymw)) # Synchronise images to match parameter in hardware page #def UpdateImage(Unit, Logo): # if Unit in Devices and Logo in Images: # if Devices[Unit].Image != Images[Logo].ID: # Domoticz.Log("Device Image update: 'WeMoInsight', Currently " + str(Devices[Unit].Image) + ", should be " + str(Images[Logo].ID)) # Devices[Unit].Update(nValue=Devices[Unit].nValue, sValue=str(Devices[Unit].sValue), Image=Images[Logo].ID) # return # Generic helper functions def LogMessage(Message): if Parameters["Mode6"] == "File": f = open(Parameters["HomeFolder"] + "plugin.log", "a") f.write(Message + "\r\n") f.close() Domoticz.Debug(Message) 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("Internal ID: '" + str(Devices[x].ID) + "'") LogMessage("External ID: '" + str(Devices[x].DeviceID) + "'") 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 main(): import argparse parser = argparse.ArgumentParser(description='WeMo Insight control module for Python') parser.add_argument('action', choices=['on', 'off', 'status', 'name', 'signal', 'params', 'autopowerthreshold', 'setpowerthreshold', 'resetpowerthreshold'], help='Action') parser.add_argument('ip', help='IP address') parser.add_argument('port', nargs='?', default='49153', help='Port') args = parser.parse_args() IP=args.ip PORT=args.port insight = wemoInsight(IP, PORT) if args.action: print(insight.action(args.action)) if __name__ == '__main__': main()
-
- Posts: 10
- Joined: Tuesday 21 March 2017 20:45
- Target OS: Raspberry Pi / ODroid
- Domoticz version: beta
- Contact:
Re: Plugin - WeMo Switch
Latest and probably last version and with some icons.
- Spoiler: show
-
Code: Select all
#!/usr/bin/python3 # # Domoticz Python Plugin for WeMo Insight by Belkin # Modifications for WeMo Insight switch and rename to wemo-insight - huey 2018/04/16 # Added support for WeMo Insight switch - r3wt3d 2017/11/16 # Based on code from: # https://gist.github.com/pruppert/af7d38cb7b7ca75584ef # https://github.com/pdumoulin/blinky # # Author: mivo # """ <plugin key="wemo-insight" name="WeMo Insight (plugin)" author="huey, with thx to mivo and r3wt3d" version="0.1" wikilink="http://www.domoticz.com/wiki/plugins" > <description> <h2>Belkin WeMo Insight plugin</h2><br/> <h3>Devices</h3> <ul style="list-style-type:square"> <li>Comes default with on/off switch and power</li> <li>Optional additional selector switch for more convenient logging of standby status</li> <li>Optional additional devices to log duration of last ontime and total for day in seconds</li> <li>Optional additional device with summary details text</li> <li>Optional additional device to reset standby threshold to default value of 8 or auto value</li> </ul> </description> <params> <param field="Address" label="IP Address" width="200px" required="true"/> <param field="Port" label="Port" width="50px" required="true" default="49153"/> <param field="Mode1" label="Standby status" width="75px"> <options> <option label="True" value="YES" default="true"/> <option label="False" value="NO"/> </options> </param> <param field="Mode2" label="On for seconds" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode3" label="Today seconds" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode4" label="Summary details" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode5" label="Standby reset" width="75px"> <options> <option label="True" value="YES"/> <option label="False" value="NO" default="true"/> </options> </param> <param field="Mode6" label="Debug" width="75px"> <options> <option label="True" value="Debug"/> <option label="False" value="Normal" default="true"/> </options> </param> </params> </plugin> """ ##import Domoticz try: import Domoticz except ImportError: def Log(s): print(s) def Debug(s): print(s) def Error(s): print(s) import sys import urllib.request import datetime class wemoInsight: ip = None ports = [49153, 49152, 49154, 49151, 49155] def __init__(self, insight_ip=None, insight_port=None): self.ip = insight_ip if insight_port: self.ports = [insight_port] def action(self, action): value = None if action == 'on': event, method, obj, value = ('basicevent', 'Set', 'BinaryState', 1) return self._send(event, method, obj, value) elif action == 'off': event, method, obj, value = ('basicevent', 'Set', 'BinaryState', 0) return self._send(event, method, obj, value) elif action == 'status': event, method, obj = ('basicevent', 'Get', 'BinaryState') return self._send(event, method, obj, value) elif action == 'name': event, method, obj = ('basicevent', 'Get', 'FriendlyName') return self._send(event, method, obj, value) elif action == 'signal': event, method, obj = ('basicevent', 'Get', 'SignalStrength') return self._send(event, method, obj, value) elif action == 'params': event, method, obj = ('insight', 'Get', 'InsightParams') return self._send(event, method, obj, value) elif action == 'autopowerthreshold': event, method, obj = ('insight', 'SetAuto', 'PowerThreshold') return self._send(event, method, obj, value) elif action == 'setpowerthreshold': event, method, obj, value = ('insight', 'Set', 'PowerThreshold', value) return self._send(event, method, obj, value) elif action == 'resetpowerthreshold': event, method, obj = ('insight', 'Reset', 'PowerThreshold') return self._send(event, method, obj, value) def on(self): return self.action('on') def off(self): return self.action('off') def status(self): return self.action('status') def name(self): return self.action('name') def signal(self): return self.action('signal') def params(self): return self.action('params') def autopowerthreshold(self): return self.action('autopowerthreshold') def setpowerthreshold(self): return self.action('setpowerthreshold') def resetpowerthreshold(self): return self.action('resetpowerthreshold') def _get_header_xml(self, event, method, obj): method = method + obj return '"urn:Belkin:service:%s:1#%s"' % (event, method) def _get_body_xml(self, event, method, obj, value=0): method = method + obj return '<u:%s xmlns:u="urn:Belkin:service:%s:1"><%s>%s</%s></u:%s>' % (method, event, obj, value, obj, method) def _send(self, event, method, obj, value=None): body_xml = self._get_body_xml(event, method, obj, value) header_xml = self._get_header_xml(event, method, obj) for port in self.ports: result = self._try_send(self.ip, port, body_xml, header_xml, obj, event) if result is not None: self.ports = [port] return result raise Exception("_send TimeoutOnAllPorts") def _try_send(self, ip, port, body, header, data, event): try: request = urllib.request.Request('http://%s:%s/upnp/control/%s1' % (ip, port, event)) request.add_header('Content-type', 'text/xml; charset="utf-8"') request.add_header('SOAPACTION', header) request_body = '<?xml version="1.0" encoding="utf-8"?>' request_body += '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' request_body += '<s:Body>%s</s:Body></s:Envelope>' % body request.data = request_body.encode() result = urllib.request.urlopen(request, timeout=3) return self._extract(result.read().decode(), data) except Exception as e: # except: # raise print(str(e)) return None #huey: not sure what this is for, seems unused to me. # def _get_request_data(self, event, method, obj, value=None): # body_xml = self._get_body_xml(event, method, obj, value) # header_xml = self._get_header_xml(event, method, obj) # headers = dict() # # url = '/upnp/control/%s1' % event # headers['Content-type'] = 'text/xml; charset="utf-8"' # headers['SOAPACTION'] = header_xml # # body = '<?xml version="1.0" encoding="utf-8"?>' \ # '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">' # body += '<s:Body>%s</s:Body></s:Envelope>' % body_xml # # headers['Content-Length'] = "%d"%(len(body)) # # return dict(url=url, headers=headers, body=body) def _extract(self, XML, tagName): #Domoticz.Debug('XML: ' + XML) #Domoticz.Debug('tagName: ' + tagName) startTag = '<%s>' % (tagName) endTag = '</%s>' % (tagName) startPos = XML.find(startTag) endPos = XML.find(endTag, startPos+1) #Domoticz.Debug('start end: ' + str(startPos) + ' ' + str(endPos)) if ((startPos == -1) or (endPos == -1)): raise Exception("_extract" + "'"+tagName+"' not found in supplied XML") return False #if ((startPos == -1) or (endPos == -1)): Domoticz.Error("'"+tagName+"' not found in supplied XML") #print('vystup:', XML[startPos+len(startTag):endPos]) return XML[startPos+len(startTag):endPos] global insight insight = wemoInsight() def onStart(): global insight Domoticz.Log("* Plugin is starting *") if Parameters["Mode6"] == "Debug": Domoticz.Debugging(1) Domoticz.Debug("sys.exec: " + str(sys.executable)) #sys.path.append('/usr/local/lib/python36/site-packages') Domoticz.Debug("sys.path: " + str(sys.path)) DumpConfigToLog() #huey: can not get external imports to work... #Domoticz.Log("Debugger started, use 'telnet 0.0.0.0 4444' to connect") #import rpdb #rpdb.set_trace() if 'WeMoInsight' not in Images: Domoticz.Debug("Create new images") Domoticz.Image('WeMoInsight.zip').Create() if (len(Devices) == 0): Domoticz.Device(Name="Switch", Unit=1, TypeName="Switch", Used=1).Create() Domoticz.Log("Switch Device created.") Domoticz.Device(Name="Power", Unit=2, TypeName="kWh", Used=1).Create() Domoticz.Log("kWh Device created.") if (3 not in Devices and Parameters["Mode2"] == "YES"): Domoticz.Device(Name="OnFor", Unit=3, TypeName="Custom", Options = { "Custom" : "1;s"}, Used=0).Create() Domoticz.Log("OnFor Custom Device created.") if (4 not in Devices and Parameters["Mode3"] == "YES"): Domoticz.Device(Name="OnTodayFor", Unit=4, TypeName="Custom", Options = { "Custom" : "1;s"}, Used=0).Create() Domoticz.Log("OnToday Custom Device created.") if (5 not in Devices and Parameters["Mode4"] == "YES"): Domoticz.Device(Name="Summary", Unit=5, TypeName="Text", Used=0).Create() Domoticz.Log("Summary Text Device created.") if (6 not in Devices and Parameters["Mode1"] == "YES"): OptionsStatus = {"LevelActions": "||", "LevelNames": "Off|On|Standby", "LevelOffHidden": "false", "SelectorStyle": "0"} Domoticz.Device(Name="Status", Unit=6, TypeName="Selector Switch", Switchtype=18, Image=12, Options=OptionsStatus, Used=0).Create() Domoticz.Log("Switch Status Device created.") if (7 not in Devices and Parameters["Mode5"] == "YES"): OptionsStandby = {"LevelActions": "||", "LevelNames": "Off|Default|Auto", "LevelOffHidden": "true", "SelectorStyle": "0"} Domoticz.Device(Name="Standby threshold", Unit=7, TypeName="Selector Switch", Switchtype=18, Image=12, Options=OptionsStandby, Used=0).Create() Domoticz.Log("Standby Reset Device created.") if 1 in Devices: UpdateImage(1, 'WeMoInsight') if 3 in Devices: UpdateImage(3, 'WeMoInsight') if 4 in Devices: UpdateImage(4, 'WeMoInsight') # if 5 in Devices: # UpdateImage(5, 'WeMoInsight') if 6 in Devices: UpdateImage(6, 'WeMoInsight') if 7 in Devices: UpdateImage(7, 'WeMoInsight') # Domoticz.Heartbeat(30) Domoticz.Heartbeat(60) insight.ip = Parameters["Address"] insight.port = Parameters["Port"] def onStop(): Domoticz.Log("* Plugin is stopping *") def onCommand(Unit, Command, Level, Hue): global insight Domoticz.Debug("onCommand called, unit: " + str(Unit) + " command: " + str(Command) + " level: " + str(Level) + " hue: " + str(Hue)) try: if (Command.upper() == 'ON') or (Unit == 6 and Command.upper() == 'SET LEVEL' and Level >= 10): status = insight.on() updStatus(status) elif (Unit == 7 and Command.upper() == 'SET LEVEL' and Level == 10): status = insight.resetpowerthreshold() Devices[7].Update(1,"10") Domoticz.Debug("Standby: 'Default (8)'") elif (Unit == 7 and Command.upper() == 'SET LEVEL' and Level == 20): status = insight.autopowerthreshold() Devices[7].Update(1,"20") Domoticz.Debug("Standby: 'Auto'") else: status = insight.off() updStatus(status) except Exception as e: Domoticz.Error('Except onCommand: ' + str(e)) return def onHeartbeat(): global insight Domoticz.Debug("* onHeartBeat called *") try: params = insight.params() except Exception as e: Domoticz.Error('Except onHeartbeat: ' + str(e)) return Domoticz.Debug('DebugParams: ' + str(params)) if params is None: Domoticz.Log('ERROR Params is undefined') else: state = int(params[0:1]) Domoticz.Debug('DebugState : ' + str(state)) power = str(insight.params()).split('|') #if state >= 1: updStatus(params) if Parameters["Mode2"] == "YES": Domoticz.Debug("* Device 3 update called *") onfor = int(power[2]) Domoticz.Debug('DebugOnFor: ' + str(onfor)) Devices[3].Update(0,str(onfor)) if Parameters["Mode3"] == "YES": Domoticz.Debug("* Device 4 update called *") ontoday = int(power[3]) Domoticz.Debug('DebugOnToday: ' + str(ontoday)) Devices[4].Update(0,str(ontoday)) if Parameters["Mode4"] == "YES": Domoticz.Debug("* Device 5 update called *") lastchange = datetime.datetime.fromtimestamp(int(power[1])) Domoticz.Debug('DebugLastChange: ' + str(lastchange)) onfortext = datetime.timedelta(seconds=int(power[2])) Domoticz.Debug('DebugOnForText: ' + str(onfortext)) ontodaytext = datetime.timedelta(seconds=int(power[3])) Domoticz.Debug('DebugOnTodayText: ' + str(ontodaytext)) ontotal = int(power[4]) Domoticz.Debug('DebugOnTotal: ' + str(ontotal)) ontotaltext = datetime.timedelta(seconds=int(power[4])) Domoticz.Debug('DebugOnTotalText: ' + str(ontotaltext)) totalmw = int(float(power[9]))/1000 Domoticz.Debug('DebugTotalkWh: ' + str(totalmw)) threshold = int(power[10])/1000 Domoticz.Debug('DebugThreshold: ' + str(threshold)) Devices[5].Update(0,"On for: "+ str(onfortext) + "<br>" + "On today: " + str(ontodaytext) + "<br>" + "On total: " + str(ontotaltext) + "<br>" + "Total kWh: " + str(totalmw) + "<br>" + "Standby threshold: " + str(threshold) + "<br>" + "Last change: " + str(lastchange)) if Parameters["Mode5"] == "YES": Domoticz.Debug("* Device 5 update called *") if threshold == int('8000')/1000: Devices[7].Update(1,"10") Domoticz.Debug("Standby: 'Default (8)'") else: Devices[7].Update(1,"20") Domoticz.Debug("Standby: 'Auto'") def updStatus(status): Domoticz.Debug("* updStatus called *") if not status: Domoticz.Error('False updStatus: ' + str(status)) return try: istate = int(status[0:1]) except ValueError: Domoticz.Error('Except updStatus: ' + str(status)) return Domoticz.Debug('DebugStatus: ' + str(status) + ' iState: ' + str(istate)) if istate == 1: if (1 in Devices): if Devices[1].nValue == 0 or Devices[1].nValue == 1: Domoticz.Debug("* Device 1 update called *, nValue: " + str(Devices[1].nValue) ) Devices[1].Update(1,"On") Domoticz.Debug("Device 1 updated to " + str(istate) + ", nValue: " + str(Devices[1].nValue) + " sValue: " + Devices[1].sValue) Domoticz.Debug("* Device 6 update called *, nValue: " + str(Devices[6].nValue) ) Devices[6].Update(10, "10") Domoticz.Debug("Device 6 updated to " + str(istate) + ", nValue: " + str(Devices[6].nValue) + " sValue: " + Devices[6].sValue) elif istate == 0: if (1 in Devices): if Devices[1].nValue == 1: Domoticz.Debug("* Device 1 update called *, nValue: " + str(Devices[1].nValue) ) Devices[1].Update(0,"Off") Domoticz.Debug("Device 1 updated to " + str(istate) + ", nValue: " + str(Devices[1].nValue) + " sValue: " + Devices[1].sValue) Domoticz.Debug("* Device 6 update called *, nValue: " + str(Devices[6].nValue) ) Devices[6].Update(0, "0") Domoticz.Debug("Device 6 updated to " + str(istate) + ", nValue: " + str(Devices[6].nValue) + " sValue: " + Devices[6].sValue) elif istate == 8: if (1 in Devices): if Devices[1].nValue == 0 or Devices[1].nValue == 1: Domoticz.Debug("* Device 1 update called *, nValue: " + str(Devices[1].nValue) ) Devices[1].Update(1,"On") Domoticz.Debug("Device 1 updated to " + str(istate) + ", nValue: " + str(Devices[1].nValue) + " sValue: " + Devices[1].sValue) Domoticz.Debug("* Device 6 update called *, nValue: " + str(Devices[6].nValue) ) Devices[6].Update(20, "20") Domoticz.Debug("Device 6 updated to " + str(istate) + ", nValue: " + str(Devices[6].nValue) + " sValue: " + Devices[6].sValue) if Parameters["Mode1"] == "YES": Domoticz.Debug("* Device 2 update called *") power = status.split('|') if Parameters["Mode1"] == "YES": currentmw = round(int(power[7])/1000) Domoticz.Debug('DebugkWh: ' + str(currentmw)) todaymw = int(power[8])/1000 Domoticz.Debug('DebugtoDay: ' + str(todaymw)) Devices[2].Update(0,str(currentmw) + "; " + str(todaymw)) # Synchronise images to match required Logo def UpdateImage(Unit, Logo): Domoticz.Debug("* updateImage called *, unit: " + str(Unit) ) Domoticz.Debug("Device current logo : " + str(Devices[Unit].Image) ) Domoticz.Debug("Device should have logo: " + str(Images[Logo].ID) ) if (Unit in Devices) and (Logo in Images): if (Devices[Unit].Image != Images[Logo].ID): Devices[Unit].Update(nValue=Devices[Unit].nValue, sValue=str(Devices[Unit].sValue), Image=Images[Logo].ID) Domoticz.Debug("Device " + str(Unit) + " image updated to " + Logo) return # Generic helper functions def LogMessage(Message): Domoticz.Debug(Message) 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("Internal ID: '" + str(Devices[x].ID) + "'") LogMessage("External ID: '" + str(Devices[x].DeviceID) + "'") 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)) LogMessage("Device Image ID: '" + str(Devices[x].Image) + "'") return def main(): import argparse parser = argparse.ArgumentParser(description='WeMo Insight control module for Python') parser.add_argument('action', choices=['on', 'off', 'status', 'name', 'signal', 'params', 'autopowerthreshold', 'setpowerthreshold', 'resetpowerthreshold'], help='Action') parser.add_argument('ip', help='IP address') parser.add_argument('port', nargs='?', default='49153', help='Port') args = parser.parse_args() IP=args.ip PORT=args.port insight = wemoInsight(IP, PORT) if args.action: print(insight.action(args.action)) if __name__ == '__main__': main()
- Attachments
-
- WeMoInsight.zip
- (6.14 KiB) Downloaded 169 times
Jump to
- General
- ↳ News & Updates
- ↳ General Discussion
- ↳ Bugs and Problems
- ↳ Other questions and discussions
- ↳ Suggestions
- Domoticz
- ↳ Installation, Compiling, Permissions, Security and Starting
- ↳ Cameras
- ↳ Switches and Scenes
- ↳ Utility
- ↳ Temperature and Weather
- ↳ Heating/cooling
- ↳ OpenTherm gateway
- ↳ Evohome
- ↳ Third party and supplementary tools
- ↳ Android
- ↳ iOS
- ↳ Windows
- ↳ Kodi (XBMC)
- ↳ Domoboard
- ↳ Dashticz
- ↳ Bugs
- ↳ Feature requests
- ↳ How-tos
- ↳ Node-RED
- ↳ Design, usability and languages
- ↳ Language / Translation
- Scripting & automation
- ↳ dzVents
- ↳ Bugs
- ↳ Examples & Solutions
- ↳ LUA
- ↳ Bash / PowerShell / Batch etc.
- ↳ Blockly
- ↳ Python
- ↳ PHP and all others
- Hardware and Protocols
- ↳ MQTT Auto Discovery
- ↳ Z-Wave
- ↳ Device information
- ↳ Zigbee
- ↳ Speech & Voice Systems
- ↳ 433 & 868 transceiver
- ↳ RFLink Transceiver
- ↳ Rfxcom Transceiver
- ↳ DIY Hardware and Protocols
- ↳ ESP8266
- ↳ PiFace
- ↳ Raspberry Pi GPIO ( WiringPi )
- ↳ MySensors
- ↳ 1-wire
- ↳ Others
- Community
- ↳ Sales, Deals and Bargains..
- ↳ Deals & bargains
- ↳ Forum feedback
- ↳ Show your projects
- ↳ Projects on other sites
Who is online
Users browsing this forum: No registered users and 1 guest