# Author: fjumelle # """

Enhances Selector


Selector to pilot other selectors.

Devices

Configuration

""" import Domoticz import ast import urllib.parse as parse import urllib.request as request import json DEVICE_TYPES = { 'Switch': { 'get' : 'type=devices&rid={0}', 'get_dict': 'Status', 'set' : 'type=command¶m=switchlight&idx={0}&switchcmd={1}' }, 'Selector': { 'get' : 'type=devices&rid={0}', 'get_dict': 'Level', 'set' : 'type=command¶m=switchlight&idx={0}&switchcmd=Set Level&level={1}' }, 'Thermostat': { 'get' : 'type=devices&rid={0}', 'get_dict': 'SetPoint', 'set' : 'type=command¶m=setsetpoint&idx={0}&setpoint={1}' }, } class BasePlugin: def __init__(self): self.debug = 0 self.heartbeat = 30 self.levels = 0 self.other_name = "?" self.devices = [] self.scanned_devices = [] self.configuration_ok = True return def onStart(self): #Debug level Domoticz.Debugging(self.debug) #Heart beat Domoticz.Heartbeat(self.heartbeat) #Levels definition levels = Parameters["Mode1"] self.levels = 1 for i in range(2, 7): value_param = Parameters["Mode" + str(i)].strip() if value_param != "": self.levels = self.levels + 1 levels = levels + ";" + value_param devices = levels.split(";") Domoticz.Debug("Levels: " + str(self.levels)) Domoticz.Debug(str(devices)) for level in range(0, self.levels): device = devices[level].split('=') if len(device) != 2: self.configuration_ok = False Domoticz.Error("Cannot find 'name=configuration' for the 'Device' #{}: '{}'.".format(level+1, devices[level])) try: list_devices = ast.literal_eval("[" + device[1] + "]") except: self.configuration_ok = False Domoticz.Error("Cannot find 'name=[device_id, device_value, device_type],[...]' for the 'Device' #{}: '{}'.".format(level+1, devices[level])) for conf in range (0, len(list_devices)): if len(list_devices[conf]) != 3: self.configuration_ok = False Domoticz.Error("Cannot find '[device_id, device_value, device_type]' in the configuration {} of the 'Device' #{}: '{}'.".format(conf+1, level+1, list_devices[conf])) if not isinstance(list_devices[conf][0], int): self.configuration_ok = False Domoticz.Error("'device_id' in the configuration {} of the 'Device' #{} shall be an integer: '{}'".format(conf+1, level+1, list_devices[conf][0])) if not list_devices[conf][2] in DEVICE_TYPES.keys(): self.configuration_ok = False Domoticz.Error("'device_type' in the configuration {} of the 'Device' #{} shall be {}: '{}'".format(conf+1, level+1, DEVICE_TYPES.keys(), list_devices[conf][2])) self.devices.append([device[0], list_devices, level*10]) #List of devices to scan for item in list_devices: self.scanned_devices.append("{}:{}".format(item[0], item[2])) #Add the 'unknown' devide self.devices.append([self.other_name, [], self.levels*10]) #Remove duplicated in the scanned_devices self.scanned_devices = list(dict.fromkeys(self.scanned_devices)) #Create device "Selector" if 1 not in Devices: Options = {"LevelActions": "||", "LevelNames": "|".join([item[0] for item in self.devices]), "LevelOffHidden": "false", "SelectorStyle": "0"} Domoticz.Device(Name="Selector", Unit=1, TypeName="Selector Switch", Switchtype=18, Options=Options, Used=1).Create() default_value = self.devices[self.levels][2] Devices[1].Update(nValue=int(default_value), sValue=str(default_value), TimedOut = 0) def onCommand(self, Unit, Command, Level, Hue): if self.configuration_ok: idx = int(Level//10) if Unit == 1: Devices[1].Update(nValue=int(Level), sValue=str(Level), TimedOut = 0) for device in self.devices[idx][1]: did = device[0] dvalue = device[1] dtype = device[2] Domoticz.Log("Device {} (type {}): Requested value {}".format(did, dtype, dvalue)) DomoticzAPI(DEVICE_TYPES[dtype]['set'].format(did, dvalue)) def onHeartbeat(self): if self.configuration_ok: #Get value of devices to scan scanned_devices = {} for item in self.scanned_devices: did, dtype = item.split(":") did = int(did) res = DomoticzAPI(DEVICE_TYPES[dtype]['get'].format(did)) value = res['result'][0][DEVICE_TYPES[dtype]['get_dict']] scanned_devices[did] = value Domoticz.Debug("scanned:" + str(scanned_devices)) for level in self.devices: status = True for device in level[1]: if device[1] != scanned_devices[device[0]]: status = False break if status: value = int(level[2]) if Devices[1].nValue != value: Devices[1].Update(nValue=value, sValue=str(value), TimedOut = 0) Domoticz.Debug("New status = " + str(level[0])) return global _plugin _plugin = BasePlugin() def onStart(): global _plugin _plugin.onStart() def onCommand(Unit, Command, Level, Hue): global _plugin _plugin.onCommand(Unit, Command, Level, Hue) def onHeartbeat(): global _plugin _plugin.onHeartbeat() def DomoticzAPI(APICall): resultJson = None url = "http://{}:{}/json.htm?{}".format(Parameters["Address"], Parameters["Port"], parse.quote(APICall, safe="&=")) Domoticz.Debug("Calling domoticz API: {}".format(url)) try: req = request.Request(url) if Parameters["Username"] != "": Domoticz.Debug("Add authentification for user {}".format(Parameters["Username"])) credentials = ('%s:%s' % (Parameters["Username"], Parameters["Password"])) encoded_credentials = base64.b64encode(credentials.encode('ascii')) req.add_header('Authorization', 'Basic %s' % encoded_credentials.decode("ascii")) response = request.urlopen(req) if response.status == 200: resultJson = json.loads(response.read().decode('utf-8')) if resultJson["status"] != "OK": Domoticz.Error("Domoticz API returned an error: status = {}".format(resultJson["status"])) resultJson = None else: Domoticz.Error("Domoticz API: http error = {}".format(response.status)) except Exception as err: Domoticz.Error("Error calling '{}'".format(url)) Domoticz.Error(str(err)) return resultJson