Beispiel #1
0
    def extra_state_attributes(self):
        """Return the attributes of the sensor."""
        val = {ATTR_ATTRIBUTION: ATTRIBUTION}
        if self._email not in self._data.data:
            return val

        for idx, value in enumerate(self._data.data[self._email]):
            tmpname = f"breach {idx + 1}"
            datetime_local = dt_util.as_local(
                dt_util.parse_datetime(value["AddedDate"]))
            tmpvalue = f"{value['Title']} {datetime_local.strftime(DATE_STR_FORMAT)}"
            val[tmpname] = tmpvalue

        return val
Beispiel #2
0
async def test_intervals(opp):
    """Test timing intervals of sensors."""
    device = time_date.TimeDateSensor(opp, "time")
    now = dt_util.utc_from_timestamp(45.5)
    with patch("openpeerpower.util.dt.utcnow", return_value=now):
        next_time = device.get_next_interval()
    assert next_time == dt_util.utc_from_timestamp(60)

    device = time_date.TimeDateSensor(opp, "beat")
    now = dt_util.parse_datetime("2020-11-13 00:00:29+01:00")
    with patch("openpeerpower.util.dt.utcnow", return_value=now):
        next_time = device.get_next_interval()
    assert next_time == dt_util.parse_datetime("2020-11-13 00:01:26.4+01:00")

    device = time_date.TimeDateSensor(opp, "date_time")
    now = dt_util.utc_from_timestamp(1495068899)
    with patch("openpeerpower.util.dt.utcnow", return_value=now):
        next_time = device.get_next_interval()
    assert next_time == dt_util.utc_from_timestamp(1495068900)

    now = dt_util.utcnow()
    device = time_date.TimeDateSensor(opp, "time_date")
    next_time = device.get_next_interval()
    assert next_time > now
 def __init__(self, config: typing.Dict) -> None:
     """Initialize a select input."""
     self._config = config
     self.editable = True
     self._current_datetime = None
     initial = config.get(CONF_INITIAL)
     if initial:
         if self.has_date and self.has_time:
             self._current_datetime = dt_util.parse_datetime(initial)
         elif self.has_date:
             date = dt_util.parse_date(initial)
             self._current_datetime = datetime.datetime.combine(date, DEFAULT_TIME)
         else:
             time = dt_util.parse_time(initial)
             self._current_datetime = datetime.datetime.combine(DEFAULT_DATE, time)
Beispiel #4
0
    def async_update_callback(self):
        """Fire the event if reason is that state is updated."""
        if (self.sensor.state == self._last_state or
                # Filter out old states. Can happen when events fire while refreshing
                dt_util.parse_datetime(self.sensor.state["lastupdated"]) <=
                dt_util.parse_datetime(self._last_state["lastupdated"])):
            return

        # Extract the press code as state
        if hasattr(self.sensor, "rotaryevent"):
            state = self.sensor.rotaryevent
        else:
            state = self.sensor.buttonevent

        self._last_state = dict(self.sensor.state)

        # Fire event
        data = {
            CONF_ID: self.event_id,
            CONF_UNIQUE_ID: self.unique_id,
            CONF_EVENT: state,
            CONF_LAST_UPDATED: self.sensor.lastupdated,
        }
        self.bridge.opp.bus.async_fire(CONF_HUE_EVENT, data)
 def _get_daily_forecast_from_weather_response(self, weather_response, now):
     if weather_response.daily:
         parse = False
         forecast = []
         for day in weather_response.daily[ATTR_DATA][0][
                 AEMET_ATTR_FORECAST][AEMET_ATTR_DAY]:
             day_date = dt_util.parse_datetime(day[AEMET_ATTR_DATE])
             if now.date() == day_date.date():
                 parse = True
             if parse:
                 cur_forecast = self._convert_forecast_day(day_date, day)
                 if cur_forecast:
                     forecast.append(cur_forecast)
         return forecast
     return None
