<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.domoticz.com/index.php?action=history&amp;feed=atom&amp;title=Plugins%2FPlugwise</id>
	<title>Plugins/Plugwise - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.domoticz.com/index.php?action=history&amp;feed=atom&amp;title=Plugins%2FPlugwise"/>
	<link rel="alternate" type="text/html" href="https://wiki.domoticz.com/index.php?title=Plugins/Plugwise&amp;action=history"/>
	<updated>2026-09-20T06:33:41Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.0</generator>
	<entry>
		<id>https://wiki.domoticz.com/index.php?title=Plugins/Plugwise&amp;diff=18368&amp;oldid=prev</id>
		<title>Walter vl at 15:44, 11 December 2023</title>
		<link rel="alternate" type="text/html" href="https://wiki.domoticz.com/index.php?title=Plugins/Plugwise&amp;diff=18368&amp;oldid=prev"/>
		<updated>2023-12-11T15:44:56Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This plugin communicates with the Plugwise Stretch 3.0 (End of Life!).  &lt;br /&gt;
&lt;br /&gt;
Unlike the plugwise2py, which communicates directly with the USB stick. &lt;br /&gt;
&lt;br /&gt;
Features:&lt;br /&gt;
&lt;br /&gt;
*Basic switch operations&lt;br /&gt;
*Logging op power consumption.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
#Create a folder under the domoticz\plugins, called Plugwise. Another name will require a change in the python code.&lt;br /&gt;
#Create a file &amp;quot;plugin.py&amp;quot; in this folder, containing the code below (in plugin.txt, as the form does not allow .py files).3&lt;br /&gt;
#Restart domoticz&lt;br /&gt;
#Add hardware (Plugwise should be in the hardware list). Setup parameters....&lt;br /&gt;
#Add unused devices to the UI.&lt;br /&gt;
&lt;br /&gt;
Devices should be added to the setup upon start of the plugin.&lt;br /&gt;
&lt;br /&gt;
Note: In the plugin folder, a file is created &amp;#039;devices.json&amp;#039;. This file contains the link between circle/sensor and unitid in domoticz. Do _not_ deleted (unused) devices in domoticz or this file if you do not know what you are doing as this will case a mismatch between plugwise/plugin/domoticz. Also, if debug is enabled, a log.txt file is created. &lt;br /&gt;
&lt;br /&gt;
==Reset==&lt;br /&gt;
If you made a mess: delete the &amp;#039;hardware&amp;#039;, delete the devices.json and repeat from step 4.&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
==Plugin==&lt;br /&gt;
 # Plugwise stretch 3.x plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; Author: Gerrit Hulleman&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 &amp;lt;plugin key=&amp;quot;PlugwiseStretch&amp;quot; name=&amp;quot;Plugwise stretch 3.x plugin&amp;quot; author=&amp;quot;Gerrit Hulleman&amp;quot; version=&amp;quot;1.0.3&amp;quot; wikilink=&amp;quot;&amp;lt;nowiki&amp;gt;http://www.domoticz.com/wiki/plugins/plugin.html&amp;lt;/nowiki&amp;gt;&amp;quot; externallink=&amp;quot;&amp;lt;nowiki&amp;gt;https://www.google.com/&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   &amp;lt;description&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;h2&amp;gt;Plugwise stretch plugin&amp;lt;/h2&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Uses the stretch to communicate with circles to read consumption (not total power usage) and toggle the relay. &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;h3&amp;gt;Features&amp;lt;/h3&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;ul style=&amp;quot;list-style-type:square&amp;quot;&amp;gt;&lt;br /&gt;
                 &amp;lt;li&amp;gt;Toggle circle/stealth relays&amp;lt;/li&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           &amp;lt;nowiki&amp;gt;&amp;lt;li&amp;gt;Read circle/stealth power usage&amp;lt;/li&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;h3&amp;gt;Recent history&amp;lt;/h3&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Version 1.0.0 - initial&lt;br /&gt;
 		Version 1.0.2 - added try/catch handling and dumping&lt;br /&gt;
 		Version 1.0.3 - removed modelname from code (not used)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   &amp;lt;/description&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   &amp;lt;params&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;param field=&amp;quot;Address&amp;quot; label=&amp;quot;Stretch host&amp;quot; width=&amp;quot;200px&amp;quot; required=&amp;quot;true&amp;quot; default=&amp;quot;stretch08126a.fritz.box&amp;quot;/&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;param field=&amp;quot;Username&amp;quot; label=&amp;quot;Stretch username&amp;quot; width=&amp;quot;200px&amp;quot; required=&amp;quot;true&amp;quot; default=&amp;quot;stretch&amp;quot;/&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;param field=&amp;quot;Password&amp;quot; label=&amp;quot;Stretch password/id&amp;quot; width=&amp;quot;200px&amp;quot; required=&amp;quot;true&amp;quot; default=&amp;quot;&amp;quot; password=&amp;quot;true&amp;quot;/&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;param field=&amp;quot;Mode1&amp;quot; label=&amp;quot;Interval&amp;quot; width=&amp;quot;200px&amp;quot; required=&amp;quot;true&amp;quot; default=&amp;quot;10&amp;quot;/&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;param field=&amp;quot;Mode6&amp;quot; label=&amp;quot;Debug&amp;quot; width=&amp;quot;75px&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           &amp;lt;options&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               &amp;lt;nowiki&amp;gt;&amp;lt;option label=&amp;quot;True&amp;quot; value=&amp;quot;Debug&amp;quot;/&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               &amp;lt;nowiki&amp;gt;&amp;lt;option label=&amp;quot;False&amp;quot; value=&amp;quot;Normal&amp;quot;  default=&amp;quot;true&amp;quot; /&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           &amp;lt;/options&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &amp;lt;nowiki&amp;gt;&amp;lt;/param&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   &amp;lt;/params&amp;gt;&lt;br /&gt;
 &amp;lt;/plugin&amp;gt;&lt;br /&gt;
 &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 import json&lt;br /&gt;
 import os               #for file IO operations&lt;br /&gt;
 import urllib&lt;br /&gt;
 import urllib.request&lt;br /&gt;
 import base64&lt;br /&gt;
 import xml.etree.ElementTree as ET&lt;br /&gt;
 import time&lt;br /&gt;
 import Domoticz&lt;br /&gt;
 &lt;br /&gt;
 class BasePlugin:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   enabled = False&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   debugMode = True&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   devicesfile = &amp;#039;plugins/Plugwise/devices.json&amp;#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   stretchHost = &amp;#039;stretch08126a.fritz.box&amp;#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   stretchUsername = &amp;#039;stretch&amp;#039;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   stretchPassword = &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   heartbeat = 10&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   unitId = 0&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   serviceIdApplianceIdMap = {} #contains a serviceId -&amp;gt; applianceId key/value map so the module can be related to the appliance. &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   moduleIdDataMap = {} #contains module id (applianceId, mac address)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   applianceIdDataMap = {} #Contains appliance data (name)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   moduleDeviceKeyToUnit = {} #Contains  the unique key (moduleId+sensor name) and Domoticz unitId (for update)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def __init__(self):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #self.var = 123&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onStart(self):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Loading parameters&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #if &amp;#039;Parameters&amp;#039; in locals(): # in case of a debug, do not load the parameters. &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.stretchHost = Parameters[&amp;quot;Address&amp;quot;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.stretchPassword = Parameters[&amp;quot;Username&amp;quot;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.stretchPassword = Parameters[&amp;quot;Password&amp;quot;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.heartbeat = Parameters[&amp;quot;Mode1&amp;quot;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if Parameters[&amp;quot;Mode6&amp;quot;] != &amp;quot;Debug&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           Domoticz.Debugging(0)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.debugMode = False;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Loading appliances from stretch&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # A call is made to the stretch to load the appliances. An appliance is a name and one/more actions/sensors (like the basic: relay on/off and power consumptions).&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #  a modules is a single device (also switches / sensors) and the only link between appliances and modules are the id&amp;#039;s of the sensors in it&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       data = self.callStretch(&amp;#039;core/appliances&amp;#039;)        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       root = ET.fromstring(data)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Processing appliances&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       for child in root.findall(&amp;quot;./appliance&amp;quot;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           name = child.find(&amp;#039;name&amp;#039;).text&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           applianceId = child.attrib[&amp;#039;id&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               self.logMessage(&amp;quot;Appliance found: &amp;quot;+applianceId+&amp;#039; - &amp;#039;+name)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.applianceIdDataMap[applianceId] = { &amp;#039;name&amp;#039; : name }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # find all services (relay/power usage etc.) linked to the appliance. This is the link to the module later on&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           for service in child.findall(&amp;quot;./services/*&amp;quot;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               serviceId = service.attrib[&amp;#039;id&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               self.serviceIdApplianceIdMap[serviceId] = applianceId        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # All known appliance are stored in the serviceIdApplianceIdMap, so the modules can be linked to the appliance based on the services they share&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # We might want to timeout the cached appliances, as new devices are not automatically added unles the plugin is restarted. Optimalisation&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Loading mapped devices from config file&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # Load mapped modules / devices from file&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #  this wil link services to existing devices, if any. &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if os.path.exists(self.devicesfile):    &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           with open(self.devicesfile) as json_file:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               data = json.load(json_file)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               for device in data[&amp;#039;devices&amp;#039;]:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       self.logMessage(json.dumps(device))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   self.moduleDeviceKeyToUnit[device[&amp;#039;devicekey&amp;#039;]]= {&amp;#039;unit&amp;#039; : device[&amp;#039;domoticzunit&amp;#039;],&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                                                                     &amp;#039;applianceId&amp;#039; : device[&amp;#039;applianceid&amp;#039;],&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                                                                     &amp;#039;name&amp;#039;: device[&amp;#039;name&amp;#039;]}&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #print(p)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;{} devices loaded from configuration file&amp;quot;.format(len(self.moduleDeviceKeyToUnit)))        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           DumpConfigToLog()&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # find all devices in domoticz to find the last-used-unitid. In case new devices are created&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       for x in Devices:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           if (x &amp;gt; self.unitId):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               self.unitId = x&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:                &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;Last unitId : &amp;quot;+str(self.unitId))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;Heartbeat : &amp;quot;+str(self.heartbeat))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Heartbeat(int(self.heartbeat))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Plugin operational&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onStop(self):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;onStop called&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onConnect(self, Connection, Status, Description):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;onConnect called&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onMessage(self, Connection, Data):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;onMessage called&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onCommand(self, Unit, Command, Level, Hue):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;onCommand called for Unit &amp;quot; + str(Unit) + &amp;quot;: Parameter &amp;#039;&amp;quot; + str(Command) + &amp;quot;&amp;#039;, Level: &amp;quot; + str(Level))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #2019-11-04 16:08:13.300 (testplugwise) onCommand called for Unit 14: Parameter &amp;#039;Off&amp;#039;, Level: 0&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # TEST : only relay&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       switchstatus = Command.lower() # on/off&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       applianceId = self.getApplianceIdFromUnit(Unit)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if applianceId == &amp;quot;&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           Domoticz.Error(&amp;quot;Unable to find appliance for unit {}&amp;quot;.format(Unit))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           return&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       url= &amp;#039;&amp;lt;nowiki&amp;gt;http://{host}/core/appliances;id={applianceId}/relay&amp;#039;.format(host=self.stretchHost&amp;lt;/nowiki&amp;gt;, applianceId=applianceId)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       postdata = &amp;quot;&amp;lt;relay&amp;gt;&amp;lt;state&amp;gt;&amp;quot; + switchstatus + &amp;quot;&amp;lt;/state&amp;gt;&amp;lt;/relay&amp;gt;&amp;quot;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;Call to: &amp;quot;+url)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       userAndPass = &amp;#039;{}:{}&amp;#039;.format(self.stretchUsername, self.stretchPassword)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       userAndPassBase64 = base64.b64encode(userAndPass.encode(&amp;#039;ascii&amp;#039;)).decode(&amp;#039;ascii&amp;#039;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #print (userAndPassBase64)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       headers = {&amp;#039;Authorization&amp;#039;: &amp;quot;Basic %s&amp;quot; % userAndPassBase64,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                  &amp;quot;Content-Type&amp;quot;:&amp;quot;application/xml&amp;quot;}&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       data = &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       req = urllib.request.Request(url, postdata.encode(&amp;#039;ascii&amp;#039;), headers)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       try:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           with urllib.request.urlopen(req) as response:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               if response.getcode() != 202:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   self.logMessage(&amp;quot;Response on relay: {}&amp;quot;.format(response.getcode()))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               data = response.read()            &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       except urllib.error.HTTPError as e:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # Return code error (e.g. 404, 501, ...)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # ...&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;#039;HTTPError: {}&amp;#039;.format(e.code))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       except urllib.error.URLError as e:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # Not an HTTP-specific error (e.g. connection refused)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # ...&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;#039;URLError: {}&amp;#039;.format(e.reason))        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;     &lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;Notification: &amp;quot; + Name + &amp;quot;,&amp;quot; + Subject + &amp;quot;,&amp;quot; + Text + &amp;quot;,&amp;quot; + Status + &amp;quot;,&amp;quot; + str(Priority) + &amp;quot;,&amp;quot; + Sound + &amp;quot;,&amp;quot; + ImageFile)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onDisconnect(self, Connection):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def onHeartbeat(self):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;onHeartbeat called&amp;quot;)        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       data = self.callStretch(&amp;#039;core/modules&amp;#039;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #    self.logMessage(&amp;quot;Modules data: &amp;quot; + str(data, &amp;#039;utf-8&amp;#039;))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       root = ET.fromstring(data)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       for child in root.findall(&amp;quot;./module&amp;quot;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           try:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               moduleData = self.getModuleDataFromNode(child)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               for service in child.findall(&amp;quot;./services/*&amp;quot;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   name = service.tag&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #get device. Unique id: moduleId / name&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   deviceKey = moduleData[&amp;#039;moduleId&amp;#039;]+&amp;#039;.&amp;#039;+name&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   deviceUnitId = self.getDeviceUnit(deviceKey)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #if (name == &amp;quot;electricity_interval_meter&amp;quot;): # power usage? - not used at this moment&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #    valDouble = 0&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #    for measurement in service.findall(&amp;#039;./measurement&amp;#039;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #        multiplier = 1 #default consumed&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #        if measurement.attrib[&amp;#039;directionality&amp;#039;] == &amp;#039;produced&amp;#039;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #            multiplier = -1&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #        valDouble += float(measurement.text) * multiplier&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   #    print (moduleData[&amp;#039;name&amp;#039;], &amp;quot;interval&amp;quot;, name, valDouble)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   if (name == &amp;quot;relay&amp;quot;):  # actual relay for on/off purposes&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       relayMeasurement = service.find(&amp;#039;measurement&amp;#039;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       state = &amp;quot;On&amp;quot; if relayMeasurement.text == &amp;quot;on&amp;quot; else &amp;quot;Off&amp;quot;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       logDateTime = relayMeasurement.attrib[&amp;#039;log_date&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       #self.logMessage(moduleData[&amp;#039;name&amp;#039;]+&amp;#039;,&amp;#039;+name+&amp;#039;,&amp;#039;+state+&amp;#039;,&amp;#039;+logDateTime+&amp;#039;,&amp;#039;+str(deviceUnitId))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       if deviceUnitId == 0:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           # create device&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           applianceName = moduleData[&amp;#039;name&amp;#039;];&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           applianceId = moduleData[&amp;#039;applianceId&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           self.logMessage(&amp;quot;Name, id: &amp;quot;+applianceName+&amp;#039;,&amp;#039;+applianceId)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           deviceUnitId = self.createDevice(applianceName, &amp;quot;Switch&amp;quot;, deviceKey, applianceId)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       #self.logMessage(json.dumps(moduleData))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       # the sub will check it the device needs updating&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       self.updateDevice(deviceUnitId, 1 if state == &amp;quot;On&amp;quot; else 0, state, False)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   if (name == &amp;quot;electricity_point_meter&amp;quot;): #current voltage, check if update needed&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       valDouble = 0&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       logDateTime = &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       # this service has two measurements: produced and consumed. The logdate seemstime to be in sync&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       for measurement in service.findall(&amp;#039;./measurement&amp;#039;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           multiplier = 1 #default consumed&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           if measurement.attrib[&amp;#039;directionality&amp;#039;] == &amp;#039;produced&amp;#039;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                               multiplier = -1&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           valDouble += float(measurement.text) * multiplier&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           logDateTime = measurement.attrib[&amp;#039;log_date&amp;#039;] &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                       if (not name in moduleData) or (moduleData[name] != logDateTime): # check if the module has been updated (logDateTime stored in moduleData[&amp;#039;electricity_point_meter&amp;#039;])&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           #print (moduleData[&amp;#039;name&amp;#039;], &amp;quot;point&amp;quot;, name, valDouble)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           moduleData[name] = logDateTime&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           if deviceUnitId == 0:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                               # create device&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                               deviceUnitId = self.createDevice(moduleData[&amp;#039;name&amp;#039;], &amp;quot;kWh&amp;quot;, deviceKey, moduleData[&amp;#039;applianceId&amp;#039;])&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                           self.updateDevice(deviceUnitId, 0, str(valDouble)+&amp;#039;;0&amp;#039;, True) # force update, even if the voltage has no changed. &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           except :&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               # exception on child, log&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               self.logMessage(&amp;quot;Exception caught&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   self.logMessage(ET.tostring(child).decode(&amp;#039;utf-8&amp;#039;))&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def createDevice(self, Name, Type, DeviceKey, ApplianceId):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.unitId += 1&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Create device: &amp;quot;+Name+&amp;quot;,&amp;quot;+Type+&amp;quot;,&amp;quot;+DeviceKey)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       newDevice = Domoticz.Device(Name=Name, Unit=self.unitId, TypeName=Type)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       newDevice.Create()&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.logMessage(&amp;quot;Add to map: &amp;quot;+str(newDevice.Unit))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.moduleDeviceKeyToUnit[DeviceKey]={&amp;#039;unit&amp;#039; : newDevice.Unit, &amp;#039;applianceId&amp;#039;: ApplianceId, &amp;#039;name&amp;#039;: Name}&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # save data to config file, as onStop is not called on restart.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       data = {}&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       devices = []&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       for keyVal in self.moduleDeviceKeyToUnit:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;quot;Key found: &amp;quot;+keyVal)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           devices.append({&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               &amp;#039;devicekey&amp;#039;: keyVal,&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               &amp;#039;domoticzunit&amp;#039;: self.moduleDeviceKeyToUnit[keyVal][&amp;#039;unit&amp;#039;],&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               &amp;#039;applianceid&amp;#039;: self.moduleDeviceKeyToUnit[keyVal][&amp;#039;applianceId&amp;#039;],&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               &amp;#039;name&amp;#039;: self.moduleDeviceKeyToUnit[keyVal][&amp;#039;name&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           })&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       data[&amp;#039;devices&amp;#039;] = devices    &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       with open(self.devicesfile, &amp;#039;w+&amp;#039;) as outfile:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           json.dump(data, outfile)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return newDevice.Unit                 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def callStretch(self, SubUrl):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       url= &amp;#039;&amp;lt;nowiki&amp;gt;http://{host}/{subUrl}&amp;#039;.format(host=self.stretchHost&amp;lt;/nowiki&amp;gt;, subUrl=SubUrl)        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       userAndPass = &amp;#039;{}:{}&amp;#039;.format(self.stretchUsername, self.stretchPassword)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       userAndPassBase64 = base64.b64encode(userAndPass.encode(&amp;#039;ascii&amp;#039;)).decode(&amp;#039;ascii&amp;#039;)        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       headers = {&amp;#039;Authorization&amp;#039;: &amp;quot;Basic %s&amp;quot; % userAndPassBase64}&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       data = &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       req = urllib.request.Request(url, None, headers)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       try:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           with urllib.request.urlopen(req) as response:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               if response.getcode() != 200:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   self.logMessage(&amp;quot;Response on call: {}&amp;quot;.format(response.getcode()))                &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               data = response.read()            &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       except urllib.error.HTTPError as e:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # Return code error (e.g. 404, 501, ...)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;#039;HTTPError: {}&amp;#039;.format(e.code))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       except urllib.error.URLError as e:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           # Not an HTTP-specific error (e.g. connection refused)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           self.logMessage(&amp;#039;URLError: {}&amp;#039;.format(e.reason))        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return data&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   # return: {applianceId, moduleId, mac, name} for a given module&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def getModuleDataFromNode(self, ModuleNode):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       moduleId = ModuleNode.attrib[&amp;#039;id&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # For this logic, a module is an appliance. The link between a module and appliance is the services they share, unique service id&amp;#039;s&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if (moduleId in self.moduleIdDataMap):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           return self.moduleIdDataMap[moduleId];&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       applianceId = &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # modelName = ModuleNode.find(&amp;#039;vendor_model&amp;#039;).attrib[&amp;#039;model_name&amp;#039;] # name: scan, &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       for service in ModuleNode.findall(&amp;quot;./services/*&amp;quot;):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           serviceId = service.attrib[&amp;#039;id&amp;#039;]            &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           if (serviceId in self.serviceIdApplianceIdMap):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               applianceId = self.serviceIdApplianceIdMap[serviceId]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               break&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # Get addional information: MAC,appliance name&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       macNode = ModuleNode.find(&amp;#039;./protocols/network_router/mac_address&amp;#039;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       macAddress = &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       applianceName = &amp;#039;-not applicable-&amp;#039; # not all modules have an appliance. Such as scans / switches&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if (macNode):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           macAddress = macNode.text&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if applianceId in self.applianceIdDataMap:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           applianceName = self.applianceIdDataMap[applianceId][&amp;#039;name&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       moduleData = { &amp;#039;applianceId&amp;#039; : applianceId, &amp;#039;moduleId&amp;#039; : moduleId, &amp;#039;mac&amp;#039; : macAddress, &amp;#039;name&amp;#039; : applianceName }&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       self.moduleIdDataMap[moduleId] = moduleData        &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #print (&amp;quot;Module:&amp;quot;, moduleId, modelName, applianceName)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return moduleData        &lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   # return the unit (id from domoticz) for a given devicekey (combi of moduleid + type of service)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   #  return 0 if not found&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def getDeviceUnit(self, DeviceKey):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if DeviceKey in self.moduleDeviceKeyToUnit:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           return self.moduleDeviceKeyToUnit[DeviceKey][&amp;#039;unit&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return 0&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   # return thee applianceId for a given unit (id from domoticz)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   #  note: multiple domoticz devices can be the same module/appliance (plug is both a switch as a power monitor)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   #  note: not indexed, just enumerator through the moduledevicekeys to find the unit and return the appliance. Only called on Command, so not a big impact on performance&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def getApplianceIdFromUnit(self, Unit):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       for key, value in self.moduleDeviceKeyToUnit.items():&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           if value[&amp;#039;unit&amp;#039;] == Unit:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               return value[&amp;#039;applianceId&amp;#039;]&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       return &amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   # Update the given unit (domoticz Id), only if the value differs from previous or forced&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def updateDevice(self, Unit, nValue, sValue, forceUpdate):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       # Make sure that the Domoticz device still exists (they can be deleted) before updating it&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #self.logMessage(&amp;quot;Update &amp;quot;+str(nValue)+&amp;quot;:&amp;#039;&amp;quot;+str(sValue)+&amp;quot;&amp;#039; (&amp;quot;+str(Unit)+&amp;quot;)&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if (Unit in Devices):            &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           if forceUpdate or (Devices[Unit].nValue != nValue) or (Devices[Unit].sValue != sValue):                &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               Devices[Unit].Update(nValue=nValue, sValue=str(sValue))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;               if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;                   self.logMessage(&amp;quot;Update do &amp;quot;+str(nValue)+&amp;quot;:&amp;#039;&amp;quot;+str(sValue)+&amp;quot;&amp;#039; (&amp;quot;+Devices[Unit].Name+&amp;quot;)&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   def logMessage(self, Message):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       #if &amp;#039;Domoticz&amp;#039;in locals():&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if self.debugMode:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           f= open(&amp;quot;plugins/Plugwise/log.txt&amp;quot;,&amp;quot;a+&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           f.write(Message+&amp;#039;\r\n&amp;#039;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(Message)&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       &lt;br /&gt;
 global _plugin&lt;br /&gt;
 _plugin = BasePlugin()&lt;br /&gt;
 &lt;br /&gt;
 def onStart():&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onStart()&lt;br /&gt;
 &lt;br /&gt;
 def onStop():&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onStop()&lt;br /&gt;
 &lt;br /&gt;
 def onConnect(Connection, Status, Description):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onConnect(Connection, Status, Description)&lt;br /&gt;
 &lt;br /&gt;
 def onMessage(Connection, Data):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onMessage(Connection, Data)&lt;br /&gt;
 &lt;br /&gt;
 def onCommand(Unit, Command, Level, Hue):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onCommand(Unit, Command, Level, Hue)&lt;br /&gt;
 &lt;br /&gt;
 def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)&lt;br /&gt;
 &lt;br /&gt;
 def onDisconnect(Connection):&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onDisconnect(Connection)&lt;br /&gt;
 &lt;br /&gt;
 def onHeartbeat():&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   global _plugin&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   _plugin.onHeartbeat()&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   # Generic helper functions&lt;br /&gt;
 def DumpConfigToLog():&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   for x in Parameters:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       if Parameters[x] != &amp;quot;&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;           Domoticz.Log( &amp;quot;&amp;#039;&amp;quot; + x + &amp;quot;&amp;#039;:&amp;#039;&amp;quot; + str(Parameters[x]) + &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   Domoticz.Log(&amp;quot;Device count: &amp;quot; + str(len(Devices)))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   for x in Devices:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device:           &amp;quot; + str(x) + &amp;quot; - &amp;quot; + str(Devices[x]))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device ID:       &amp;#039;&amp;quot; + str(Devices[x].ID) + &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device UnitID:   &amp;#039;&amp;quot; + str(Devices[x].Unit) + &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device DeviceID: &amp;#039;&amp;quot; + str(Devices[x].DeviceID) + &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device Name:     &amp;#039;&amp;quot; + Devices[x].Name + &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device nValue:    &amp;quot; + str(Devices[x].nValue))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device sValue:   &amp;#039;&amp;quot; + Devices[x].sValue + &amp;quot;&amp;#039;&amp;quot;)&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;       Domoticz.Log(&amp;quot;Device LastLevel: &amp;quot; + str(Devices[x].LastLevel))&lt;br /&gt;
 &amp;lt;nowiki&amp;gt; &amp;lt;/nowiki&amp;gt;   return&lt;/div&gt;</summary>
		<author><name>Walter vl</name></author>
	</entry>
</feed>