def process_occupancy_control_received_command_event( self, event ): # OC event handler for a command from OL to control area locking log.info("Occupancy Control for area {} received command {}".format( self.name, event.itemCommand)) parts = str(event.itemCommand).split(',') command = parts[0] if command == "LOCK": self.lock() if len(parts) == 2: timeout = int(parts[1]) self.start_lock_timer(timeout) elif command == "UNLOCK": self.unlock() elif command == "CLEARLOCKS": self.clear_lock() elif command == "LOG": log.info('Occupacy Control command {}'.format(self)) return log.info("Occupancy locking level for area {} is {}".format( self.name, self.locking_level)) # propagate to child areas for child_item in self.get_child_area_group_items(): log.info( "Propagating occupancy control {} to child area {}".format( event.itemCommand, child_item.name)) events.sendCommand( self.get_occupancy_control_item_for_area(child_item.name), event.itemCommand)
def onCronJob(self): getLogger().debug( ("'onCronJob' called for '{}'....").format(self.getName())) try: curConditionState = self.GetConditionActiveStatus() curRequestedState = self.GetRequestedTriggerState() curAllowedState = curConditionState & curRequestedState getLogger().debug( ("'onCronJob' called for '{}'....").format(self.getName())) if (curConditionState): for itemName, curItem in self._arrVirtualSwitches.items(): getLogger().debug( ("'onCronJob' processing item '{}' ('{}')....").format( itemName, curItem)) physicalItem = itemRegistry.getItem(itemName) #events.sendCommand(curItem, self.getStateInactive())getLogger().debug(("Calling 'forceState for '{}' requestedState='{}' curState='{}' conditionState='{}'....").format(itemName, curRequestedState, str(curItem.state).upper(), curConditionState)) newState = curItem._physicalDevice.getStateInactive() if (curRequestedState): newState = curItem._physicalDevice.getStateActive() if (newState != physicalItem.state): events.sendCommand(physicalItem, newState) else: getLogger().debug( "'onCronJob' skipping (ConditionState is FALSE)") except: LogException() return
def send_command(item, command): if item.type == 'Dimmer': if command == 'ON': command = 100 elif command == 'OFF': command = 0 events.sendCommand(item, command)
def toggle_action(item, active): """ This function sends the OFF command to the Item. Args: Item item: The Item to perform the action on boolean active: Area activity (True for active and False for inactive) """ events.sendCommand(item, ON if item.state == OFF else OFF)
def post_update_if_different(item_or_item_name, new_value, sendACommand=False, floatPrecision=None): """ Checks if the current state of the item is different than the desired new state. If the target state is the same, no update is posted. sendCommand vs postUpdate: If you want to tell something to change (turn a light on, change the thermostat to a new temperature, start raising the blinds, etc.), then you want to send a command to an Item using sendCommand. If your Items' states are not being updated by a binding, the autoupdate feature or something else external, you will probably want to update the state in a rule using ``events.postUpdate``. Unfortunately, most decimal fractions cannot be represented exactly as binary fractions. A consequence is that, in general, the decimal floating-point numbers you enter are only approximated by the binary floating-point numbers actually stored in the machine. Therefore, comparing the stored value with the new value will most likely always result in a difference. You can supply the named argument floatPrecision to round the value before comparing. Args: item_or_item_name (Item or str): name of the Item new_value (State or Command): state to update the Item with, or Command if using sendACommand (must be of a type supported by the Item) sendACommand (Boolean): (optional) ``True`` to send a command instead of an update floatPrecision (int): (optional) the precision of the Item's state to use when comparing values Returns: bool: ``True``, if the command or update was sent, else ``False`` """ compare_value = None item = itemRegistry.getItem(item_or_item_name) if isinstance(item_or_item_name, basestring) else item_or_item_name if sendACommand: compare_value = TypeParser.parseCommand(item.acceptedCommandTypes, str(new_value)) else: compare_value = TypeParser.parseState(item.acceptedDataTypes, str(new_value)) if compare_value is not None: if item.state != compare_value or (isinstance(new_value, float) and floatPrecision is not None and round(item.state.floatValue(), floatPrecision) != new_value): if sendACommand: events.sendCommand(item, new_value) LOG.debug(u"New sendCommand value for '{}' is '{}'".format(item.name, new_value)) else: events.postUpdate(item, new_value) LOG.debug(u"New postUpdate value for '{}' is '{}'".format(item.name, new_value)) return True else: LOG.debug(u"Not {} {} to '{}' since it is the same as the current state".format("sending command" if sendACommand else "posting update", new_value, item.name)) return False else: LOG.warn(u"'{}' is not an accepted {} for '{}'".format(new_value, "command type" if sendACommand else "state", item.name)) return False
def sendCommand(item_or_item_name, new_value): """ Sends a command to an item regardless of its current state. Args: item_or_item_name (Item or str): name of the Item new_value (Command): Command to send to the Item """ item = itemRegistry.getItem(item_or_item_name) if isinstance( item_or_item_name, basestring) else item_or_item_name events.sendCommand(item, new_value)
def sendCommand(item_or_item_name, new_value): """ Sends a command to an item regardless of its current state. Args: item_or_item_name (Item or str): name of the Item new_value (Command): Command to send to the Item """ LOG.warn("The 'core.utils.sendCommand' function is pending deprecation.") item = itemRegistry.getItem(item_or_item_name) if isinstance(item_or_item_name, basestring) else item_or_item_name events.sendCommand(item, new_value)
def incrementUsageCount(self): try: getLogger().debug("Calling 'incrementUsageCount' for '" + self.getName() + "' count='" + str(self.usageCount) + "'") with self.lock: self.usageCount = self.usageCount + 1 getLogger().debug("Increment usage count for '" + self.getName() + "' to '" + str(self.usageCount) + "'") if (self.usageCount > 0): getLogger().info(("'sendCommand' called for item '{}' newState='{}'").format(self.getName(), self.getStateActive())) curItem = itemRegistry.getItem(self.getName()) events.sendCommand(curItem, self.getStateActive()) except: LogException()
def __init__(self, name): try: PhysicalDevice.__init__(self, name) curItem = scope.itemRegistry.getItem(self.getName()) strState = str(curItem.state).upper() getLogger().debug(("Initialize BinaryDevice '{}', current state is '{}' (Type='{}')").format(self.getName(), curItem.state, type(curItem.state))) if (strState == 'NULL'): getLogger().info(("BinaryDevice '{}' is in uninitialized state. Changing state from '{}' to state '{}'").format(self.getName(), curItem.state, self.getStateInactive())) events.sendCommand(curItem, self.getStateInactive()) except: LogException()
def decrementUsageCount(self): try: getLogger().debug("calling 'decrementUsageCount' for '" + self.getName() + "' count='" + str(self.usageCount) + "'") with self.lock: if (self.usageCount>0): self.usageCount = self.usageCount - 1 getLogger().debug("Decrement usage count for '" + self.getName() + "' to '" +str(self.usageCount)+ "'") if (self.usageCount<1): getLogger().info("'sendCommand' called for item '" + self.getName() + "' newState='"+ str(self.getStateInactive()) + "'") curItem = itemRegistry.getItem(self.getName()) events.sendCommand(curItem, self.getStateInactive()) except: LogException()
def timer_body(target, value, is_command, time, log): """ Called when the differed action timer expires, sends the command to the target Item. Arguments: - target: Item name to send the command to - value: Command or state to issue to the target Item - is_command: Whether to send value to target as a command or an update - time: the original time string - log: logger passed in from the Rule that is using this. """ log.debug("{} {} to {} after {}".format( "Commanding" if is_command else "Updating", target, value, time)) if is_command: events.sendCommand(target, str(value)) else: events.postUpdate(target, str(value))
def light_action(item, active): """ This function performs an action on a light Item. When called, this function pulls in the metadata for the supplied Item or uses the default values specified in ``configuration.AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION"["default_levels"]``, if the metadata does not exist. This metadata is then compared to the current lux level to determine if a light should be turned OFF or set to the specified level. This function should work for everyone without modification. Args: Item item: The Item to perform the action on boolean active: Area activity (True for active and False for inactive) """ #start_time = DateTime.now().getMillis() item_metadata = get_key_value(item.name, "area_triggers_and_actions", "light_action") lux_item_name = item_metadata.get("lux_item_name", AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION["light_action"].get("lux_item_name")) trigger_type = "active" if active else "inactive" lux_trigger = item_metadata.get(trigger_type, {}).get("modes", {}).get(items[MODE_ITEM].toString(), {}).get("lux_trigger", AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION["light_action"]["default_levels"][trigger_type]["lux_trigger"]) lux_type = "low_lux" if lux_trigger == 0 or lux_item_name is None or items[lux_item_name].intValue() < lux_trigger else "high_lux" levels = item_metadata.get(trigger_type, {}).get("modes", {}).get(items[MODE_ITEM].toString(), {}).get(lux_type, {}) brightness = PercentType(str(levels.get("brightness", AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION["light_action"]["default_levels"][trigger_type][lux_type]["brightness"]))) #LOG.warn(u"light_action: trigger_type: {}, item.name: {}, item.state: {}, lux: {}, lux_trigger: {}, lux_type: {}, brightness: {}, lux_item_name: {}".format(trigger_type, item.name, item.state, items[AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION["light_action"]["lux_item_name"]], lux_trigger, lux_type, brightness, lux_item_name)) if item.type in ["Dimmer", "Rollershutter"] or (item.type == "Group" and item.baseItem.type == "Dimmer"): if item.state != brightness: if item.state <= PercentType(DISABLE_AUTOMATION_BRIGHTNESS): events.sendCommand(item, brightness) LOG.info(u"{} {}: {}".format("<<<<<<<<<<<<<<<<<<<<<" if brightness == DecimalType(0) else ">>>>>>>", item.name, brightness)) else: LOG.info(u"'{}': dimmer is currently set > {}, so not adjusting".format(DISABLE_AUTOMATION_BRIGHTNESS, item.name)) else: LOG.debug(u"'{}': dimmer is already set to '{}', so not sending command".format(item.name, brightness)) elif item.type == "Color" or (item.type == "Group" and item.baseItem.type == "Color"): hue = DecimalType(str(levels.get("hue", AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION["light_action"]["default_levels"][trigger_type][lux_type]["hue"]))) saturation = PercentType(str(levels.get("saturation", AREA_TRIGGERS_AND_ACTIONS_CONFIGURATION["light_action"]["default_levels"][trigger_type][lux_type]["saturation"]))) if item.state != HSBType(hue, saturation, brightness): if item.state.brightness < PercentType(DISABLE_AUTOMATION_BRIGHTNESS): events.sendCommand(item, HSBType(hue, saturation, brightness)) LOG.info(u"{} {}: '{}'".format("<<<<<<<<<<<<<<<<<<<<<" if brightness == DecimalType(0) else ">>>>>>>", item.name, HSBType(hue, saturation, brightness))) else: LOG.info(u"'{}': brightness is currently set > {}, so not adjusting".format(DISABLE_AUTOMATION_BRIGHTNESS, item.name)) else: LOG.debug(u"'{}': color is already set to [{}, {}, {}], so not sending command".format(item.name, hue, saturation, brightness)) elif item.type == "Switch" or (item.type == "Group" and item.baseItem.type == "Switch"): new_state = brightness.as(OnOffType) if item.state != new_state: events.sendCommand(item, new_state) LOG.info(u"{} {}: {}".format("<<<<<<<<<<<<<<<<<<<<<" if new_state == OFF else ">>>>>>>", item.name, new_state)) else: LOG.debug(u"'{}': switch is already '{}', so not sending command".format(item.name, new_state))
def process_occupancy_state_changed_event( self, event ): # OS event handler when the area's OS group item changes, execute Occupied or Vacant Actions if self.occupancy_settings.exists(): # must have these to proceed state = str(event.itemState) log.warn( "Occupancy state changed to {} ---->>> Settings for area {}: {} " .format(state, self.name, self.occupancy_settings)) if not self.is_locked(): # check if area locked before proceeding if state == 'ON': actions = self.occupancy_settings.get_occupied_actions() # perform any actions for action in actions: #log.info ('for loop {}'.format(action)) if action == "LightsOn": for item in self.item.members: for tag in item.getTags(): if tag == "Lighting": send_command(item, 'ON') elif action == "LightsOnIfDark": if (itemRegistry.getItem( "VT_DayLight_Switch").state) == 'OFF': for item in self.item.members: for tag in item.getTags(): if tag == "Lighting": send_command(item, 'ON') elif action == "SceneOn": for item in self.item.members: for tag in item.getTags(): if tag == "AreaScene": events.sendCommand(item, 'ON') elif action == "SceneOnIfDark": if str( itemRegistry.getItem( "VT_DayLight_Switch").state) == 'OFF': for item in self.item.members: for tag in item.getTags(): if tag == "AreaScene": events.sendCommand(item, 'ON') else: log.info('Unknown action {} in area {}'.format( action, self.name)) # OFF = vacant, do any vacant actions elif state == 'OFF': actions = self.occupancy_settings.get_vacant_actions() # Process any actions based 'ON' the tags for that area for action in actions: #log.info ('Action {}'.format (action)) if action == "LightsOff": for item in self.item.members: for tag in item.getTags(): if tag == "Lighting": send_command(item, 'OFF') elif action == "SceneOff": for item in self.item.members: for tag in item.getTags(): if tag == "AreaScene": events.sendCommand(item, 'OFF') elif action == "ExhaustFansOff": for item in self.item.members: for tag in item.getTags(): if tag == "ExhaustFan": events.sendCommand(item, 'OFF') elif action == "AVOff": for item in self.item.members: for tag in item.getTags(): if tag == "AVPower": events.sendCommand(item, 'OFF') else: log.info('Unknown action {} in area {}'.format( action, self.name)) else: #area locked log.warn( "Area {} is locked, occupancy state changed, should not happen" .format(self.name)) #self.update_group_OS_item(,event.oldItemState) **** cannot do this results in endless event loop #if event.oldItemState == 'ON': # do not allow area to be vacant if it was on and locked # self.update_group_OS_item('ON',item) else: log.info("Area {} has no settings".format(self.name))
def light_action(item, active): """ This function performs an action on a light Item. When called, this function pulls in the metadata for the supplied Item or uses the default values specified in ``configuration.area_triggers_and_actions_dict"["default_levels"]``, if the metadata does not exist. This metadata is then compared to the current lux level to determine if a light should be turned OFF or set to the specified level. This function should work for everyone without modification. Args: Item item: The Item to perform the action on boolean active: Area activity (True for active and False for inactive) """ #start_time = DateTime.now().getMillis() item_metadata = get_key_value(item.name, "area_triggers_and_actions", "modes", str(items["Mode"])) low_lux_trigger = item_metadata.get( "low_lux_trigger", area_triggers_and_actions_dict["default_levels"]["low_lux_trigger"]) hue = DecimalType( item_metadata.get( "hue", area_triggers_and_actions_dict["default_levels"]["hue"])) saturation = PercentType( str( item_metadata.get( "saturation", area_triggers_and_actions_dict["default_levels"] ["saturation"]))) brightness = PercentType( str( item_metadata.get( "brightness", area_triggers_and_actions_dict["default_levels"] ["brightness"]))) #log.warn("light_action: item.name [{}], active [{}], brightness [{}], lux [{}], low_lux_trigger [{}]".format(item.name, active, brightness, items[area_triggers_and_actions_dict["lux_item_name"]], low_lux_trigger)) lux_item_name = area_triggers_and_actions_dict.get("lux_item_name") if active and brightness > PercentType(0) and ( True if lux_item_name is None else items[lux_item_name].intValue() <= low_lux_trigger): if item.type == "Dimmer" or (item.type == "Group" and item.baseItem.type == "Dimmer"): if item.state != brightness: if item.state < PercentType(99): events.sendCommand(item, brightness) log.info(">>>>>>> {}: {}".format(item.name, brightness)) else: log.info( "[{}]: dimmer was manually set > 98, so not adjusting". format(item.name)) else: log.debug( "[{}]: dimmer is already set to [{}], so not sending command" .format(item.name, brightness)) elif item.type == "Color" or (item.type == "Group" and item.baseType == "Color"): if item.state != HSBType(hue, saturation, brightness): if item.state.brightness < PercentType(99): events.sendCommand(item, HSBType(hue, saturation, brightness)) log.info(">>>>>>> {}: [{}]".format( item.name, HSBType(hue, saturation, brightness))) else: log.info( "[{}]: brightness was manually set > 98, so not adjusting" .format(item.name)) else: log.debug( "[{}]: color is already set to [{}, {}, {}], so not sending command" .format(item.name, hue, saturation, brightness)) elif item.type == "Switch" or (item.type == "Group" and item.baseItem.type == "Switch"): if item.state == OFF: events.sendCommand(item, ON) log.info(">>>>>>> {}: ON".format(item.name)) else: log.debug( "[{}]: switch is already [ON], so not sending command". format(item.name)) else: if item.type == "Dimmer" or (item.type == "Group" and item.baseItem.type == "Dimmer"): if item.state != PercentType(0): if item.state < PercentType(99): events.sendCommand(item, PercentType(0)) log.info("<<<<<<<<<<<<<<<<<<<<< {}: 0".format(item.name)) else: log.info( "{}: dimmer was manually set > 98, so not adjusting". format(item.name)) else: log.debug( "[{}]: dimmer is already set to [0], so not sending command" .format(item.name)) elif item.type == "Color" or (item.type == "Group" and item.baseType == "Color"): if item.state != HSBType(DecimalType(0), PercentType(0), PercentType(0)): if item.state.brightness < PercentType(99): events.sendCommand(item, "0, 0, 0") log.info("<<<<<<<<<<<<<<<<<<<<< {}: [0, 0, 0]".format( item.name)) else: log.info( "{}: brightness was manually set > 98, so not adjusting" .format(item.name)) else: log.debug( "[{}]: color is already set to [0, 0, 0], so not sending command" .format(item.name)) elif item.type == "Switch" or (item.type == "Group" and item.baseItem.type == "Switch"): if item.state == ON: events.sendCommand(item, OFF) log.info("<<<<<<<<<<<<<<<<<<<<< {}: OFF".format(item.name)) else: log.debug( "[{}]: switch is already set to [OFF], so not sending command" .format(item.name))