Beispiel #6
0
    async def load_auth_tokens(store) -> tuple[dict, dict | None]:
        app_storage = await store.async_load()
        tokens = dict(app_storage or {})

        if tokens.pop(CONF_USERNAME, None) != config[DOMAIN][CONF_USERNAME]:
            # any tokens won't be valid, and store might be be corrupt
            await store.async_save({})
            return ({}, None)

        # evohomeasync2 requires naive/local datetimes as strings
        if tokens.get(ACCESS_TOKEN_EXPIRES) is not None:
            tokens[ACCESS_TOKEN_EXPIRES] = _dt_aware_to_naive(
                dt_util.parse_datetime(tokens[ACCESS_TOKEN_EXPIRES]))

        user_data = tokens.pop(USER_DATA, None)
        return (tokens, user_data)
Beispiel #7
0
    def _async_handle_update(self, *args, **kwargs) -> None:
        """Update the state using webhook data."""
        if self._cancel_update:
            self._cancel_update()
            self._cancel_update = None

        if args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_DELAY_ON:
            endtime = parse_datetime(args[0][0][KEY_RAIN_DELAY_END])
            _LOGGER.debug("Rain delay expires at %s", endtime)
            self._state = True
            self._cancel_update = async_track_point_in_utc_time(
                self.opp, self._delay_expiration, endtime)
        elif args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_DELAY_OFF:
            self._state = False

        self.async_write_op_state()
Beispiel #8
0
def log_rate_limits(opp, target, resp, level=20):
    """Output rate limit log line at given level."""
    rate_limits = resp["rateLimits"]
    resetsAt = dt_util.parse_datetime(rate_limits["resetsAt"])
    resetsAtTime = resetsAt - dt_util.utcnow()
    rate_limit_msg = ("iOS push notification rate limits for %s: "
                      "%d sent, %d allowed, %d errors, "
                      "resets in %s")
    _LOGGER.log(
        level,
        rate_limit_msg,
        ios.device_name_for_push_id(opp, target),
        rate_limits["successful"],
        rate_limits["maximum"],
        rate_limits["errors"],
        str(resetsAtTime).split(".")[0],
    )
Beispiel #9
0
async def async_parse_last_reboot(uid: str, msg) -> Event:
    """Handle parsing event message.

    Topic: tns1:Monitoring/OperatingTime/LastReboot
    """
    try:
        return Event(
            f"{uid}_{msg.Topic._value_1}",
            "Last Reboot",
            "sensor",
            "timestamp",
            None,
            dt_util.as_local(
                dt_util.parse_datetime(msg.Message._value_1.Data.SimpleItem[0].Value)
            ),
        )
    except (AttributeError, KeyError, ValueError):
        return None
Beispiel #10
0
def last_run_was_recently_clean(cursor):
    """Verify the last recorder run was recently clean."""

    cursor.execute("SELECT end FROM recorder_runs ORDER BY start DESC LIMIT 1;")
    end_time = cursor.fetchone()

    if not end_time or not end_time[0]:
        return False

    last_run_end_time = process_timestamp(dt_util.parse_datetime(end_time[0]))
    now = dt_util.utcnow()

    _LOGGER.debug("The last run ended at: %s (now: %s)", last_run_end_time, now)

    if last_run_end_time + MAX_RESTART_TIME < now:
        return False

    return True
Beispiel #11
0
async def test_form_duplicated_id(opp):
    """Test setting up duplicated entry."""

    now = dt_util.parse_datetime("2021-01-09 12:00:00+00:00")
    with patch("openpeerpower.util.dt.now", return_value=now), patch(
            "openpeerpower.util.dt.utcnow",
            return_value=now), requests_mock.mock() as _m:
        aemet_requests_mock(_m)

        entry = MockConfigEntry(domain=DOMAIN,
                                unique_id="40.30403754--3.72935236",
                                data=CONFIG)
        entry.add_to_opp(opp)

        result = await opp.config_entries.flow.async_init(
            DOMAIN, context={"source": SOURCE_USER}, data=CONFIG)

        assert result["type"] == "abort"
        assert result["reason"] == "already_configured"
