def print_aldb(service): """Print the All-Link Database for a device.""" # For now this sends logs to the log file. # Future direction is to create an INSTEON control panel. entity_id = service.data[CONF_ENTITY_ID] signal = f"{entity_id}_{SIGNAL_PRINT_ALDB}" dispatcher_send(opp, signal)
def _frame_received(frame): """Run when a Zigbee frame is received. Pickles the frame, then encodes it into base64 since it contains non JSON serializable binary. """ dispatcher_send(opp, SIGNAL_ZIGBEE_FRAME_RECEIVED, frame)
def scan_devices(self, now: datetime | None = None) -> None: """Scan for new devices and return a list of found device ids.""" _LOGGER.debug("Checking devices for FRITZ!Box router %s", self.host) consider_home = self._options.get( CONF_CONSIDER_HOME, DEFAULT_CONSIDER_HOME.total_seconds() ) new_device = False for known_host in self._update_info(): if not known_host.get("mac"): continue dev_mac = known_host["mac"] dev_name = known_host["name"] dev_ip = known_host["ip"] dev_home = known_host["status"] dev_info = Device(dev_mac, dev_ip, dev_name) if dev_mac in self._devices: self._devices[dev_mac].update(dev_info, dev_home, consider_home) else: device = FritzDevice(dev_mac) device.update(dev_info, dev_home, consider_home) self._devices[dev_mac] = device new_device = True dispatcher_send(self.opp, self.signal_device_update) if new_device: dispatcher_send(self.opp, self.signal_device_new)
def update(self, status) -> None: """Update the iCloud device.""" self._status = status self._status[ ATTR_ACCOUNT_FETCH_INTERVAL] = self._account.fetch_interval device_status = DEVICE_STATUS_CODES.get(self._status[DEVICE_STATUS], "error") self._attrs[ATTR_DEVICE_STATUS] = device_status self._battery_status = self._status[DEVICE_BATTERY_STATUS] self._attrs[ATTR_BATTERY_STATUS] = self._battery_status device_battery_level = self._status.get(DEVICE_BATTERY_LEVEL, 0) if self._battery_status != "Unknown" and device_battery_level is not None: self._battery_level = int(device_battery_level * 100) self._attrs[ATTR_BATTERY] = self._battery_level self._attrs[ATTR_LOW_POWER_MODE] = self._status[ DEVICE_LOW_POWER_MODE] if (self._status[DEVICE_LOCATION] and self._status[DEVICE_LOCATION][DEVICE_LOCATION_LATITUDE]): location = self._status[DEVICE_LOCATION] if self._location is None: dispatcher_send(self._account.opp, self._account.signal_device_new) self._location = location
def _start_recovery(self): self._wrap_event_flag.clear() dispatcher_send(self._opp, service_signal(SERVICE_UPDATE, self._wrap_name)) self._unsub_recheck = track_time_interval(self._opp, self._wrap_test_online, RECHECK_INTERVAL)
def poll_device_update(event_time): """Update Smarty device.""" _LOGGER.debug("Updating Smarty device") if smarty.update(): _LOGGER.debug("Update success") dispatcher_send(opp, SIGNAL_UPDATE_SMARTY) else: _LOGGER.debug("Update failed")
def test_platform(self, mock_setup_component): """Test discover platform method.""" calls = [] @callback def platform_callback(platform, info): """Platform callback method.""" calls.append((platform, info)) run_callback_threadsafe( self.opp.loop, discovery.async_listen_platform, self.opp, "test_component", platform_callback, ).result() discovery.load_platform( self.opp, "test_component", "test_platform", "discovery info", {"test_component": {}}, ) self.opp.block_till_done() assert mock_setup_component.called assert mock_setup_component.call_args[0] == ( self.opp, "test_component", { "test_component": {} }, ) self.opp.block_till_done() discovery.load_platform( self.opp, "test_component_2", "test_platform", "discovery info", {"test_component": {}}, ) self.opp.block_till_done() assert len(calls) == 1 assert calls[0] == ("test_platform", "discovery info") dispatcher_send( self.opp, discovery.SIGNAL_PLATFORM_DISCOVERED, { "service": discovery.EVENT_LOAD_PLATFORM.format("test_component") }, ) self.opp.block_till_done() assert len(calls) == 1
def _signal_zone_update(self): """Signal a zone update. Whenever the underlying library does an action against a zone, the data for the zone is updated. Update a single zone. """ dispatcher_send(self.opp, f"{SIGNAL_ZONE_UPDATE}-{self._zone.zone_id}")
def _mqtt_on_disconnect(self, _mqttc, _userdata, result_code: int) -> None: """Disconnected callback.""" self.connected = False dispatcher_send(self.opp, MQTT_DISCONNECTED) _LOGGER.warning( "Disconnected from MQTT server %s:%s (%s)", self.conf[CONF_BROKER], self.conf[CONF_PORT], result_code, )
def update(self): """Update the registered zones.""" for device in self.devices: self.update_sensor("device", device["shortSerialNo"]) for zone in self.zones: self.update_sensor("zone", zone["id"]) self.data["weather"] = self.tado.getWeather() dispatcher_send( self.opp, SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, "weather", "data"), )
def handle_receive(event): """Handle received messages from w800rf32 gateway.""" # Log event if not event.device: return _LOGGER.debug("Receive W800rf32 event in handle_receive") # Get device_type from device_id in opp.data device_id = event.device.lower() signal = W800RF32_DEVICE.format(device_id) dispatcher_send(opp, signal, event)
def _signal_thermostat_update(self): """Signal a thermostat update. Whenever the underlying library does an action against a thermostat, the data for the thermostat and all connected zone is updated. Update all the zones on the thermostat. """ dispatcher_send( self.opp, f"{SIGNAL_THERMOSTAT_UPDATE}-{self._thermostat.thermostat_id}")
def callback_notify(notify): """Process NOTIFY message from STB.""" if notify.ip_address in opp.data[DATA_MEDIAROOM]: dispatcher_send(opp, SIGNAL_STB_NOTIFY, notify) return _LOGGER.debug("Discovered new stb %s", notify.ip_address) opp.data[DATA_MEDIAROOM].append(notify.ip_address) new_stb = MediaroomDevice(host=notify.ip_address, device_id=notify.device_uuid, optimistic=False) async_add_entities([new_stb])
def capture_image(call): """Capture a new image.""" entity_ids = call.data.get(ATTR_ENTITY_ID) target_entities = [ entity_id for entity_id in opp.data[DOMAIN].entity_ids if entity_id in entity_ids ] for entity_id in target_entities: signal = f"abode_camera_capture_{entity_id}" dispatcher_send(opp, signal)
def trigger_automation(call): """Trigger an Abode automation.""" entity_ids = call.data.get(ATTR_ENTITY_ID) target_entities = [ entity_id for entity_id in opp.data[DOMAIN].entity_ids if entity_id in entity_ids ] for entity_id in target_entities: signal = f"abode_trigger_automation_{entity_id}" dispatcher_send(opp, signal)
def _mqtt_on_connect(self, _mqttc, _userdata, _flags, result_code: int) -> None: """On connect callback. Resubscribe to all topics we were subscribed to and publish birth message. """ # pylint: disable=import-outside-toplevel import paho.mqtt.client as mqtt if result_code != mqtt.CONNACK_ACCEPTED: _LOGGER.error( "Unable to connect to the MQTT broker: %s", mqtt.connack_string(result_code), ) return self.connected = True dispatcher_send(self.opp, MQTT_CONNECTED) _LOGGER.info( "Connected to MQTT server %s:%s (%s)", self.conf[CONF_BROKER], self.conf[CONF_PORT], result_code, ) # Group subscriptions to only re-subscribe once for each topic. keyfunc = attrgetter("topic") for topic, subs in groupby(sorted(self.subscriptions, key=keyfunc), keyfunc): # Re-subscribe with the highest requested qos max_qos = max(subscription.qos for subscription in subs) self.opp.add_job(self._async_perform_subscription, topic, max_qos) if (CONF_BIRTH_MESSAGE in self.conf and ATTR_TOPIC in self.conf[CONF_BIRTH_MESSAGE]): async def publish_birth_message(birth_message): await self._op_started.wait( ) # Wait for Open Peer Power to start await self._discovery_cooldown( ) # Wait for MQTT discovery to cool down await self.async_publish( topic=birth_message.topic, payload=birth_message.payload, qos=birth_message.qos, retain=birth_message.retain, ) birth_message = Message(**self.conf[CONF_BIRTH_MESSAGE]) asyncio.run_coroutine_threadsafe( publish_birth_message(birth_message), self.opp.loop)
def handle_update_tags_event(self, event): """Handle push event from wireless tag manager.""" _LOGGER.info("Push notification for update arrived: %s", event) try: tag_id = event.data.get("id") mac = event.data.get("mac") dispatcher_send(self.opp, SIGNAL_TAG_UPDATE.format(tag_id, mac), event) except Exception as ex: # pylint: disable=broad-except _LOGGER.error( "Unable to handle tag update event:\ %s error: %s", str(event), str(ex), )
async def async_create_new_entities(address): _LOGGER.debug( "Adding new INSTEON device to Open Peer Power with address %s", address) await devices.async_save(workdir=opp.config.config_dir) device = devices[address] await device.async_status() platforms = get_device_platforms(device) for platform in platforms: if platform == ON_OFF_EVENTS: add_on_off_event_device(opp, device) else: signal = f"{SIGNAL_ADD_ENTITIES}_{platform}" dispatcher_send(opp, signal, {"address": device.address})
def update(self, now=None): """Get the latest data from iperf3.""" if self.protocol == "udp": # UDP only have 1 way attribute result = self._run_test(ATTR_DOWNLOAD) self.data[ATTR_DOWNLOAD] = self.data[ATTR_UPLOAD] = getattr( result, "Mbps", None) self.data[ATTR_VERSION] = getattr(result, "version", None) else: result = self._run_test(ATTR_DOWNLOAD) self.data[ATTR_DOWNLOAD] = getattr(result, "received_Mbps", None) self.data[ATTR_VERSION] = getattr(result, "version", None) self.data[ATTR_UPLOAD] = getattr(self._run_test(ATTR_UPLOAD), "sent_Mbps", None) dispatcher_send(self._opp, DATA_UPDATED, self.host)
def update(self): """Get the latest data from Transmission instance.""" try: self.data = self._api.session_stats() self._torrents = self._api.get_torrents() self._session = self._api.get_session() self.check_completed_torrent() self.check_started_torrent() self.check_removed_torrent() _LOGGER.debug("Torrent Data for %s Updated", self.host) self.available = True except TransmissionError: self.available = False _LOGGER.error("Unable to connect to Transmission client %s", self.host) dispatcher_send(self.opp, self.signal_update)
def handle_binary_event(self, event): """Handle push notifications for binary (on/off) events.""" _LOGGER.info("Push notification for binary event arrived: %s", event) try: tag_id = event.data.get("id") event_type = event.data.get("type") mac = event.data.get("mac") dispatcher_send( self.opp, SIGNAL_BINARY_EVENT_UPDATE.format(tag_id, event_type, mac), event, ) except Exception as ex: # pylint: disable=broad-except _LOGGER.error( "Unable to handle tag binary event:\ %s error: %s", str(event), str(ex), )
def discover_chromecast(opp: OpenPeerPower, device_info): """Discover a Chromecast.""" info = ChromecastInfo( services=device_info.services, uuid=device_info.uuid, model_name=device_info.model_name, friendly_name=device_info.friendly_name, is_audio_group=device_info.port != DEFAULT_PORT, ) if info.uuid is None: _LOGGER.error("Discovered chromecast without uuid %s", info) return info = info.fill_out_missing_chromecast_info() _LOGGER.debug("Discovered new or updated chromecast %s", info) dispatcher_send(opp, SIGNAL_CAST_DISCOVERED, info)
def command(self, *args, **kwargs): """amcrest.Http.command wrapper to catch errors.""" try: ret = super().command(*args, **kwargs) except LoginError as ex: with self._wrap_lock: was_online = self.available was_login_err = self._wrap_login_err self._wrap_login_err = True if not was_login_err: _LOGGER.error("%s camera offline: Login error: %s", self._wrap_name, ex) if was_online: self._start_recovery() raise except AmcrestError: with self._wrap_lock: was_online = self.available errs = self._wrap_errors = self._wrap_errors + 1 offline = not self.available _LOGGER.debug("%s camera errs: %i", self._wrap_name, errs) if was_online and offline: _LOGGER.error("%s camera offline: Too many errors", self._wrap_name) self._start_recovery() raise with self._wrap_lock: was_offline = not self.available self._wrap_errors = 0 self._wrap_login_err = False if was_offline: self._unsub_recheck() self._unsub_recheck = None _LOGGER.error("%s camera back online", self._wrap_name) self._wrap_event_flag.set() dispatcher_send(self._opp, service_signal(SERVICE_UPDATE, self._wrap_name)) return ret
def _monitor_events(opp, name, api, event_codes): event_codes = set(event_codes) while True: api.available_flag.wait() try: for code, payload in api.event_actions("All", retries=5): event_data = { "camera": name, "event": code, "payload": payload } opp.bus.fire("amcrest", event_data) if code in event_codes: signal = service_signal(SERVICE_EVENT, name, code) start = any( str(key).lower() == "action" and str(val).lower() == "start" for key, val in payload.items()) _LOGGER.debug("Sending signal: '%s': %s", signal, start) dispatcher_send(opp, signal, start) except AmcrestError as error: _LOGGER.warning("Error while processing events from %s camera: %r", name, error)
def update(self, now: datetime.datetime | None = None) -> None: """Request new Sonos favorites from a speaker.""" new_favorites = None discovered = self.opp.data[DATA_SONOS].discovered for uid, speaker in discovered.items(): try: new_favorites = speaker.soco.music_library.get_sonos_favorites( ) except SoCoException as err: _LOGGER.warning("Error requesting favorites from %s: %s", speaker.soco, err) else: # Prefer this SoCo instance next update discovered.move_to_end(uid, last=False) break if new_favorites is None: _LOGGER.error("Could not reach any speakers to update favorites") return self._favorites = [] for fav in new_favorites: try: # exclude non-playable favorites with no linked resources if fav.reference.resources: self._favorites.append(fav) except SoCoException as ex: # Skip unknown types _LOGGER.error("Unhandled favorite '%s': %s", fav.title, ex) _LOGGER.debug( "Cached %s favorites for household %s", len(self._favorites), self.household_id, ) dispatcher_send(self.opp, f"{SONOS_HOUSEHOLD_UPDATED}-{self.household_id}")
def update_sensor(self, sensor_type, sensor): """Update the internal data from Tado.""" _LOGGER.debug("Updating %s %s", sensor_type, sensor) try: if sensor_type == "device": data = self.tado.getDeviceInfo(sensor) if ( INSIDE_TEMPERATURE_MEASUREMENT in data["characteristics"]["capabilities"] ): data[TEMP_OFFSET] = self.tado.getDeviceInfo(sensor, TEMP_OFFSET) elif sensor_type == "zone": data = self.tado.getZoneState(sensor) else: _LOGGER.debug("Unknown sensor: %s", sensor_type) return except RuntimeError: _LOGGER.error( "Unable to connect to Tado while updating %s %s", sensor_type, sensor, ) return self.data[sensor_type][sensor] = data _LOGGER.debug( "Dispatching update to %s %s %s: %s", self.home_id, sensor_type, sensor, data, ) dispatcher_send( self.opp, SIGNAL_TADO_UPDATE_RECEIVED.format(self.home_id, sensor_type, sensor), )
def signal_update() -> None: """Signal updates to data.""" dispatcher_send(opp, UPDATE_SIGNAL, url)
def update(self): """Update device properties and send data updated signal.""" self._update_properties() dispatcher_send(self._opp, DATA_UPDATED.format(self._host))
def _initialize_device(self): self._get_capabilities() self._initialized = True dispatcher_send(self._opp, DEVICE_INITIALIZED.format(self._host))
def _remove_entity(self, external_id): """Remove entity.""" dispatcher_send(self._opp, f"ign_sismologia_delete_{external_id}")