def _handle_push_notification(self, namespace, payload, from_myself=False): def fire_switch_state_change(dev, channel_id, o_state, n_state, f_myself): if o_state != n_state: evt = DeviceSwitchStatusEvent(dev=dev, channel_id=channel_id, switch_state=n_state, generated_by_myself=f_myself) self.fire_event(evt) with self._state_lock: if namespace == TOGGLE: # Update the local state and fire the event only if the state actually changed channel_index = 0 old_switch_state = self._state.get(channel_index) switch_state = payload['toggle']['onoff'] == 1 self._state[channel_index] = switch_state fire_switch_state_change(self, channel_index, old_switch_state, switch_state, from_myself) return True elif namespace == TOGGLEX: if isinstance(payload['togglex'], list): for c in payload['togglex']: # Update the local state and fire the event only if the state actually changed channel_index = c['channel'] old_switch_state = self._state.get(channel_index) switch_state = c['onoff'] == 1 self._state[channel_index] = switch_state fire_switch_state_change(self, channel_index, old_switch_state, switch_state, from_myself) return True elif isinstance(payload['togglex'], dict): # Update the local state and fire the event only if the state actually changed channel_index = payload['togglex']['channel'] old_switch_state = self._state.get(channel_index) switch_state = payload['togglex']['onoff'] == 1 self._state[channel_index] = switch_state fire_switch_state_change(self, channel_index, old_switch_state, switch_state, from_myself) return True elif namespace == REPORT: # Ignoring REPORT l.info("Report event is currently unhandled.") return False elif namespace == CONSUMPTIONX: # Ignoring l.info("ConsumptionX push event is currently ignored") return False else: l.error("Unknown/Unsupported namespace/command: %s" % namespace) l.debug("Namespace: %s, Data: %s" % (namespace, payload)) return False
def _operate_door(self, channel, state, callback, wait_for_sensor_confirmation): # If the door is already in the target status, do not execute the command. already_in_state = False with self._state_lock: already_in_state = self.get_status()[channel] == state if already_in_state and callback is None: l.info("Command was not executed: the door state is already %s" % ("open" if state else "closed")) return elif already_in_state and callback is not None: callback(None, self._door_state[channel]) return payload = { "state": { "channel": channel, "open": state, "uuid": self.uuid } } if wait_for_sensor_confirmation: door_event = None if callback is None: door_event = Event() def waiter(data): self.unregister_event_callback(waiter) if data.channel != channel: return if callback is None: door_event.set() else: if not compare_same_states(data.door_state, state): callback("Operation failed", data.door_state) else: callback(None, data.door_state) self.register_event_callback(waiter) self.execute_command(command="SET", namespace=GARAGE_DOOR_STATE, payload=payload, callback=None) if callback is None: door_event.wait() current_state = self._door_state[channel] if current_state != state: raise Exception("Operation failed.") else: self.execute_command(command="SET", namespace=GARAGE_DOOR_STATE, payload=payload, callback=callback)