Beispiel #12
0
    async def async_callback(self, payload):
        """Handle received data."""
        errors = payload.get("errors")
        if errors:
            _LOGGER.error(errors[0])
            return
        data = payload.get("data")
        if data is None:
            return
        live_measurement = data.get("liveMeasurement")
        if live_measurement is None:
            return

        timestamp = dt_util.parse_datetime(live_measurement.pop("timestamp"))
        new_entities = []
        for sensor_type, state in live_measurement.items():
            if state is None or sensor_type not in RT_SENSOR_MAP:
                continue
            if sensor_type in self._entities:
                async_dispatcher_send(
                    self.opp,
                    SIGNAL_UPDATE_ENTITY.format(self._entities[sensor_type]),
                    state,
                    timestamp,
                )
            else:
                sensor_name, device_class, unit, state_class = RT_SENSOR_MAP[
                    sensor_type
                ]
                if sensor_type == "accumulatedCost":
                    unit = self._tibber_home.currency
                entity = TibberSensorRT(
                    self._tibber_home,
                    sensor_name,
                    device_class,
                    unit,
                    state,
                    state_class,
                )
                new_entities.append(entity)
                self._entities[sensor_type] = entity.unique_id
        if new_entities:
            self._async_add_entities(new_entities)
Beispiel #13
0
    async def async_set_operation_mode(self, operation_mode: str) -> None:
        """Set new operation mode for a DHW controller.

        Except for Auto, the mode is only until the next SetPoint.
        """
        if operation_mode == STATE_AUTO:
            await self._evo_broker.call_client_api(
                self._evo_device.set_dhw_auto())
        else:
            await self._update_schedule()
            until = dt_util.parse_datetime(
                self.setpoints.get("next_sp_from", ""))
            until = dt_util.as_utc(until) if until else None

            if operation_mode == STATE_ON:
                await self._evo_broker.call_client_api(
                    self._evo_device.set_dhw_on(until=until))
            else:  # STATE_OFF
                await self._evo_broker.call_client_api(
                    self._evo_device.set_dhw_off(until=until))
Beispiel #14
0
def log_rate_limits(opp, device_name, resp, level=logging.INFO):
    """Output rate limit log line at given level."""
    if ATTR_PUSH_RATE_LIMITS not in resp:
        return

    rate_limits = resp[ATTR_PUSH_RATE_LIMITS]
    resetsAt = rate_limits[ATTR_PUSH_RATE_LIMITS_RESETS_AT]
    resetsAtTime = dt_util.parse_datetime(resetsAt) - dt_util.utcnow()
    rate_limit_msg = ("mobile_app push notification rate limits for %s: "
                      "%d sent, %d allowed, %d errors, "
                      "resets in %s")
    _LOGGER.log(
        level,
        rate_limit_msg,
        device_name,
        rate_limits[ATTR_PUSH_RATE_LIMITS_SUCCESSFUL],
        rate_limits[ATTR_PUSH_RATE_LIMITS_MAXIMUM],
        rate_limits[ATTR_PUSH_RATE_LIMITS_ERRORS],
        str(resetsAtTime).split(".")[0],
    )
Beispiel #15
0
    def update_from_latest_data(self):
        """Update the state."""
        data = self.openuv.data[DATA_UV].get("result")

        if not data:
            self._available = False
            return

        self._available = True

        if self._sensor_type == TYPE_CURRENT_OZONE_LEVEL:
            self._state = data["ozone"]
        elif self._sensor_type == TYPE_CURRENT_UV_INDEX:
            self._state = data["uv"]
        elif self._sensor_type == TYPE_CURRENT_UV_LEVEL:
            if data["uv"] >= 11:
                self._state = UV_LEVEL_EXTREME
            elif data["uv"] >= 8:
                self._state = UV_LEVEL_VHIGH
            elif data["uv"] >= 6:
                self._state = UV_LEVEL_HIGH
            elif data["uv"] >= 3:
                self._state = UV_LEVEL_MODERATE
            else:
                self._state = UV_LEVEL_LOW
        elif self._sensor_type == TYPE_MAX_UV_INDEX:
            self._state = data["uv_max"]
            self._attrs.update({
                ATTR_MAX_UV_TIME:
                as_local(parse_datetime(data["uv_max_time"]))
            })
        elif self._sensor_type in (
                TYPE_SAFE_EXPOSURE_TIME_1,
                TYPE_SAFE_EXPOSURE_TIME_2,
                TYPE_SAFE_EXPOSURE_TIME_3,
                TYPE_SAFE_EXPOSURE_TIME_4,
                TYPE_SAFE_EXPOSURE_TIME_5,
                TYPE_SAFE_EXPOSURE_TIME_6,
        ):
            self._state = data["safe_exposure_time"][EXPOSURE_TYPE_MAP[
                self._sensor_type]]
