Source code for caspia.gateway.rules.activate_button

# pylint: disable=line-too-long,too-many-return-statements,too-many-branches
from caspia.gateway import services as gateway_services
from caspia.meadow import observers, rules, services
from caspia.node import components, pollen_action


[docs]def activate_on_do_rule(rule: rules.OnDoRule, context) -> bool: # on button push, release is_btn_char = isinstance(rule.on, services.Characteristic) and isinstance( rule.on.service, gateway_services.Button) is_btn_char = is_btn_char and (rule.on.name in ['push', 'release']) if is_btn_char: return activate_rule_on_button_characteristic_notification(rule, context) # on button hold, click is_btn_evt = isinstance(rule.on, (services.ButtonHoldEvent, services.ButtonClickEvent)) if is_btn_evt: return activate_rule_on_button_event(rule, context) return None
[docs]def activate_rule_on_button_characteristic_notification(rule, context): assert isinstance(rule, rules.OnDoRule) is_btn_char = isinstance(rule.on, services.Characteristic) is_btn_char = is_btn_char and isinstance(rule.on.service, gateway_services.Button) is_btn_char = is_btn_char and (rule.on.name in ['push', 'release']) if not is_btn_char: return False pollen_data = create_pollen_data_for_button_observer(rule.do, rule.on, context) if pollen_data is None: return False button_s = rule.on.service if rule.on.name == 'push': trigger = components.Button.EventConfig.TRIGGER_PUSH elif rule.on.name == 'release': trigger = components.Button.EventConfig.TRIGGER_RELEASE button_s.button_c.config.add_event(create_button_event(trigger, pollen_data)) return True
[docs]def activate_rule_on_button_event(rule, context): """Activate rule, where rule.on is ButtonClickEvent or ButtonHoldEvent.""" pollen_data = create_pollen_data_for_button_observer(observer=rule.do, observable=rule.on, context=context) if pollen_data is None: return None button_s = rule.on.button if isinstance(rule.on, services.ButtonClickEvent): event = create_button_event(0, pollen_data, cancelling=True) else: # ButtonHoldEvent event = create_button_event(rule.on.interval, pollen_data, cancelling=rule.on.cancelling) button_s.button_c.config.add_event(event) return True
[docs]def create_button_event(trigger, pollen_data, cancelling=True): ptype, address, data = pollen_data if ptype == 'request': evt_type = components.Button.EventConfig.TYPE_REQUEST elif ptype == 'broadcast': evt_type = components.Button.EventConfig.TYPE_BROADCAST else: raise ValueError('Could not create button event with type %r' % ptype) return components.Button.EventConfig(trigger=trigger, evt_type=evt_type, addr=address, data=data, canceling=cancelling)
[docs]def create_pollen_data_for_button_observer(observer, observable, context): """Return (type, address, data), for example ('request', 0x1C, b'test') or None if not supported.""" if isinstance(observer, observers.CharacteristicObserver): characteristic = observer.characteristic lightgroup_behavior = context.get_lightgroup_behavior(characteristic.service, create=False) if lightgroup_behavior: if characteristic.name == 'toggle': return pollen_action.build(components.relay.Relay.group_toggle, lightgroup_behavior.identifier) elif characteristic.name == 'is_on' and observer.value: return pollen_action.build(components.relay.Relay.group_on, lightgroup_behavior.identifier) elif characteristic.name == 'is_on' and not observer.value: return pollen_action.build(components.relay.Relay.group_off, lightgroup_behavior.identifier) elif isinstance(characteristic.service, gateway_services.RelayBasedServiceMixin): if characteristic.name == 'toggle': return pollen_action.build(components.relay.Relay.toggle, characteristic.service.relay_c) elif characteristic.name == 'is_on' and observer.value: return pollen_action.build(components.relay.Relay.on, characteristic.service.relay_c) elif characteristic.name == 'is_on' and not observer.value: return pollen_action.build(components.relay.Relay.off, characteristic.service.relay_c) elif isinstance(characteristic.service, gateway_services.Blinds): if characteristic.name == 'move_up': return pollen_action.build(components.blinds.Blinds.move_up, characteristic.service.blinds_c) elif characteristic.name == 'move_down': return pollen_action.build(components.blinds.Blinds.move_down, characteristic.service.blinds_c) elif characteristic.name == 'stop_movement': return pollen_action.build(components.blinds.Blinds.stop_movement, characteristic.service.blinds_c) elif characteristic.name == 'calibrate': return pollen_action.build(components.blinds.Blinds.calibrate, characteristic.service.blinds_c) return None elif isinstance(observer, services.button.ButtonTriggerEvent): button_c = observable.button.button_c if isinstance(observable, services.button.ButtonClickEvent): evt_type = components.Button.ButtonEvent.EVENT_CLICK interval = None elif isinstance(observable, services.button.ButtonHoldEvent): evt_type = components.Button.ButtonEvent.EVENT_HOLD interval = observable.interval else: raise ValueError('Invalid observable class %r' % observable) data = components.Button.ButtonEvent.create_raw_broadcast_data(button_c.identifier, evt_type, interval=interval) return ('broadcast', components.button.Button.type | 0x100, data) return None