Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
 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
Example #6
0
 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
Example #7
0
    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
Example #8
0
    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
Example #9
0
    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
Example #10
0
 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
Example #11
0
 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
Example #12
0
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
Example #13
0
 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
Example #14
0
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
Example #15
0
    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
Example #16
0
    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
Example #17
0
    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}")
Example #18
0
    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
Example #19
0
    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
Example #20
0
 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
Example #21
0
 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"
     )
Example #22
0
    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 ""
Example #23
0
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
Example #24
0
    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}"
            )