Beispiel #16
0
    async def async_get_events(self, opp, start_date, end_date):
        """Get all tasks in a specific time frame."""
        if self._id is None:
            project_task_data = [
                task for task in self._api.state[TASKS]
                if not self._project_id_whitelist
                or task[PROJECT_ID] in self._project_id_whitelist
            ]
        else:
            project_data = await opp.async_add_executor_job(
                self._api.projects.get_data, self._id)
            project_task_data = project_data[TASKS]

        events = []
        for task in project_task_data:
            if task["due"] is None:
                continue
            due_date = _parse_due_date(
                task["due"], self._api.state["user"]["tz_info"]["gmt_string"])
            midnight = dt.as_utc(
                dt.parse_datetime(
                    due_date.strftime("%Y-%m-%d") + "T00:00:00" +
                    self._api.state["user"]["tz_info"]["gmt_string"]))

            if start_date < due_date < end_date:
                if due_date == midnight:
                    # If the due date has no time data, return just the date so that it
                    # will render correctly as an all day event on a calendar.
                    due_date_value = due_date.strftime("%Y-%m-%d")
                else:
                    due_date_value = due_date.isoformat()
                event = {
                    "uid": task["id"],
                    "title": task["content"],
                    "start": due_date_value,
                    "end": due_date_value,
                    "allDay": True,
                    "summary": task["content"],
                }
                events.append(event)
        return events
Beispiel #17
0
    async def async_added_to_opp(self) -> None:
        """Startup with initial state or previous state."""
        await super().async_added_to_opp()

        self._logger = logging.getLogger(
            f"{__name__}.{split_entity_id(self.entity_id)[1]}"
        )
        self.action_script.update_logger(self._logger)

        state = await self.async_get_last_state()
        if state:
            enable_automation = state.state == STATE_ON
            last_triggered = state.attributes.get("last_triggered")
            if last_triggered is not None:
                self.action_script.last_triggered = parse_datetime(last_triggered)
            self._logger.debug(
                "Loaded automation %s with state %s from state "
                " storage last state %s",
                self.entity_id,
                enable_automation,
                state,
            )
        else:
            enable_automation = DEFAULT_INITIAL_STATE
            self._logger.debug(
                "Automation %s not in state storage, state %s from default is used",
                self.entity_id,
                enable_automation,
            )

        if self._initial_state is not None:
            enable_automation = self._initial_state
            self._logger.debug(
                "Automation %s initial state %s overridden from "
                "config initial_state",
                self.entity_id,
                enable_automation,
            )

        if enable_automation:
            await self.async_enable()
Beispiel #18
0
async def test_unload_entry(opp):
    """Test that the options form."""

    now = dt_util.parse_datetime("2021-01-09 12:00:00+00:00")
    with patch("openpeerpower.util.dt.now", return_value=now), patch(
            "openpeerpower.util.dt.utcnow",
            return_value=now), requests_mock.mock() as _m:
        aemet_requests_mock(_m)

        config_entry = MockConfigEntry(domain=DOMAIN,
                                       unique_id="aemet_unique_id",
                                       data=CONFIG)
        config_entry.add_to_opp(opp)

        assert await opp.config_entries.async_setup(config_entry.entry_id)
        await opp.async_block_till_done()
        assert config_entry.state is ConfigEntryState.LOADED

        await opp.config_entries.async_unload(config_entry.entry_id)
        await opp.async_block_till_done()
        assert config_entry.state is ConfigEntryState.NOT_LOADED
 def _get_hourly_forecast_from_weather_response(self, weather_response,
                                                now):
     if weather_response.hourly:
         parse = False
         hour = now.hour
         forecast = []
         for day in weather_response.hourly[ATTR_DATA][0][
                 AEMET_ATTR_FORECAST][AEMET_ATTR_DAY]:
             day_date = dt_util.parse_datetime(day[AEMET_ATTR_DATE])
             hour_start = 0
             if now.date() == day_date.date():
                 parse = True
                 hour_start = now.hour
             if parse:
                 for hour in range(hour_start, 24):
                     cur_forecast = self._convert_forecast_hour(
                         day_date, day, hour)
                     if cur_forecast:
                         forecast.append(cur_forecast)
         return forecast
     return None
