async def _async_update_data(self) -> None: """Update the state.""" try: await self.hass.async_add_executor_job(self.client.update_info) except (OSError, RequestException) as ex: raise update_coordinator.UpdateFailed( f"Exception during Venstar info update: {ex}") from ex # older venstars sometimes cannot handle rapid sequential connections await asyncio.sleep(1) try: await self.hass.async_add_executor_job(self.client.update_sensors) except (OSError, RequestException) as ex: raise update_coordinator.UpdateFailed( f"Exception during Venstar sensor update: {ex}") from ex # older venstars sometimes cannot handle rapid sequential connections await asyncio.sleep(1) try: await self.hass.async_add_executor_job(self.client.update_alerts) except (OSError, RequestException) as ex: raise update_coordinator.UpdateFailed( f"Exception during Venstar alert update: {ex}") from ex return None
async def _async_update_data(self) -> None: """Fetch data.""" if not self.device.connected: raise update_coordinator.UpdateFailed("Device disconnected") try: LOGGER.debug("Polling Shelly RPC Device - %s", self.name) async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC): await self.device.update_status() except (OSError, aioshelly.exceptions.RPCTimeout) as err: raise update_coordinator.UpdateFailed( "Device disconnected") from err
async def _async_update_data(self): """Fetch data.""" if self.entry.data.get("sleep_period"): # Sleeping device, no point polling it, just mark it unavailable raise update_coordinator.UpdateFailed("Sleeping device did not update") _LOGGER.debug("Polling Shelly Device - %s", self.name) try: async with async_timeout.timeout(POLLING_TIMEOUT_SEC): return await self.device.update() except OSError as err: raise update_coordinator.UpdateFailed("Error fetching data") from err
async def _async_update_data(self) -> None: """Fetch data.""" if sleep_period := self.entry.data.get("sleep_period"): # Sleeping device, no point polling it, just mark it unavailable raise update_coordinator.UpdateFailed( f"Sleeping device did not update within {sleep_period} seconds interval" )
async def _async_update_data(self) -> None: """Fetch data.""" data = await self.open_garage_connection.update_state() if data is None: raise update_coordinator.UpdateFailed( "Unable to connect to OpenGarage device") return data
async def _async_update_data(self): try: async with async_timeout.timeout(5): await self.async_update() except ConnectionError as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err
async def _async_update_data(self): """Update the data from the SolarLog device.""" try: api = await self.hass.async_add_executor_job(SolarLog, self.host) except (OSError, Timeout, HTTPError) as err: raise update_coordinator.UpdateFailed(err) if api.time.year == 1999: raise update_coordinator.UpdateFailed( "Invalid data returned (can happen after Solarlog restart).") self.logger.debug( "Connection to Solarlog successful. Retrieving latest Solarlog update of %s", api.time, ) data = {} try: data["TIME"] = api.time data["powerAC"] = api.power_ac data["powerDC"] = api.power_dc data["voltageAC"] = api.voltage_ac data["voltageDC"] = api.voltage_dc data["yieldDAY"] = api.yield_day / 1000 data["yieldYESTERDAY"] = api.yield_yesterday / 1000 data["yieldMONTH"] = api.yield_month / 1000 data["yieldYEAR"] = api.yield_year / 1000 data["yieldTOTAL"] = api.yield_total / 1000 data["consumptionAC"] = api.consumption_ac data["consumptionDAY"] = api.consumption_day / 1000 data["consumptionYESTERDAY"] = api.consumption_yesterday / 1000 data["consumptionMONTH"] = api.consumption_month / 1000 data["consumptionYEAR"] = api.consumption_year / 1000 data["consumptionTOTAL"] = api.consumption_total / 1000 data["totalPOWER"] = api.total_power data["alternatorLOSS"] = api.alternator_loss data["CAPACITY"] = round(api.capacity * 100, 0) data["EFFICIENCY"] = round(api.efficiency * 100, 0) data["powerAVAILABLE"] = api.power_available data["USAGE"] = round(api.usage * 100, 0) except AttributeError as err: raise update_coordinator.UpdateFailed( f"Missing details data in Solarlog response: {err}") from err _LOGGER.debug("Updated Solarlog overview data: %s", data) return data
async def _async_update_data(self): """Fetch data.""" try: async with async_timeout.timeout(5): return await self.device.update() except (aiocoap.error.Error, OSError) as err: raise update_coordinator.UpdateFailed("Error fetching data") from err
async def _async_update_data(self): """Update the data from the SolarLog device.""" try: data = await self.hass.async_add_executor_job(SolarLog, self.host) except (OSError, Timeout, HTTPError) as err: raise update_coordinator.UpdateFailed(err) if data.time.year == 1999: raise update_coordinator.UpdateFailed( "Invalid data returned (can happen after Solarlog restart).") self.logger.debug( "Connection to Solarlog successful. Retrieving latest Solarlog update of %s", data.time, ) return data
async def _async_update_data(self): """Fetch data.""" try: async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC): _LOGGER.debug("REST update for %s", self.name) return await self.device.update_status() except OSError as err: raise update_coordinator.UpdateFailed("Error fetching data") from err
async def _async_update_data(self): """Fetch data.""" _LOGGER.debug("Polling Shelly Device - %s", self.name) try: async with async_timeout.timeout(POLLING_TIMEOUT_SEC): return await self.device.update() except OSError as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err
async def get_newest_version(hass, huuid, include_components): """Get the newest Home Assistant version.""" if huuid: info_object = await hass.helpers.system_info.async_get_system_info() if include_components: info_object["components"] = list(hass.config.components) linux_dist = await hass.async_add_executor_job(linux_distribution, False) info_object["distribution"] = linux_dist[0] info_object["os_version"] = linux_dist[1] info_object["huuid"] = huuid else: info_object = {} session = async_get_clientsession(hass) with async_timeout.timeout(30): req = await session.post(UPDATER_URL, json=info_object) _LOGGER.info( ( "Submitted analytics to Home Assistant servers. " "Information submitted includes %s" ), info_object, ) try: res = await req.json() except ValueError as err: raise update_coordinator.UpdateFailed( "Received invalid JSON from Home Assistant Update" ) from err try: res = RESPONSE_SCHEMA(res) return res["version"], res["release-notes"] except vol.Invalid as err: raise update_coordinator.UpdateFailed( f"Got unexpected response: {err}" ) from err
async def _async_update_data(self): """Fetch data.""" try: async with async_timeout.timeout(5): _LOGGER.debug("REST update for %s", self.device.settings["device"]["hostname"]) return await self.device.update_status() except OSError as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err
async def get_newest_version(hass): """Get the newest Home Assistant version.""" session = async_get_clientsession(hass) async with async_timeout.timeout(30): req = await session.get(UPDATER_URL) try: res = await req.json() except ValueError as err: raise update_coordinator.UpdateFailed( "Received invalid JSON from Home Assistant Update") from err try: res = RESPONSE_SCHEMA(res) return res["current_version"], res["release_notes"] except vol.Invalid as err: raise update_coordinator.UpdateFailed( f"Got unexpected response: {err}") from err
async def _async_update_data(self): """Fetch data.""" # Race condition on shutdown. Stop all the fetches. if self._unsub_stop is None: return None try: async with async_timeout.timeout(5): return await self.device.update() except (aiocoap_error.Error, OSError) as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err
async def _async_update_data(self) -> None: """Fetch data.""" if self.device.connected: return try: _LOGGER.debug("Reconnecting to Shelly RPC Device - %s", self.name) async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC): await self.device.initialize() except OSError as err: raise update_coordinator.UpdateFailed( "Device disconnected") from err
async def async_get_districts(): """Fetch data from API endpoint. Here the data for each district is loaded. """ try: with async_timeout.timeout(10): return { case.county: case for case in await api.load_districts() } except (asyncio.TimeoutError, aiohttp.ClientError) as err: raise update_coordinator.UpdateFailed( f"Error communicating with API: {err}")
async def update_data(): """Update the data.""" async with async_timeout.timeout(2.5): state = await client.get_state() if state["muted"] is None or state["in_meeting"] is None: raise update_coordinator.UpdateFailed("Got invalid response") if state["in_meeting"]: coordinator.update_interval = UPDATE_INTERVAL_IN_MEETING else: coordinator.update_interval = UPDATE_INTERVAL_NOT_IN_MEETING return state
async def _async_update_data(self) -> None: """Fetch data.""" try: async with async_timeout.timeout(AIOSHELLY_DEVICE_TIMEOUT_SEC): LOGGER.debug("REST update for %s", self.name) await self.device.update_status() if self.device.status[ "uptime"] > 2 * REST_SENSORS_UPDATE_INTERVAL: return old_firmware = self.device.firmware_version await self.device.update_shelly() if self.device.firmware_version == old_firmware: return device_update_info(self.hass, self.device, self.entry) except OSError as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err
async def _async_update_data(self) -> None: """Update FritzboxTools data.""" try: await self.async_scan_devices() except FRITZ_EXCEPTIONS as ex: raise update_coordinator.UpdateFailed(ex) from ex
async def _async_update_data(self) -> None: """Mark device offline if no data.""" raise update_coordinator.UpdateFailed( f"Device {self.name} did not send update for {MAX_UPDATE_INTERVAL_SEC} seconds" )
async def _async_update_data(self) -> None: """Fetch data.""" if sleep_period := self.entry.data.get(CONF_SLEEP_PERIOD): # Sleeping device, no point polling it, just mark it unavailable raise update_coordinator.UpdateFailed( f"Sleeping device did not update within {sleep_period} seconds interval" ) LOGGER.debug("Polling Shelly Block Device - %s", self.name) try: async with async_timeout.timeout(POLLING_TIMEOUT_SEC): await self.device.update() device_update_info(self.hass, self.device, self.entry) except OSError as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err @property def model(self) -> str: """Model of the device.""" return cast(str, self.entry.data["model"]) @property def mac(self) -> str: """Mac address of the device.""" return cast(str, self.entry.unique_id) @property def sw_version(self) -> str: """Firmware version of the device.""" return self.device.firmware_version if self.device.initialized else ""
class BlockDeviceWrapper(update_coordinator.DataUpdateCoordinator): """Wrapper for a Shelly block based device with Home Assistant specific functions.""" def __init__(self, hass: HomeAssistant, entry: ConfigEntry, device: BlockDevice) -> None: """Initialize the Shelly device wrapper.""" self.device_id: str | None = None sleep_period = entry.data["sleep_period"] if sleep_period: update_interval = SLEEP_PERIOD_MULTIPLIER * sleep_period else: update_interval = (UPDATE_PERIOD_MULTIPLIER * device.settings["coiot"]["update_period"]) device_name = (get_block_device_name(device) if device.initialized else entry.title) super().__init__( hass, _LOGGER, name=device_name, update_interval=timedelta(seconds=update_interval), ) self.hass = hass self.entry = entry self.device = device entry.async_on_unload( self.async_add_listener(self._async_device_updates_handler)) self._last_input_events_count: dict = {} entry.async_on_unload( hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self._handle_ha_stop)) @callback def _async_device_updates_handler(self) -> None: """Handle device updates.""" if not self.device.initialized: return assert self.device.blocks # For buttons which are battery powered - set initial value for last_event_count if self.model in SHBTN_MODELS and self._last_input_events_count.get( 1) is None: for block in self.device.blocks: if block.type != "device": continue if block.wakeupEvent[0] == "button": self._last_input_events_count[1] = -1 break # Check for input events for block in self.device.blocks: if ("inputEvent" not in block.sensor_ids or "inputEventCnt" not in block.sensor_ids): continue channel = int(block.channel or 0) + 1 event_type = block.inputEvent last_event_count = self._last_input_events_count.get(channel) self._last_input_events_count[channel] = block.inputEventCnt if (last_event_count is None or last_event_count == block.inputEventCnt or event_type == ""): continue if event_type in INPUTS_EVENTS_DICT: self.hass.bus.async_fire( EVENT_SHELLY_CLICK, { ATTR_DEVICE_ID: self.device_id, ATTR_DEVICE: self.device.settings["device"]["hostname"], ATTR_CHANNEL: channel, ATTR_CLICK_TYPE: INPUTS_EVENTS_DICT[event_type], ATTR_GENERATION: 1, }, ) else: _LOGGER.warning( "Shelly input event %s for device %s is not supported, please open issue", event_type, self.name, ) async def _async_update_data(self) -> None: """Fetch data.""" if sleep_period := self.entry.data.get("sleep_period"): # Sleeping device, no point polling it, just mark it unavailable raise update_coordinator.UpdateFailed( f"Sleeping device did not update within {sleep_period} seconds interval" ) _LOGGER.debug("Polling Shelly Block Device - %s", self.name) try: async with async_timeout.timeout(POLLING_TIMEOUT_SEC): await self.device.update() except OSError as err: raise update_coordinator.UpdateFailed( "Error fetching data") from err
async def async_get_districts(): """Fetch data from rki-covid-parser library. Here the data for each district is loaded. """ _LOGGER.debug("fetch data from rki-covid-parser.") try: with async_timeout.timeout(30): # return {case.county: case for case in await api.load_districts()} await parser.load_data() _LOGGER.debug("fetching finished.") items = {} # districts for d in parser.districts: district = parser.districts[d] items[district.county] = DistrictData( district.name, district.county, district.state, district.population, district.cases, district.deaths, district.casesPerWeek, district.recovered, district.weekIncidence, district.casesPer100k, district.newCases, district.newDeaths, district.newRecovered, district.lastUpdate, ) # states for s in parser.states: state = parser.states[s] name = "BL " + state.name items[name] = DistrictData( name, name, None, state.population, state.cases, state.deaths, state.casesPerWeek, state.recovered, state.weekIncidence, state.casesPer100k, state.newCases, state.newDeaths, state.newRecovered, state.lastUpdate, ) # country items["Deutschland"] = DistrictData( "Deutschland", "Deutschland", None, parser.country.population, parser.country.cases, parser.country.deaths, parser.country.casesPerWeek, parser.country.recovered, parser.country.weekIncidence, parser.country.casesPer100k, parser.country.newCases, parser.country.newDeaths, parser.country.newRecovered, parser.country.lastUpdate, ) _LOGGER.debug("parsing data finished.") return items except asyncio.TimeoutError as err: raise update_coordinator.UpdateFailed( f"Error reading data from rki-covid-parser timed-out: {err}" ) except aiohttp.ClientError as err: raise update_coordinator.UpdateFailed( f"Error reading data from rki-covid-parser by client: {err}" )