def execute(self, module, input): now = ZonedDateTime.now() if itemStateOlderThen("Dawn_Time", now) and itemStateNewerThen( "Dusk_Time", now): # triggers solar value update sendCommand("Solar_Total_Yield", REFRESH) sendCommand("Solar_AC_Power", REFRESH) acPower = getItemState('Solar_AC_Power').intValue() dailyConsumption = getItemState("Solar_Daily_Yield").doubleValue() msg = "{} W, {:.2f} kWh".format(acPower, dailyConsumption) if itemLastUpdateOlderThen( "Solar_Total_Yield", now.minusMinutes(15)) and itemStateOlderThen( "Dawn_Time", now.minusMinutes(60)): self.log.error("Solar values not updated") else: msg = "Inaktiv" postUpdateIfChanged("Solar_Message", msg)
def execute(self, module, input): if getItemState("pOther_Manual_State_Auto_Rollershutter") != ON: return contactItemName = input['event'].getItemName() if contactItemName not in contact_map: return config = contact_map[contactItemName] state = None if input['event'].getItemState() == OPEN: state = UP else: if getItemState("pOther_Automatic_State_Rollershutter").intValue( ) == SunProtectionHelper.STATE_ROLLERSHUTTER_DOWN: # check that more windows are DOWN than UP. #closedShutters = 0 #for _config in configs: # if getItemState(_config["shutter"]).intValue() == 100: # closedShutters += 1 #if closedShutters >= math.floor( len(configs) / 2 ): state = DOWN elif ("sunprotection" in config and getItemState(config["sunprotection"]) == ON and "sunprotectionOnlyIfAway" not in config): state = DOWN if state is None: return sendCommand(config["shutter"], state)
def updateInfoMessage(self, infoItem, temperatureItem, humidityItem, co2Item=None, temperatureTargetItem=None): #self.log.info(u">>>delay: {}".format(infoItem)) msg = u"" if temperatureTargetItem is not None: msg = u"{}({}) ".format( msg, getItemState(temperatureTargetItem).format("%.1f")) #self.log.info(temperatureItem) msg = u"{}{} °C, ".format(msg, getItemState(temperatureItem).format("%.1f")) #self.log.info(humidityItem) msg = u"{}{} %".format(msg, getItemState(humidityItem).format("%.1f")) if co2Item is not None: msg = u"{}, {} ppm".format(msg, getItemState(co2Item).format("%d")) postUpdateIfChanged(infoItem, msg) self.updateTimer[infoItem] = None
def execute(self, module, input): if getItemState( "pOther_Manual_State_Auto_Lighting") == ON and getItemState( "pOther_Presence_State").intValue( ) == PresenceHelper.STATE_AWAY: sendCommand("pGF_Corridor_Light_Hue_Color", 30) sendCommand("pGF_Livingroom_Light_Hue4_Color", 30)
def execute(self, module, input): if getItemState("pOther_Manual_State_Auto_Rollershutter") != ON: return if self.awayTimer != None: self.awayTimer.cancel() self.awayTimer = None if getItemState("pOther_Automatic_State_Rollershutter").intValue() in [ SunProtectionHelper.STATE_ROLLERSHUTTER_DOWN, SunProtectionHelper.STATE_ROLLERSHUTTER_MAYBE_UP ]: return if input['event'].getItemState().intValue( ) == PresenceHelper.STATE_AWAY: self.presenceTimer = startTimer(self.log, 1800, self.updateCallback, args=[DOWN]) elif input['event'].getItemState().intValue( ) == PresenceHelper.STATE_PRESENT and input['event'].getOldItemState( ).intValue() in [ PresenceHelper.STATE_AWAY, PresenceHelper.STATE_MAYBE_PRESENT ]: self.updateCallback(UP)
def execute(self, module, input): # we don't want do be notified if getItemState("pOther_Manual_State_Air_Thoroughly_Notify") != ON: return if 'event' in input: if self.timer != None: self.timer.cancel() self.timer = None if input['event'].getItemState().intValue( ) == PresenceHelper.STATE_PRESENT and input[ 'event'].getOldItemState().intValue() in [ PresenceHelper.STATE_AWAY, PresenceHelper.STATE_MAYBE_PRESENT ]: # delayed notification to give all devices the chance to be detected as present self.timer = startTimer( self.log, 60, self.process, args=[PresenceHelper.getPresentRecipients()]) # 1 min else: # we are away if getItemState("pOther_Presence_State").intValue() in [ PresenceHelper.STATE_AWAY, PresenceHelper.STATE_MAYBE_PRESENT ]: return # recipients will be selected only if there are state changes recipients = None self.process(recipients)
def execute(self, module, input): if getItemState( "pOther_Automatic_State_Sunprotection_Terrace").intValue( ) == SunProtectionHelper.STATE_TERRACE_MAYBE_CLOSED: pass elif getItemState( "pOther_Automatic_State_Sunprotection_Terrace").intValue( ) == SunProtectionHelper.STATE_TERRACE_CLOSED: # DOWN only if automatic is enabled and (people are present or where present changed recently or terrace door is open) if (getItemState("pOther_Manual_State_Auto_Sunprotection") == ON and (getItemState("pOther_Presence_State").intValue() not in [ PresenceHelper.STATE_AWAY, PresenceHelper.STATE_MAYBE_PRESENT ] or itemLastChangeNewerThen( "pOther_Presence_State", ZonedDateTime.now().minusMinutes(120)) or getItemState( "pGF_Livingroom_Openingcontact_Window_Terrace_State") == OPEN)): #self.log.info(u"down") sendCommand("pOutdoor_Terrace_Shading_Left_Control", DOWN) sendCommand("pOutdoor_Terrace_Shading_Right_Control", DOWN) else: #self.log.info(u"up") # UP always when sun protection time is over sendCommand("pOutdoor_Terrace_Shading_Left_Control", UP) sendCommand("pOutdoor_Terrace_Shading_Right_Control", UP)
def confirmArriving(self): presenceState = getItemState("pOther_Presence_State").intValue() if presenceState != PresenceHelper.STATE_MAYBE_PRESENT: return newestUpdate = None for item in getItem("gSensor_Indoor").getAllMembers(): if getItemState(item) == OPEN: newestUpdate = ZonedDateTime.now() break _update = getItemLastUpdate(item) if newestUpdate == None or _update.isAfter(newestUpdate): newestUpdate = _update ref = ZonedDateTime.now().minusSeconds(7) self.isConfirmed = newestUpdate.isAfter(ref) or newestUpdate.isEqual( ref) if self.isConfirmed: self.delayedAwayCheck() else: self.setAway(False) self.confirmTimer = None
def getPresentRecipients(): recipients = [] if getItemState("pOther_Presence_Holger_State") == OnOffType.ON: recipients.append('bot_holger') if getItemState("pOther_Presence_Sandra_State") == OnOffType.ON: recipients.append('bot_sandra') return recipients
def execute(self, module, input): if getItemState("pOther_Manual_State_Notify") != ON: return state = getItemState("pOther_Presence_State").intValue() if state in [PresenceHelper.STATE_AWAY, PresenceHelper.STATE_SLEEPING]: itemName = input['event'].getItemName() item = getItem(itemName) location = self.getLocation(item) if "Door" in itemName: msg = u"Tür im {} {}".format( location.getLabel(), u"offen" if input['event'].getItemState() == OPEN else u"geschlossen") elif "Window" in itemName: msg = u"Fenster im {} {}".format( location.getLabel(), u"offen" if input['event'].getItemState() == OPEN else u"geschlossen") elif "Motiondetector" in itemName: if input['event'].getItemState() == CLOSED: return # during sleep, ignore moving detection if state == PresenceHelper.STATE_SLEEPING: return msg = u"Bewegung im {} erkannt".format(location.getLabel()) #self.log.info(u"{} {} {} {}".format(group,itemName,item.getLabel(),location.getLabel())) sendNotification(u"Alarm", u"{}".format(msg))
def execute(self, module, input): moverStatus = getItemState("pOutdoor_Mower_Status").toString() if itemLastUpdateOlderThen("pOutdoor_Mower_WlanSignal", ZonedDateTime.now().minusMinutes(60)): if moverStatus != "98": postUpdate("pOutdoor_Mower_Status", 98) postUpdate( "pOutdoor_Mower_StatusFormatted", Transformation.transform("MAP", "robonect_status.map", "98")) else: seconds = getItemState("pOutdoor_Mower_Duration").intValue() hours = seconds / (60 * 60) seconds = seconds % (60 * 60) minutes = seconds / 60 #seconds = seconds % 60 msg = u"{} seit ".format( Transformation.transform("MAP", "robonect_status.map", moverStatus)) if hours < 10: msg = u"{}0".format(msg) msg = u"{}{}:".format(msg, hours) if minutes < 10: msg = u"{}0".format(msg) msg = u"{}{}:".format(msg, minutes) postUpdateIfChanged("pOutdoor_Mower_StatusFormatted", msg)
def execute(self, module, input): active = [] group = "Fehler" ventilation_state = getItemState( "pGF_Utilityroom_Ventilation_State_Message").toString() if ventilation_state != "Alles ok": if ventilation_state == "Filter": active.append(u"Filter") else: active.append(u"Lüftung") if getItemState("pGF_Utilityroom_Heating_State_Message").toString( ) != "Alles ok": active.append(u"Heizung") if getItemState("pGF_Garage_Solar_Inverter_Is_Working") == OFF: active.append(u"Solar") if getItemState("State_Server").intValue() > 1: active.append(u"Server") if len(active) == 0: active.append(u"Alles ok") group = "Info" msg = u", ".join(active) if postUpdateIfChanged("pOther_State_Message_Main", msg): sendNotificationToAllAdmins("Main " + group, msg)
def delayUpdate(self): msg = u"{}%, {}%".format( getItemState("pGF_Utilityroom_Heating_Power").format("%.0f"), getItemState("pGF_Utilityroom_Heating_Circuit_Pump_Speed").format( "%.0f")) postUpdateIfChanged("pGF_Utilityroom_Heating_Power_Message", msg) self.updateTimer = None
def execute(self, module, input): now = ZonedDateTime.now() currentErtrag = getItemState("Solar_Annual_Yield").doubleValue() currentEinspeisung = getItemState( "Electric_VZ_Jahreseinspeisung").doubleValue() postUpdateIfChanged("Solar_Annual_Consumption", currentErtrag - currentEinspeisung)
def delayUpdate(self): msg = u"{}°C, {}°C".format( getItemState("pGF_Utilityroom_Heating_Temperature_Offset").format( "%.1f"), getItemState("pGF_Utilityroom_Heating_Temperature_Offset_Target"). format("%.1f")) postUpdateIfChanged( "pGF_Utilityroom_Heating_Temperature_Offset_Message", msg) self.updateTimer = None
def findStep(self): duration = getItemState( "pOutdoor_Watering_Logic_Program_Duration").intValue() * 60.0 remaining = 0 info = u"" # detect current active index activeIndex = -1 for i in range(len(circuits)): group = circuits[i] if getItemState(group[2][0] + "_Powered") == ON: activeIndex = i runtime = ChronoUnit.SECONDS.between( getItemLastChange(group[2][0] + "_Powered"), ZonedDateTime.now()) remaining = (duration * group[0]) - runtime break if remaining <= 0: nextIndex = -1 # detect next index for i in range(len(circuits)): if activeIndex != -1 and i <= activeIndex: continue group = circuits[i] for circuit in group[2]: if getItemState(circuit + "_Auto") == ON: nextIndex = i break if nextIndex != -1: break if nextIndex == -1: self.disableAllCircuits() postUpdate("pOutdoor_Watering_Logic_Program_Start", OFF) else: for circuit in circuits[nextIndex][2]: if getItemState(circuit + "_Auto") == ON: sendCommand(circuit + "_Powered", ON) nextGroup = circuits[nextIndex] remaining = (duration * nextGroup[0]) info = nextGroup[1] # deactivate current index if activeIndex != -1: for circuit in circuits[activeIndex][2]: sendCommand(circuit + "_Powered", OFF) else: info = circuits[activeIndex][1] return [info, remaining]
def execute(self, module, input): now = ZonedDateTime.now() currentSupply = getItemState( "pGF_Utilityroom_Electricity_Total_Supply").doubleValue() currentYield = getItemState( "pGF_Garage_Solar_Inverter_Total_Yield").doubleValue() # Tagesverbrauch startSupply = getHistoricItemState( "pGF_Utilityroom_Electricity_Total_Supply", now.toLocalDate().atStartOfDay(now.getZone())).doubleValue() startYield = getHistoricItemState( "pGF_Garage_Solar_Inverter_Total_Yield", now.toLocalDate().atStartOfDay(now.getZone())).doubleValue() # sometimes solar converter is providing wrong value. Mostly if he is inactive in the night if currentYield > 1000000000 or startYield > 1000000000: # can be INFO because it is a 'normal' behavior of this solar converter self.log.info( u"Wrong Solar Value: currentYield is {}, startYield is {}". format(currentYield, startYield)) return totalSupply = currentSupply - startSupply totalYield = currentYield - startYield dailyConsumption = totalYield - totalSupply postUpdateIfChanged("pGF_Garage_Solar_Inverter_Daily_Yield", totalYield) #self.log.info(u"A {} {}".format(currentSupply,currentYield)) #self.log.info(u"B {} {}".format(startSupply,startYield)) #self.log.info(u"C {} {}".format(totalSupply,totalYield)) postUpdateIfChanged("pGF_Garage_Solar_Inverter_Daily_Consumption", dailyConsumption) # Jahresverbrauch refDay = now.withYear(now.getYear()).withMonth(1).withDayOfMonth(1) refDate = refDay.toLocalDate().atStartOfDay(refDay.getZone()) startSupply = getHistoricItemState( "pGF_Utilityroom_Electricity_Total_Supply", refDate).doubleValue() startYield = getHistoricItemState( "pGF_Garage_Solar_Inverter_Total_Yield", refDate).doubleValue() totalSupply = currentSupply - startSupply totalYield = currentYield - startYield annualConsumption = totalYield - totalSupply #self.log.info(u"D {} {}".format(startSupply,startYield)) #self.log.info(u"E {}".format(annualConsumption)) postUpdateIfChanged("pGF_Garage_Solar_Inverter_Annual_Consumption", annualConsumption)
def execute(self, module, input): msg = u"Nicht aktiv" if getItemState( "pOther_Manual_State_Auto_Attic_Light").intValue() != 1: soilMoistSensor1 = getItemState( "pIndoor_Plant_Sensor_Device_State1").intValue( ) if getItemState( "pIndoor_Plant_Sensor_Device_Enabled1") == ON else 1000 soilMoistSensor2 = getItemState( "pIndoor_Plant_Sensor_Device_State2").intValue( ) if getItemState( "pIndoor_Plant_Sensor_Device_Enabled2") == ON else 1000 soilMoistSensor3 = getItemState( "pIndoor_Plant_Sensor_Device_State3").intValue( ) if getItemState( "pIndoor_Plant_Sensor_Device_Enabled3") == ON else 1000 soilMoistSensor4 = getItemState( "pIndoor_Plant_Sensor_Device_State4").intValue( ) if getItemState( "pIndoor_Plant_Sensor_Device_Enabled4") == ON else 1000 if soilMoistSensor1 < 380 or soilMoistSensor2 < 380 or soilMoistSensor3 < 380 or soilMoistSensor4 < 380: msg = u"Jetzt Giessen" elif soilMoistSensor1 < 400 or soilMoistSensor2 < 400 or soilMoistSensor3 < 400 or soilMoistSensor4 < 400: msg = u"Giessen" else: msg = u"Feucht genug" postUpdateIfChanged("pIndoor_Plant_Sensor_Watering_Info", msg)
def delayUpdate(self): solarCollector = getItemState( "pGF_Utilityroom_Heating_Temperature_Solar_Collector") solarStorage = getItemState( "pGF_Utilityroom_Heating_Temperature_Solar_Storage") msg = u"{}°C, {}°C".format(solarCollector.format("%.1f"), solarStorage.format("%.1f")) postUpdateIfChanged( "pGF_Utilityroom_Heating_Temperature_Solar_Message", msg) self.updateTimer = None
def execute(self, module, input): dailyEnergyDemand = getItemState( "pGF_Utilityroom_Electricity_Current_Daily_Demand").doubleValue() dailyEnergySupply = getItemState( "pGF_Utilityroom_Electricity_Current_Daily_Supply").doubleValue() dailySolarSupply = getItemState( "pGF_Garage_Solar_Inverter_Daily_Yield").doubleValue() postUpdateIfChanged( "pGF_Utilityroom_Electricity_Current_Daily_Consumption", dailyEnergyDemand - dailyEnergySupply + dailySolarSupply)
def delayUpdate(self): if isinstance(getItemState("pGF_Utilityroom_Ventilation_Incoming"), UnDefType) \ or isinstance(getItemState("pGF_Utilityroom_Ventilation_Outgoing"), UnDefType): return msg = u"→ {}%, ← {}%".format( getItemState("pGF_Utilityroom_Ventilation_Incoming").toString(), getItemState("pGF_Utilityroom_Ventilation_Outgoing").toString()) postUpdateIfChanged("pGF_Utilityroom_Ventilation_Fan_Message", msg) self.updateTimer = None
def delayUpdate(self): msg = u"({}°C) {}°C, {}°C".format( getItemState("pOutdoor_Weather_Forecast_Temperature_4h").format( "%.1f"), getItemState("pGF_Utilityroom_Heating_Temperature_Outdoor").format( "%.1f"), getItemState("pGF_Utilityroom_Heating_Temperature_Outdoor_Subdued" ).format("%.1f")) postUpdateIfChanged( "pGF_Utilityroom_Heating_Temperature_Outdoor_Message", msg) self.updateTimer = None
def _getCurrentColors(self): color1 = getItemState( "pGF_Livingroom_Light_Hue1_Color").toString().split(",") color2 = getItemState( "pGF_Livingroom_Light_Hue2_Color").toString().split(",") color3 = getItemState( "pGF_Livingroom_Light_Hue3_Color").toString().split(",") color4 = getItemState( "pGF_Livingroom_Light_Hue4_Color").toString().split(",") color5 = getItemState( "pGF_Livingroom_Light_Hue5_Color").toString().split(",") return [color1, color2, color3, color4, color5]
def execute(self, module, input): reference_duration = getItemState( "pOutdoor_Watering_Logic_Program_Duration").intValue() for i in range(len(circuits)): for circuit in circuits[i][2]: if getItemState(circuit + "_Auto") == ON: duration = (circuits[i][0] * reference_duration) duration = int(math.floor(duration)) postUpdate(circuit + "_Info", u"{} min.".format(duration)) else: postUpdate(circuit + "_Info", u"inaktiv")
def execute(self, module, input): if getItemState("pOther_Manual_State_Auto_Rollershutter") != ON: return if getItemState("pOther_Automatic_State_Rollershutter").intValue( ) == SunProtectionHelper.STATE_ROLLERSHUTTER_DOWN: for config in configs: if getItemState(config["contact"]) != CLOSED: continue sendCommand(config["shutter"], DOWN) elif getItemState("pOther_Presence_State").intValue( ) == PresenceHelper.STATE_AWAY and getItemState( "pOther_Automatic_State_Rollershutter").intValue( ) == SunProtectionHelper.STATE_ROLLERSHUTTER_UP: sendCommand("gShutters", UP)
def execute(self, module, input): active = [] if getItemState("gOutdoor_Watering_Circuits") == ON: active.append(u"Bewässerung") if getItemState("pOutdoor_Light_Automatic_Main_Switch") != ON: active.append(u"Beleuchtung") if len(active) == 0: active.append(u"Alles ok") msg = ", ".join(active) postUpdateIfChanged("pOther_State_Message_Garden", msg)
def callbackProgress(self): if self.progressTimer is not None and self.currentProgressMsg != getItemState( "pOutdoor_Watering_Logic_Program_State").toString(): self.log.info("Cancel Watering Progress Zombie Timer") self.cleanProgressTimer() return msg, remaining = self.findStep() if remaining <= 0: self.cleanProgressTimer() return remainingInMinutes = int(math.floor(remaining / 60.0)) if remainingInMinutes > 0: msg = u"{} noch {} min".format(msg, remainingInMinutes) else: msg = u"{} gleich fertig".format(msg) self.currentProgressMsg = msg postUpdate("pOutdoor_Watering_Logic_Program_State", self.currentProgressMsg) self.progressTimer = startTimer(self.log, 60.0, self.callbackProgress)
def updateCallback(self, state): for config in configs: # handle only shutters which depends on presence state if "sunprotectionOnlyIfAway" not in config: continue if state == DOWN: if getItemState(config["contact"]) != CLOSED: continue if getItemState(config["sunprotection"]) != ON: continue sendCommandIfChanged(config["shutter"], state) self.awayTimer = None
def delayUpdate(self): if isinstance(getItemState("pGF_Utilityroom_Ventilation_Indoor_Incoming_Temperature"), UnDefType) \ or isinstance(getItemState("pGF_Utilityroom_Ventilation_Indoor_Outgoing_Temperature"), UnDefType): return msg = u"→ {}°C, ← {}°C".format( getItemState( "pGF_Utilityroom_Ventilation_Indoor_Incoming_Temperature"). format("%.1f"), getItemState( "pGF_Utilityroom_Ventilation_Indoor_Outgoing_Temperature"). format("%.1f")) postUpdateIfChanged( "pGF_Utilityroom_Ventilation_Indoor_Temperature_Message", msg) self.updateTimer = None
def execute(self, module, input): global ruleTimeouts now = ZonedDateTime.now() #last = ruleTimeouts.get("Motiondetector_Outdoor_Individual_Switches",0) #if now - last > 1000: ruleTimeouts["Motiondetector_Outdoor_Main_Switch"] = now ruleTimeouts["Light_Outdoor"] = now itemName = input['event'].getItemName() itemCommand = input['event'].getItemCommand() switchState = ON for i, entry in enumerate(manualMappings): if entry[1] == itemName: sendCommandIfChanged(entry[0], OFF) if itemCommand == OFF: switchState = OFF else: if getItemState(entry[1]) == OFF: switchState = OFF # must be a command to inform physical knx switch sendCommandIfChanged("pOutdoor_Light_Automatic_Main_Switch", switchState)