Beispiel #20
0
    async def async_set_preset_mode(self, preset_mode: str | None) -> None:
        """Set the preset mode; if None, then revert to following the schedule."""
        evo_preset_mode = HA_PRESET_TO_EVO.get(preset_mode, EVO_FOLLOW)

        if evo_preset_mode == EVO_FOLLOW:
            await self._evo_broker.call_client_api(
                self._evo_device.cancel_temp_override()
            )
            return

        temperature = self._evo_device.setpointStatus["targetHeatTemperature"]

        if evo_preset_mode == EVO_TEMPOVER:
            await self._update_schedule()
            until = dt_util.parse_datetime(self.setpoints.get("next_sp_from", ""))
        else:  # EVO_PERMOVER
            until = None

        until = dt_util.as_utc(until) if until else None
        await self._evo_broker.call_client_api(
            self._evo_device.set_temperature(temperature, until=until)
        )
Beispiel #21
0
async def _test_self_reset(opp, config, start_time, expect_reset=True):
    """Test energy sensor self reset."""
    assert await async_setup_component(opp, DOMAIN, config)
    assert await async_setup_component(opp, SENSOR_DOMAIN, config)
    await opp.async_block_till_done()

    opp.bus.async_fire(EVENT_OPENPEERPOWER_START)
    entity_id = config[DOMAIN]["energy_bill"]["source"]

    now = dt_util.parse_datetime(start_time)
    with alter_time(now):
        async_fire_time_changed(opp, now)
        opp.states.async_set(entity_id, 1, {"unit_of_measurement": "kWh"})
        await opp.async_block_till_done()

    now += timedelta(seconds=30)
    with alter_time(now):
        async_fire_time_changed(opp, now)
        opp.states.async_set(entity_id,
                             3, {"unit_of_measurement": "kWh"},
                             force_update=True)
        await opp.async_block_till_done()

    now += timedelta(seconds=30)
    with alter_time(now):
        async_fire_time_changed(opp, now)
        await opp.async_block_till_done()
        opp.states.async_set(entity_id,
                             6, {"unit_of_measurement": "kWh"},
                             force_update=True)
        await opp.async_block_till_done()

    state = opp.states.get("sensor.energy_bill")
    if expect_reset:
        assert state.attributes.get("last_period") == "2"
        assert state.state == "3"
    else:
        assert state.attributes.get("last_period") == 0
        assert state.state == "5"
Beispiel #22
0
 def update(self) -> None:
     """Read new state data from the library."""
     _LOGGER.debug("Updating %s", self._vehicle.name)
     vehicle_state = self._vehicle.state
     vehicle_last_trip = self._vehicle.state.last_trip
     if self._attribute == "charging_status":
         self._state = getattr(vehicle_state, self._attribute).value
     elif self.unit_of_measurement == VOLUME_GALLONS:
         value = getattr(vehicle_state, self._attribute)
         value_converted = self.opp.config.units.volume(value, VOLUME_LITERS)
         self._state = round(value_converted)
     elif self.unit_of_measurement == LENGTH_MILES:
         value = getattr(vehicle_state, self._attribute)
         value_converted = self.opp.config.units.length(value, LENGTH_KILOMETERS)
         self._state = round(value_converted)
     elif self._service is None:
         self._state = getattr(vehicle_state, self._attribute)
     elif self._service == SERVICE_LAST_TRIP:
         if self._attribute == "date_utc":
             date_str = getattr(vehicle_last_trip, "date")
             self._state = dt_util.parse_datetime(date_str).isoformat()
         else:
             self._state = getattr(vehicle_last_trip, self._attribute)
