diff --git a/pyduofern/duofern.py b/pyduofern/duofern.py index 47c4118..ef32191 100644 --- a/pyduofern/duofern.py +++ b/pyduofern/duofern.py @@ -96,11 +96,9 @@ def __init__(self, send_hook=None, asyncio=False, changes_callback=None): def add_device(self, code, name=None): if name is None: - name = code + name = len(self.modules['by_code']) logger.debug("adding {}".format(code)) self.modules['by_code'][code] = {'name': name} - if len(code) == 8: - self.modules['by_code'][code]['chanNo'] = code[6:] def del_device(self, code, name=None): if name is None: @@ -109,14 +107,26 @@ def del_device(self, code, name=None): if code in self.modules['by_code']: del self.modules['by_code'][code] - def update_state(self, hash, key, value, trigger=None): - hash[key] = value - if self.changes_callback: + def update_state(self, code, key, value, trigger=None, channel=None): + """ + + :param code: duofern system code + :param key: some arbitrary key that should be set in the state dict + :param value: the corresponding value + :param trigger: whether or not to trigger + :param channel: if this is a multichannel actor: The channel the key should be set for + :return: + """ + if channel is None: + self.modules['by_code'][code][key] = value + else: + self.modules['by_code'][code][key+"_"+channel] = value + if self.changes_callback and trigger: self.changes_callback() - def delete_state(self, hash, key): - if key in hash: - del hash[key] + def delete_state(self, code, key): + if key in self.modules['by_code'][code]: + del self.modules['by_code'][code][key] def parse(self, msg): code = msg[30:36] @@ -152,15 +162,15 @@ def parse(self, msg): # Device paired if msg[0:4] == "0602": - self.update_state(hash, "state", "paired", "1") + self.update_state(code, "state", "paired", "1", channel=channel) # del hash['READINGS']['unpaired'] logger.info("DUOFERN device paired, ID {}".format(code)) # Device unpaired elif (msg[0:4] == "0603"): readingsBeginUpdate(hash) - self.update_state(hash, "unpaired", 1, "1") - self.update_state(hash, "state", "unpaired", "1") + self.update_state(code, "unpaired", 1, "1", channel=channel) + self.update_state(code, "state", "unpaired", "1", channel=channel) self.del_device(code) # readingsEndUpdate(hash, 1) # Notify is done by Dispatch logger.warning("DUOFERN device unpaired, code {}".format(code)) @@ -170,14 +180,14 @@ def parse(self, msg): format = msg[6:6 + 2] ver = msg[24:24 + 1] + msg[25:25 + 1] - self.update_state(hash, "version", ver, "0") + self.update_state(code, "version", ver, "0", channel=channel) # RemoveInternalTimer(hash) # del hash['helper']['timeout'] # Bewegungsmelder, Wettersensor, Mehrfachwandtaster not tested yet if code[0:2] in ("65", "69", "74"): # pragma: no cover - self.update_state(hash, "state", "OK", "1") + self.update_state(code, "state", "OK", "1", channel=channel) module_definition01 = self.modules['by_code'][code + "01"] if not module_definition01: DoTrigger("global", "UNDEFINED DUOFERN_code_actor DUOFERN code01") @@ -185,20 +195,12 @@ def parse(self, msg): # Universalaktor -- not tested yet elif code[0:2] == "43": # pragma: no cover - self.update_state(hash, "state", "OK", "1") - try: - module_definition01 = self.modules['by_code'][code + "01"] - except KeyError: - self.add_device(code + "01") - logger.info("detected unknown device, ID={}".format(code + "01")) - module_definition01 = self.modules['by_code'][code + "01"] + self.update_state(code, "state", "OK", "1", channel=channel) + module_definition01 = self.modules['by_code'][code] + if not module_definition01: + DoTrigger("global", "UNDEFINED DUOFERN_code+_01 DUOFERN code+01") - try: - module_definition02 = self.modules['by_code'][code + "02"] - except KeyError: - self.add_device(code + "02") - logger.info("detected unknown device, ID={}".format(code + "02")) - module_definition02 = self.modules['by_code'][code + "02"] + module_definition02 = None if module_definition01: hash = module_definition01 @@ -222,18 +224,18 @@ def parse(self, msg): state = "closed" if (pos == 100) else pos readingsBeginUpdate(hash) - self.update_state(hash, "ventilatingPosition", ventPos, "1") - self.update_state(hash, "ventilatingMode", ventMode, "1") - self.update_state(hash, "sunPosition", sunPos, "1") - self.update_state(hash, "sunMode", sunMode, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "sunAutomatic", sunAuto, "1") - self.update_state(hash, "dawnAutomatic", dawnAuto, "1") - self.update_state(hash, "duskAutomatic", duskAuto, "1") - self.update_state(hash, "manualMode", manualMode, "1") - self.update_state(hash, "position", pos, "1") - self.update_state(hash, "state", state, "1") - self.update_state(hash, "moving", "stop", "1") + self.update_state(code, "ventilatingPosition", ventPos, "1", channel=channel) + self.update_state(code, "ventilatingMode", ventMode, "1", channel=channel) + self.update_state(code, "sunPosition", sunPos, "1", channel=channel) + self.update_state(code, "sunMode", sunMode, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "sunAutomatic", sunAuto, "1", channel=channel) + self.update_state(code, "dawnAutomatic", dawnAuto, "1", channel=channel) + self.update_state(code, "duskAutomatic", duskAuto, "1", channel=channel) + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + self.update_state(code, "position", pos, "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) + self.update_state(code, "moving", "stop", "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch # Universal Aktor, Steckdosenaktor, Troll Comfort DuoFern (Lichtmodus) not tested yet @@ -254,17 +256,17 @@ def parse(self, msg): state = "on" if (level == 100) else level readingsBeginUpdate(hash) - self.update_state(hash, "sunMode", sunMode, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "sunAutomatic", sunAuto, "1") - self.update_state(hash, "dawnAutomatic", dawnAuto, "1") - self.update_state(hash, "duskAutomatic", duskAuto, "1") - self.update_state(hash, "manualMode", manualMode, "1") - self.update_state(hash, "modeChange", modeChange, "1") - self.update_state(hash, "stairwellFunction", stairwellFunction, "1") - self.update_state(hash, "stairwellTime", stairwellTime, "1") - self.update_state(hash, "level", level, "1") - self.update_state(hash, "state", state, "1") + self.update_state(code, "sunMode", sunMode, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "sunAutomatic", sunAuto, "1", channel=channel) + self.update_state(code, "dawnAutomatic", dawnAuto, "1", channel=channel) + self.update_state(code, "duskAutomatic", duskAuto, "1", channel=channel) + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + self.update_state(code, "modeChange", modeChange, "1", channel=channel) + self.update_state(code, "stairwellFunction", stairwellFunction, "1", channel=channel) + self.update_state(code, "stairwellTime", stairwellTime, "1", channel=channel) + self.update_state(code, "level", level, "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) readingsEndUpdate(hash, 1) if module_definition02: @@ -286,17 +288,17 @@ def parse(self, msg): state = "on" if (level == 100) else level readingsBeginUpdate(hash) - self.update_state(hash, "sunMode", sunMode, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "sunAutomatic", sunAuto, "1") - self.update_state(hash, "dawnAutomatic", dawnAuto, "1") - self.update_state(hash, "duskAutomatic", duskAuto, "1") - self.update_state(hash, "manualMode", manualMode, "1") - self.update_state(hash, "modeChange", modeChange, "1") - self.update_state(hash, "stairwellFunction", stairwellFunction, "1") - self.update_state(hash, "stairwellTime", stairwellTime, "1") - self.update_state(hash, "level", level, "1") - self.update_state(hash, "state", state, "1") + self.update_state(code, "sunMode", sunMode, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "sunAutomatic", sunAuto, "1", channel=channel) + self.update_state(code, "dawnAutomatic", dawnAuto, "1", channel=channel) + self.update_state(code, "duskAutomatic", duskAuto, "1", channel=channel) + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + self.update_state(code, "modeChange", modeChange, "1", channel=channel) + self.update_state(code, "stairwellFunction", stairwellFunction, "1", channel=channel) + self.update_state(code, "stairwellTime", stairwellTime, "1", channel=channel) + self.update_state(code, "level", level, "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch elif format == "23": pos = int(msg[22:22 + 2], 16) & 0x7F @@ -331,47 +333,47 @@ def parse(self, msg): state = "closed" if (pos == 100) else state readingsBeginUpdate(hash) - self.update_state(hash, "ventilatingPosition", ventPos, "1") - self.update_state(hash, "ventilatingMode", ventMode, "1") - self.update_state(hash, "sunPosition", sunPos, "1") - self.update_state(hash, "sunMode", sunMode, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "sunAutomatic", sunAuto, "1") - self.update_state(hash, "dawnAutomatic", dawnAuto, "1") - self.update_state(hash, "duskAutomatic", duskAuto, "1") - self.update_state(hash, "manualMode", manualMode, "1") - self.update_state(hash, "windAutomatic", windAuto, "1") - self.update_state(hash, "windMode", windMode, "1") - self.update_state(hash, "windDirection", windDir, "1") - self.update_state(hash, "rainAutomatic", rainAuto, "1") - self.update_state(hash, "rainMode", rainMode, "1") - self.update_state(hash, "rainDirection", rainDir, "1") - self.update_state(hash, "runningTime", runningTime, "1") - self.update_state(hash, "motorDeadTime", deadTimes[deadTime], "1") - self.update_state(hash, "position", pos, "1") - self.update_state(hash, "reversal", reversal, "1") - self.update_state(hash, "blindsMode", blindsMode, "1") + self.update_state(code, "ventilatingPosition", ventPos, "1", channel=channel) + self.update_state(code, "ventilatingMode", ventMode, "1", channel=channel) + self.update_state(code, "sunPosition", sunPos, "1", channel=channel) + self.update_state(code, "sunMode", sunMode, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "sunAutomatic", sunAuto, "1", channel=channel) + self.update_state(code, "dawnAutomatic", dawnAuto, "1", channel=channel) + self.update_state(code, "duskAutomatic", duskAuto, "1", channel=channel) + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + self.update_state(code, "windAutomatic", windAuto, "1", channel=channel) + self.update_state(code, "windMode", windMode, "1", channel=channel) + self.update_state(code, "windDirection", windDir, "1", channel=channel) + self.update_state(code, "rainAutomatic", rainAuto, "1", channel=channel) + self.update_state(code, "rainMode", rainMode, "1", channel=channel) + self.update_state(code, "rainDirection", rainDir, "1", channel=channel) + self.update_state(code, "runningTime", runningTime, "1", channel=channel) + self.update_state(code, "motorDeadTime", deadTimes[deadTime], "1", channel=channel) + self.update_state(code, "position", pos, "1", channel=channel) + self.update_state(code, "reversal", reversal, "1", channel=channel) + self.update_state(code, "blindsMode", blindsMode, "1", channel=channel) # not tested yet if blindsMode == "on": # pragma: no cover - self.update_state(hash, "tiltInSunPos", tiltInSunPos, "1") - self.update_state(hash, "tiltInVentPos", tiltInVentPos, "1") - self.update_state(hash, "tiltAfterMoveLevel", tiltAfterMoveLevel, "1") - self.update_state(hash, "tiltAfterStopDown", tiltAfterStopDown, "1") - self.update_state(hash, "module_definitionaultSlatPos", module_definitionaultSlatPos, "1") - self.update_state(hash, "slatRunTime", slatRunTime, "1") - self.update_state(hash, "slatPosition", slatPosition, "1") + self.update_state(code, "tiltInSunPos", tiltInSunPos, "1", channel=channel) + self.update_state(code, "tiltInVentPos", tiltInVentPos, "1", channel=channel) + self.update_state(code, "tiltAfterMoveLevel", tiltAfterMoveLevel, "1", channel=channel) + self.update_state(code, "tiltAfterStopDown", tiltAfterStopDown, "1", channel=channel) + self.update_state(code, "module_definitionaultSlatPos", module_definitionaultSlatPos, "1", channel=channel) + self.update_state(code, "slatRunTime", slatRunTime, "1", channel=channel) + self.update_state(code, "slatPosition", slatPosition, "1", channel=channel) else: - self.delete_state(hash, 'tiltInSunPos') - self.delete_state(hash, 'tiltInVentPos') - self.delete_state(hash, 'tiltAfterMoveLevel') - self.delete_state(hash, 'tiltAfterStopDown') - self.delete_state(hash, 'module_definitionaultSlatPos') - self.delete_state(hash, 'slatRunTime') - self.delete_state(hash, 'slatPosition') - - self.update_state(hash, "moving", "stop", "1") - self.update_state(hash, "state", state, "1") + self.delete_state(code, 'tiltInSunPos') + self.delete_state(code, 'tiltInVentPos') + self.delete_state(code, 'tiltAfterMoveLevel') + self.delete_state(code, 'tiltAfterStopDown') + self.delete_state(code, 'module_definitionaultSlatPos') + self.delete_state(code, 'slatRunTime') + self.delete_state(code, 'slatPosition') + + self.update_state(code, "moving", "stop", "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch # Rohrmotor, SX5 -- not tested yet elif format == "24": # pragma: no cover @@ -410,36 +412,36 @@ def parse(self, msg): state = "block" if (block == "1") else pos readingsBeginUpdate(hash) - self.update_state(hash, "manualMode", manualMode, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "ventilatingPosition", ventPos, "1") - self.update_state(hash, "ventilatingMode", ventMode, "1") - self.update_state(hash, "position", pos, "1") - self.update_state(hash, "state", state, "1") - self.update_state(hash, "obstacle", obstacle, "1") - self.update_state(hash, "block", block, "1") - self.update_state(hash, "moving", "stop", "1") + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "ventilatingPosition", ventPos, "1", channel=channel) + self.update_state(code, "ventilatingMode", ventMode, "1", channel=channel) + self.update_state(code, "position", pos, "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) + self.update_state(code, "obstacle", obstacle, "1", channel=channel) + self.update_state(code, "block", block, "1", channel=channel) + self.update_state(code, "moving", "stop", "1", channel=channel) if code[0:2] == "4E": # SX5 - self.update_state(hash, "10minuteAlarm", alert10, "1") - self.update_state(hash, "automaticClosing", closingTimes['autoClose'], "1") - self.update_state(hash, "2000cycleAlarm", alert2000, "1") - self.update_state(hash, "openSpeed", openSpeeds['openSpeed'], "1") - self.update_state(hash, "backJump", backJump, "1") - self.update_state(hash, "lightCurtain", lightCurtain, "1") + self.update_state(code, "10minuteAlarm", alert10, "1", channel=channel) + self.update_state(code, "automaticClosing", closingTimes['autoClose'], "1", channel=channel) + self.update_state(code, "2000cycleAlarm", alert2000, "1", channel=channel) + self.update_state(code, "openSpeed", openSpeeds['openSpeed'], "1", channel=channel) + self.update_state(code, "backJump", backJump, "1", channel=channel) + self.update_state(code, "lightCurtain", lightCurtain, "1", channel=channel) else: - self.update_state(hash, "sunPosition", sunPos, "1") - self.update_state(hash, "sunMode", sunMode, "1") - self.update_state(hash, "sunAutomatic", sunAuto, "1") - self.update_state(hash, "dawnAutomatic", dawnAuto, "1") - self.update_state(hash, "duskAutomatic", duskAuto, "1") - self.update_state(hash, "windAutomatic", windAuto, "1") - self.update_state(hash, "windMode", windMode, "1") - self.update_state(hash, "windDirection", windDir, "1") - self.update_state(hash, "rainAutomatic", rainAuto, "1") - self.update_state(hash, "rainMode", rainMode, "1") - self.update_state(hash, "rainDirection", rainDir, "1") - self.update_state(hash, "reversal", reversal, "1") + self.update_state(code, "sunPosition", sunPos, "1", channel=channel) + self.update_state(code, "sunMode", sunMode, "1", channel=channel) + self.update_state(code, "sunAutomatic", sunAuto, "1", channel=channel) + self.update_state(code, "dawnAutomatic", dawnAuto, "1", channel=channel) + self.update_state(code, "duskAutomatic", duskAuto, "1", channel=channel) + self.update_state(code, "windAutomatic", windAuto, "1", channel=channel) + self.update_state(code, "windMode", windMode, "1", channel=channel) + self.update_state(code, "windDirection", windDir, "1", channel=channel) + self.update_state(code, "rainAutomatic", rainAuto, "1", channel=channel) + self.update_state(code, "rainMode", rainMode, "1", channel=channel) + self.update_state(code, "rainDirection", rainDir, "1", channel=channel) + self.update_state(code, "reversal", reversal, "1", channel=channel) readingsEndUpdate(hash, 1) @@ -465,21 +467,21 @@ def parse(self, msg): state = "on" if (level == 100) else level readingsBeginUpdate(hash) - self.update_state(hash, "stairwellFunction", stairwellFunction, "1") - self.update_state(hash, "stairwellTime", stairwellTime, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "duskAutomatic", duskAuto, "1") - self.update_state(hash, "sunAutomatic", sunAuto, "1") - self.update_state(hash, "sunMode", sunMode, "1") - self.update_state(hash, "manualMode", manualMode, "1") - self.update_state(hash, "dawnAutomatic", dawnAuto, "1") - self.update_state(hash, "saveIntermediateOnStop", intemedSave, "1") - self.update_state(hash, "runningTime", runningTime, "1") - self.update_state(hash, "intermediateValue", intemedVal, "1") - self.update_state(hash, "intermediateMode", intermedMode, "1") - self.update_state(hash, "level", level, "1") - self.update_state(hash, "modeChange", modeChange, "1") - self.update_state(hash, "state", state, "1") + self.update_state(code, "stairwellFunction", stairwellFunction, "1", channel=channel) + self.update_state(code, "stairwellTime", stairwellTime, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "duskAutomatic", duskAuto, "1", channel=channel) + self.update_state(code, "sunAutomatic", sunAuto, "1", channel=channel) + self.update_state(code, "sunMode", sunMode, "1", channel=channel) + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + self.update_state(code, "dawnAutomatic", dawnAuto, "1", channel=channel) + self.update_state(code, "saveIntermediateOnStop", intemedSave, "1", channel=channel) + self.update_state(code, "runningTime", runningTime, "1", channel=channel) + self.update_state(code, "intermediateValue", intemedVal, "1", channel=channel) + self.update_state(code, "intermediateMode", intermedMode, "1", channel=channel) + self.update_state(code, "level", level, "1", channel=channel) + self.update_state(code, "modeChange", modeChange, "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch # Thermostat -- not tested yet @@ -500,20 +502,20 @@ def parse(self, msg): state = "T: temperature1 desired: desiredTemp" readingsBeginUpdate(hash) - self.update_state(hash, "measured-temp", temperature1, "1") - self.update_state(hash, "measured-temp2", temperature2, "1") - self.update_state(hash, "temperatureThreshold1", tempThreshold1, "1") - self.update_state(hash, "temperatureThreshold2", tempThreshold2, "1") - self.update_state(hash, "temperatureThreshold3", tempThreshold3, "1") - self.update_state(hash, "temperatureThreshold4", tempThreshold4, "1") - self.update_state(hash, "desired-temp", desiredTemp, "1") - self.update_state(hash, "output", output, "1") - self.update_state(hash, "manualOverride", manualOverride, "1") - self.update_state(hash, "actTempLimit", actTempLimit, "1") - self.update_state(hash, "timeAutomatic", timerAuto, "1") - self.update_state(hash, "manualMode", manualMode, "1") - - self.update_state(hash, "state", state, "1") + self.update_state(code, "measured-temp", temperature1, "1", channel=channel) + self.update_state(code, "measured-temp2", temperature2, "1", channel=channel) + self.update_state(code, "temperatureThreshold1", tempThreshold1, "1", channel=channel) + self.update_state(code, "temperatureThreshold2", tempThreshold2, "1", channel=channel) + self.update_state(code, "temperatureThreshold3", tempThreshold3, "1", channel=channel) + self.update_state(code, "temperatureThreshold4", tempThreshold4, "1", channel=channel) + self.update_state(code, "desired-temp", desiredTemp, "1", channel=channel) + self.update_state(code, "output", output, "1", channel=channel) + self.update_state(code, "manualOverride", manualOverride, "1", channel=channel) + self.update_state(code, "actTempLimit", actTempLimit, "1", channel=channel) + self.update_state(code, "timeAutomatic", timerAuto, "1", channel=channel) + self.update_state(code, "manualMode", manualMode, "1", channel=channel) + + self.update_state(code, "state", state, "1", channel=channel) readingsEndUpdate(hash, 1) else: @@ -555,18 +557,18 @@ def parse(self, msg): for chan in chans: if id[2:4] in ("1a", "18", "19", "01", "02", "03"): if (id[2:4] == "1a") or (id[0:2] == "0e") or (code[0:2] in ("a0", "a2")): - self.update_state(hash, "state", sensorMsg[id]['state'] + "." + chan, "1") + self.update_state(code, "state", sensorMsg[id]['state'] + "." + chan, "1", channel=channel) else: - self.update_state(hash, "state", sensorMsg[id]['state'], "1") + self.update_state(code, "state", sensorMsg[id]['state'], "1", channel=channel) - self.update_state(hash, "channelchan", sensorMsg[id]['name'], "1") + self.update_state(code, "channelchan", sensorMsg[id]['name'], "1", channel=channel) else: if (code[0:2] not in ("69", "73")) or (id[2:4] in ("11", "12")): chan = "" if code[0:2] in ("65", "a5", "aa", "ab"): - self.update_state(hash, "state", sensorMsg[id]['state'], "1") + self.update_state(code, "state", sensorMsg[id]['state'], "1", channel=channel) - self.update_state(hash, "event", sensorMsg[id]['name'] + "." + chan, "1") + self.update_state(code, "event", sensorMsg[id]['name'] + "." + chan, "1", channel=channel) DoTrigger(hash["name"], sensorMsg[id][name] + "." + chan) @@ -595,13 +597,13 @@ def parse(self, msg): state += " B: ".format(brightness) readingsBeginUpdate(hash) - self.update_state(hash, "brightness", brightness, "1") - self.update_state(hash, "sunDirection", sunDirection, "1") - self.update_state(hash, "sunHeight", sunHeight, "1") - self.update_state(hash, "temperature", temperature, "1") - self.update_state(hash, "isRaining", isRaining, "1") - self.update_state(hash, "state", state, "1") - self.update_state(hash, "wind", wind, "1") + self.update_state(code, "brightness", brightness, "1", channel=channel) + self.update_state(code, "sunDirection", sunDirection, "1", channel=channel) + self.update_state(code, "sunHeight", sunHeight, "1", channel=channel) + self.update_state(code, "temperature", temperature, "1", channel=channel) + self.update_state(code, "isRaining", isRaining, "1", channel=channel) + self.update_state(code, "state", state, "1", channel=channel) + self.update_state(code, "wind", wind, "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch # Umweltsensor Zeit @@ -622,8 +624,8 @@ def parse(self, msg): second = msg[24:24 + 2] readingsBeginUpdate(hash) - self.update_state(hash, "date", "20" + str(year) + "-" + str(month) + "-" + str(day), "1") - self.update_state(hash, "time", str(hour) + ":" + str(minute) + ":" + str(second), "1") + self.update_state(code, "date", "20" + str(year) + "-" + str(month) + "-" + str(day), "1", channel=channel) + self.update_state(code, "time", str(hour) + ":" + str(minute) + ":" + str(second), "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch # Umweltsensor Konfiguration @@ -640,8 +642,8 @@ def parse(self, msg): channel = "01" del hash['READINGS']['configModified'] - self.update_state(hash, ".regreg", "regVal", "1") - # self.update_state(hash, "regreg", "regVal", "1") + self.update_state(code, ".regreg", "regVal", "1", channel=channel) + # self.update_state(code, "regreg", "regVal", "1", channel=channel) DUOFERN_DecodeWeatherSensorConfig(hash) # Rauchmelder Batterie @@ -650,8 +652,8 @@ def parse(self, msg): batteryLevel = int(msg[8:8 + 2], 16) readingsBeginUpdate(hash) - self.update_state(hash, "battery", battery, "1") - self.update_state(hash, "batteryLevel", batteryLevel, "1") + self.update_state(code, "battery", battery, "1", channel=channel) + self.update_state(code, "batteryLevel", batteryLevel, "1", channel=channel) readingsEndUpdate(hash, 1) # Notify is done by Dispatch # ACK, Befehl vom Aktor empfangen @@ -663,7 +665,7 @@ def parse(self, msg): # NACK, Befehl nicht vom Aktor empfangen elif msg[0:8] == "810108aa": logger.warning("missing ack for {}".format(hash)) - # self.update_state(hash, "state", "MISSING ACK", "1") + # self.update_state(code, "state", "MISSING ACK", "1", channel=channel) # foreach (grep (/^channel_/, keys%{hash})){ # chnHash = module_definitions{hash->{_}} # readingsSingleUpdate(chnHash, "state", "MISSING ACK", 1) @@ -685,7 +687,7 @@ def send(self, cmd): yield from self.send_hook(cmd) @asyncio.coroutine - def set(self, device_id, cmd, *args): + def set(self, code, cmd, *args, channel=None): # my (hash, @a) = @_ # b = @a @@ -695,8 +697,8 @@ def set(self, device_id, cmd, *args): # cmd = shift @a arg = args[0] if len(args) >= 1 else None arg2 = args[1] if len(args) > 1 else None - code = device_id[0:0 + 6] - name = self.modules['by_code'][device_id]['name'] + code = code[0:0 + 6] + name = self.modules['by_code'][code]['name'] # sets @@ -729,7 +731,7 @@ def set(self, device_id, cmd, *args): if code[0:2] in ("65", "74") and len(code) >= 8 and code[6:8] == "01": sets = merge_dicts(setsSwitchActor) # if (code =~ /^(65|74)....01/) - blindsMode = "off" if not "blindsMode" in self.modules['by_code'][device_id] else self.modules['by_code'][device_id] + blindsMode = "off" if not "blindsMode" in self.modules['by_code'][code] else self.modules['by_code'][code] if (blindsMode == "on"): sets = merge_dicts(sets, setsBlinds) @@ -742,10 +744,10 @@ def set(self, device_id, cmd, *args): return None elif cmd == "clear": - keys = self.modules['by_code'][device_id].keys() + keys = self.modules['by_code'][code].keys() for key in keys: if key != 'name': - self.modules['by_code'][device_id].__delitem__(key) + self.modules['by_code'][code].__delitem__(key) return None # cH = (hash) # delete _->{READINGS} foreach (@cH) @@ -760,8 +762,8 @@ def set(self, device_id, cmd, *args): elif cmd == "writeConfig": for x in range(0, 8): # for(my x=0; x<8; x++) { - regV = "00000000000000000000" if not ".reg{}".format(x) in self.modules['by_code'][device_id] else \ - self.modules['by_code'][device_id][".reg{}".format(x)] + regV = "00000000000000000000" if not ".reg{}".format(x) in self.modules['by_code'][code] else \ + self.modules['by_code'][code][".reg{}".format(x)] reg = "%02x" % (x + 0x81) buf = duoWeatherWriteConfig buf = buf.replace("yyyyyy", code) @@ -769,8 +771,8 @@ def set(self, device_id, cmd, *args): buf = buf.replace("nnnnnnnnnnnnnnnnnnnn", regV) yield from self.send(buf) - if "configModified" in self.modules['by_code'][device_id]: - self.modules['by_code'][device_id].__delitem__("configModified") + if "configModified" in self.modules['by_code'][code]: + self.modules['by_code'][code].__delitem__("configModified") # delete hash->{READINGS}{configModified} return None @@ -941,8 +943,8 @@ def set(self, device_id, cmd, *args): buf = duoCommand command = None - if 'chanNo' in self.modules['by_code'][device_id]: - chanNo = self.modules['by_code'][device_id]['chanNo'] + if 'chanNo' in self.modules['by_code'][code]: + chanNo = self.modules['by_code'][code]['chanNo'] # chanNo = hash->{chanNo} if (hash->{chanNo}) if 'noArg' in commands[cmd]: @@ -1023,46 +1025,46 @@ def set(self, device_id, cmd, *args): if subCmd not in commands[cmd]: raise Exception("Wrong argument {}, {}".format(arg, subCmd)) - position = -1 if not "position" in self.modules['by_code'][device_id] else self.modules['by_code'][device_id][ + position = -1 if not "position" in self.modules['by_code'][code] else self.modules['by_code'][code][ "position"] # toggleUpDown = AttrVal(name, "toggleUpDown", "0") - toggleUpDown = self.modules['by_code'][device_id]['toggleUpDown'] if 'toggleUpDown' in self.modules['by_code'][ - device_id] else 0 - moving = "stop" if not "moving" in self.modules['by_code'][device_id] else self.modules['by_code'][device_id][ + toggleUpDown = self.modules['by_code'][code]['toggleUpDown'] if 'toggleUpDown' in self.modules['by_code'][ + code] else 0 + moving = "stop" if not "moving" in self.modules['by_code'][code] else self.modules['by_code'][code][ "moving"] - timeAutomatic = "on" if not "timeAutomatic" in self.modules['by_code'][device_id] else \ - self.modules['by_code'][device_id]["timeAutomatic"] - dawnAutomatic = "on" if not "dawnAutomatic" in self.modules['by_code'][device_id] else \ - self.modules['by_code'][device_id]["dawnAutomatic"] - duskAutomatic = "on" if not "duskAutomatic" in self.modules['by_code'][device_id] else \ - self.modules['by_code'][device_id]["duskAutomatic"] + timeAutomatic = "on" if not "timeAutomatic" in self.modules['by_code'][code] else \ + self.modules['by_code'][code]["timeAutomatic"] + dawnAutomatic = "on" if not "dawnAutomatic" in self.modules['by_code'][code] else \ + self.modules['by_code'][code]["dawnAutomatic"] + duskAutomatic = "on" if not "duskAutomatic" in self.modules['by_code'][code] else \ + self.modules['by_code'][code]["duskAutomatic"] if moving != "stop": if cmd in ('up', 'down', 'toggle'): if toggleUpDown: cmd = "stop" - # self.update_state(hash,"moving","moving") + # self.update_state(code,"moving","moving", channel=channel) if ((cmd == "toggle") and (position > -1)): - self.update_state(hash, "moving", "moving", 1) + self.update_state(code, "moving", "moving", 1, channel=channel) if ((cmd == "dawn") and (dawnAutomatic == "on") and (position > 0)): - self.update_state(hash, "moving", "up", 1) + self.update_state(code, "moving", "up", 1, channel=channel) if ((cmd == "dusk") and (duskAutomatic == "on") and (position < 100) and (position > -1)): - self.update_state(hash, "moving", "down", 1) + self.update_state(code, "moving", "down", 1, channel=channel) if timer == "00" or timeAutomatic == "on": if ((cmd == "up") and (position > 0)): - self.update_state(hash, "moving", "up", 1) + self.update_state(code, "moving", "up", 1, channel=channel) if ((cmd == "down") and (position < 100) and (position > -1)): - self.update_state(hash, "moving", "down", 1) + self.update_state(code, "moving", "down", 1, channel=channel) if cmd == "position": if arg > position: - self.update_state(hash, "moving", "down", 1) + self.update_state(code, "moving", "down", 1, channel=channel) elif (arg < position): - self.update_state(hash, "moving", "up", 1) + self.update_state(code, "moving", "up", 1, channel=channel) else: - self.update_state(hash, "moving", "stop", 1) + self.update_state(code, "moving", "stop", 1, channel=channel) command = commands[cmd][subCmd]