Beispiel #23
0
    def handle_new_task(call):
        """Call when a user creates a new Todoist Task from Open Peer Power."""
        project_name = call.data[PROJECT_NAME]
        project_id = project_id_lookup[project_name]

        # Create the task
        item = api.items.add(call.data[CONTENT], project_id=project_id)

        if LABELS in call.data:
            task_labels = call.data[LABELS]
            label_ids = [
                label_id_lookup[label.lower()] for label in task_labels
            ]
            item.update(labels=label_ids)

        if PRIORITY in call.data:
            item.update(priority=call.data[PRIORITY])

        _due: dict = {}
        if DUE_DATE_STRING in call.data:
            _due["string"] = call.data[DUE_DATE_STRING]

        if DUE_DATE_LANG in call.data:
            _due["lang"] = call.data[DUE_DATE_LANG]

        if DUE_DATE in call.data:
            due_date = dt.parse_datetime(call.data[DUE_DATE])
            if due_date is None:
                due = dt.parse_date(call.data[DUE_DATE])
                due_date = datetime(due.year, due.month, due.day)
            # Format it in the manner Todoist expects
            due_date = dt.as_utc(due_date)
            date_format = "%Y-%m-%dT%H:%M%S"
            due_date = datetime.strftime(due_date, date_format)
            _due["date"] = due_date

        if _due:
            item.update(due=_due)

        _reminder_due: dict = {}
        if REMINDER_DATE_STRING in call.data:
            _reminder_due["string"] = call.data[REMINDER_DATE_STRING]

        if REMINDER_DATE_LANG in call.data:
            _reminder_due["lang"] = call.data[REMINDER_DATE_LANG]

        if REMINDER_DATE in call.data:
            due_date = dt.parse_datetime(call.data[REMINDER_DATE])
            if due_date is None:
                due = dt.parse_date(call.data[REMINDER_DATE])
                due_date = datetime(due.year, due.month, due.day)
            # Format it in the manner Todoist expects
            due_date = dt.as_utc(due_date)
            date_format = "%Y-%m-%dT%H:%M:%S"
            due_date = datetime.strftime(due_date, date_format)
            _reminder_due["date"] = due_date

        if _reminder_due:
            api.reminders.add(item["id"], due=_reminder_due)

        # Commit changes
        api.commit()
        _LOGGER.debug("Created Todoist task: %s", call.data[CONTENT])
Beispiel #24
0
async def test_setting_rising(opp, legacy_patchable_time):
    """Test retrieving sun setting and rising."""
    utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
    with patch("openpeerpower.helpers.condition.dt_util.utcnow", return_value=utc_now):
        await async_setup_component(
            opp, sun.DOMAIN, {sun.DOMAIN: {sun.CONF_ELEVATION: 0}}
        )

    await opp.async_block_till_done()
    state = opp.states.get(sun.ENTITY_ID)

    from astral import LocationInfo
    import astral.sun

    utc_today = utc_now.date()

    location = LocationInfo(
        latitude=opp.config.latitude, longitude=opp.config.longitude
    )

    mod = -1
    while True:
        next_dawn = astral.sun.dawn(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_dawn > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_dusk = astral.sun.dusk(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_dusk > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_midnight = astral.sun.midnight(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_midnight > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_noon = astral.sun.noon(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_noon > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_rising = astral.sun.sunrise(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_rising > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_setting = astral.sun.sunset(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_setting > utc_now:
            break
        mod += 1

    assert next_dawn == dt_util.parse_datetime(
        state.attributes[sun.STATE_ATTR_NEXT_DAWN]
    )
    assert next_dusk == dt_util.parse_datetime(
        state.attributes[sun.STATE_ATTR_NEXT_DUSK]
    )
    assert next_midnight == dt_util.parse_datetime(
        state.attributes[sun.STATE_ATTR_NEXT_MIDNIGHT]
    )
    assert next_noon == dt_util.parse_datetime(
        state.attributes[sun.STATE_ATTR_NEXT_NOON]
    )
    assert next_rising == dt_util.parse_datetime(
        state.attributes[sun.STATE_ATTR_NEXT_RISING]
    )
    assert next_setting == dt_util.parse_datetime(
        state.attributes[sun.STATE_ATTR_NEXT_SETTING]
    )
Beispiel #25
0
 def last_update(self):
     """Return the last_update time for the device."""
     last_update = parse_datetime(self.device.last_update)
     return last_update
Beispiel #26
0
    async def _build_media_items(self, title, category):
        """Fetch requested gameclip/screenshot media."""
        title_id, _, thumbnail = title.split("#", 2)
        owner, kind = category.split("#", 1)

        items: list[XboxMediaItem] = []
        with suppress(ValidationError):  # Unexpected API response
            if kind == "gameclips":
                if owner == "my":
                    response: GameclipsResponse = (
                        await self.client.gameclips.get_recent_clips_by_xuid(
                            self.client.xuid, title_id
                        )
                    )
                elif owner == "community":
                    response: GameclipsResponse = await self.client.gameclips.get_recent_community_clips_by_title_id(
                        title_id
                    )
                else:
                    return None
                items = [
                    XboxMediaItem(
                        item.user_caption
                        or dt_util.as_local(
                            dt_util.parse_datetime(item.date_recorded)
                        ).strftime("%b. %d, %Y %I:%M %p"),
                        item.thumbnails[0].uri,
                        item.game_clip_uris[0].uri,
                        MEDIA_CLASS_VIDEO,
                    )
                    for item in response.game_clips
                ]
            elif kind == "screenshots":
                if owner == "my":
                    response: ScreenshotResponse = (
                        await self.client.screenshots.get_recent_screenshots_by_xuid(
                            self.client.xuid, title_id
                        )
                    )
                elif owner == "community":
                    response: ScreenshotResponse = await self.client.screenshots.get_recent_community_screenshots_by_title_id(
                        title_id
                    )
                else:
                    return None
                items = [
                    XboxMediaItem(
                        item.user_caption
                        or dt_util.as_local(item.date_taken).strftime(
                            "%b. %d, %Y %I:%M%p"
                        ),
                        item.thumbnails[0].uri,
                        item.screenshot_uris[0].uri,
                        MEDIA_CLASS_IMAGE,
                    )
                    for item in response.screenshots
                ]

        return BrowseMediaSource(
            domain=DOMAIN,
            identifier=f"{title}~~{category}",
            media_class=MEDIA_CLASS_DIRECTORY,
            media_content_type="",
            title=f"{owner.title()} {kind.title()}",
            can_play=False,
            can_expand=True,
            children=[_build_media_item(title, category, item) for item in items],
            children_media_class=MEDIA_CLASS_MAP[kind],
            thumbnail=thumbnail,
        )
Beispiel #27
0
def is_valid_datetime(string: str) -> bool:
    """Test if string dt is a valid datetime."""
    try:
        return dt_util.parse_datetime(string) is not None
    except ValueError:
        return False
Beispiel #28
0
    async def updating_devices(self, *_):
        """Find the current data from self.data."""
        if not self.data:
            return

        now = dt_util.utcnow()
        forecast_time = now + dt_util.dt.timedelta(hours=self._forecast)

        # Find the correct time entry. Since not all time entries contain all
        # types of data, we cannot just select one. Instead, we order  them by
        # distance from the desired forecast_time, and for every device iterate
        # them in order of increasing distance, taking the first time_point
        # that contains the desired data.

        ordered_entries = []

        for time_entry in self.data["product"]["time"]:
            valid_from = dt_util.parse_datetime(time_entry["@from"])
            valid_to = dt_util.parse_datetime(time_entry["@to"])

            if now >= valid_to:
                # Has already passed. Never select this.
                continue

            average_dist = abs(
                (valid_to - forecast_time).total_seconds()) + abs(
                    (valid_from - forecast_time).total_seconds())

            ordered_entries.append((average_dist, time_entry))

        ordered_entries.sort(key=lambda item: item[0])

        # Update all devices
        tasks = []
        if ordered_entries:
            for dev in self.devices:
                new_state = None

                for (_, selected_time_entry) in ordered_entries:
                    loc_data = selected_time_entry["location"]

                    if dev.type not in loc_data:
                        continue

                    if dev.type == "precipitation":
                        new_state = loc_data[dev.type]["@value"]
                    elif dev.type == "symbol":
                        new_state = loc_data[dev.type]["@number"]
                    elif dev.type in (
                            "temperature",
                            "pressure",
                            "humidity",
                            "dewpointTemperature",
                    ):
                        new_state = loc_data[dev.type]["@value"]
                    elif dev.type in ("windSpeed", "windGust"):
                        new_state = loc_data[dev.type]["@mps"]
                    elif dev.type == "windDirection":
                        new_state = float(loc_data[dev.type]["@deg"])
                    elif dev.type in (
                            "fog",
                            "cloudiness",
                            "lowClouds",
                            "mediumClouds",
                            "highClouds",
                    ):
                        new_state = loc_data[dev.type]["@percent"]

                    break

                # pylint: disable=protected-access
                if new_state != dev._state:
                    dev._state = new_state
                    tasks.append(dev.async_update_op_state())

        if tasks:
            await asyncio.wait(tasks)
Beispiel #29
0
    async def async_added_to_opp(self):
        """Handle entity which will be added."""
        await super().async_added_to_opp()

        if self._period == QUARTER_HOURLY:
            for quarter in range(4):
                async_track_time_change(
                    self.opp,
                    self._async_reset_meter,
                    minute=(quarter * 15) + self._period_offset.seconds %
                    (15 * 60) // 60,
                    second=self._period_offset.seconds % 60,
                )
        elif self._period == HOURLY:
            async_track_time_change(
                self.opp,
                self._async_reset_meter,
                minute=self._period_offset.seconds // 60,
                second=self._period_offset.seconds % 60,
            )
        elif self._period in [
                DAILY, WEEKLY, MONTHLY, BIMONTHLY, QUARTERLY, YEARLY
        ]:
            async_track_time_change(
                self.opp,
                self._async_reset_meter,
                hour=self._period_offset.seconds // 3600,
                minute=self._period_offset.seconds % 3600 // 60,
                second=self._period_offset.seconds % 3600 % 60,
            )

        async_dispatcher_connect(self.opp, SIGNAL_RESET_METER,
                                 self.async_reset_meter)

        state = await self.async_get_last_state()
        if state:
            self._state = Decimal(state.state)
            self._unit_of_measurement = state.attributes.get(
                ATTR_UNIT_OF_MEASUREMENT)
            self._last_period = state.attributes.get(ATTR_LAST_PERIOD)
            self._last_reset = dt_util.as_utc(
                dt_util.parse_datetime(state.attributes.get(ATTR_LAST_RESET)))
            if state.attributes.get(ATTR_STATUS) == COLLECTING:
                # Fake cancellation function to init the meter in similar state
                self._collecting = lambda: None

        @callback
        def async_source_tracking(event):
            """Wait for source to be ready, then start meter."""
            if self._tariff_entity is not None:
                _LOGGER.debug("<%s> tracks utility meter %s", self.name,
                              self._tariff_entity)
                async_track_state_change_event(self.opp, [self._tariff_entity],
                                               self.async_tariff_change)

                tariff_entity_state = self.opp.states.get(self._tariff_entity)
                self._change_status(tariff_entity_state.state)
                return

            _LOGGER.debug("<%s> collecting from %s", self.name,
                          self._sensor_source_id)
            self._collecting = async_track_state_change_event(
                self.opp, [self._sensor_source_id], self.async_reading)

        self.opp.bus.async_listen_once(EVENT_OPENPEERPOWER_START,
                                       async_source_tracking)
Beispiel #30
0
    async def get(self, request, datetime=None):
        """Return history over a period of time."""
        timer_start = time.perf_counter()
        if datetime:
            datetime = dt_util.parse_datetime(datetime)

            if datetime is None:
                return self.json_message("Invalid datetime", HTTP_BAD_REQUEST)

        now = dt_util.utcnow()

        one_day = timedelta(days=1)
        if datetime:
            start_time = dt_util.as_utc(datetime)
        else:
            start_time = now - one_day

        if start_time > now:
            return self.json([])

        end_time = request.query.get("end_time")
        if end_time:
            end_time = dt_util.parse_datetime(end_time)
            if end_time:
                end_time = dt_util.as_utc(end_time)
            else:
                return self.json_message("Invalid end_time", HTTP_BAD_REQUEST)
        else:
            end_time = start_time + one_day
        entity_ids = request.query.get("filter_entity_id")
        if entity_ids:
            entity_ids = entity_ids.lower().split(",")
        include_start_time_state = "skip_initial_state" not in request.query

        opp = request.app["opp"]

        result = await opp.async_add_job(
            get_significant_states,
            opp,
            start_time,
            end_time,
            entity_ids,
            self.filters,
            include_start_time_state,
        )
        result = list(result.values())
        if _LOGGER.isEnabledFor(logging.DEBUG):
            elapsed = time.perf_counter() - timer_start
            _LOGGER.debug("Extracted %d states in %fs", sum(map(len, result)),
                          elapsed)

        # Optionally reorder the result to respect the ordering given
        # by any entities explicitly included in the configuration.
        if self.use_include_order:
            sorted_result = []
            for order_entity in self.filters.included_entities:
                for state_list in result:
                    if state_list[0].entity_id == order_entity:
                        sorted_result.append(state_list)
                        result.remove(state_list)
                        break
            sorted_result.extend(result)
            result = sorted_result

        return await opp.async_add_job(self.json, result)