Ejemplo n.º 1
0
    def update_from_latest_data(self):
        """Update the state."""
        data = self.openuv.data[DATA_PROTECTION_WINDOW]

        if not data:
            self._available = False
            return

        self._available = True

        for key in ("from_time", "to_time", "from_uv", "to_uv"):
            if not data.get(key):
                LOGGER.info("Skipping update due to missing data: %s", key)
                return

        if self._sensor_type == TYPE_PROTECTION_WINDOW:
            self._state = (parse_datetime(data["from_time"]) <= utcnow() <=
                           parse_datetime(data["to_time"]))
            self._attrs.update({
                ATTR_PROTECTION_WINDOW_ENDING_TIME:
                as_local(parse_datetime(data["to_time"])),
                ATTR_PROTECTION_WINDOW_ENDING_UV:
                data["to_uv"],
                ATTR_PROTECTION_WINDOW_STARTING_UV:
                data["from_uv"],
                ATTR_PROTECTION_WINDOW_STARTING_TIME:
                as_local(parse_datetime(data["from_time"])),
            })
Ejemplo n.º 2
0
    def _update_internal_state(self, time_date):
        time = dt_util.as_local(time_date).strftime(TIME_STR_FORMAT)
        time_utc = time_date.strftime(TIME_STR_FORMAT)
        date = dt_util.as_local(time_date).date().isoformat()
        date_utc = time_date.date().isoformat()

        if self.type == "time":
            self._state = time
        elif self.type == "date":
            self._state = date
        elif self.type == "date_time":
            self._state = f"{date}, {time}"
        elif self.type == "date_time_utc":
            self._state = f"{date_utc}, {time_utc}"
        elif self.type == "time_date":
            self._state = f"{time}, {date}"
        elif self.type == "time_utc":
            self._state = time_utc
        elif self.type == "beat":
            # Calculate Swatch Internet Time.
            time_bmt = time_date + timedelta(hours=1)
            delta = timedelta(
                hours=time_bmt.hour,
                minutes=time_bmt.minute,
                seconds=time_bmt.second,
                microseconds=time_bmt.microsecond,
            )

            # Use integers to better handle rounding. For example,
            # int(63763.2/86.4) = 737 but 637632//864 = 738.
            beat = int(delta.total_seconds() * 10) // 864

            self._state = f"@{beat:03d}"
        elif self.type == "date_time_iso":
            self._state = dt_util.parse_datetime(f"{date} {time}").isoformat()
Ejemplo n.º 3
0
    def _update_internal_state(self, time_date):
        time = dt_util.as_local(time_date).strftime(TIME_STR_FORMAT)
        time_utc = time_date.strftime(TIME_STR_FORMAT)
        date = dt_util.as_local(time_date).date().isoformat()
        date_utc = time_date.date().isoformat()

        # Calculate Swatch Internet Time.
        time_bmt = time_date + timedelta(hours=1)
        delta = timedelta(
            hours=time_bmt.hour,
            minutes=time_bmt.minute,
            seconds=time_bmt.second,
            microseconds=time_bmt.microsecond,
        )
        beat = int((delta.seconds + delta.microseconds / 1000000.0) / 86.4)

        if self.type == "time":
            self._state = time
        elif self.type == "date":
            self._state = date
        elif self.type == "date_time":
            self._state = f"{date}, {time}"
        elif self.type == "date_time_utc":
            self._state = f"{date_utc}, {time_utc}"
        elif self.type == "time_date":
            self._state = f"{time}, {date}"
        elif self.type == "time_utc":
            self._state = time_utc
        elif self.type == "beat":
            self._state = f"@{beat:03d}"
        elif self.type == "date_time_iso":
            self._state = dt_util.parse_datetime(f"{date} {time}").isoformat()
Ejemplo n.º 4
0
def sun(
    opp: OpenPeerPower,
    before: Optional[str] = None,
    after: Optional[str] = None,
    before_offset: Optional[timedelta] = None,
    after_offset: Optional[timedelta] = None,
) -> bool:
    """Test if current time matches sun requirements."""
    utcnow = dt_util.utcnow()
    today = dt_util.as_local(utcnow).date()
    before_offset = before_offset or timedelta(0)
    after_offset = after_offset or timedelta(0)

    sunrise_today = get_astral_event_date(opp, SUN_EVENT_SUNRISE, today)
    sunset_today = get_astral_event_date(opp, SUN_EVENT_SUNSET, today)

    sunrise = sunrise_today
    sunset = sunset_today
    if today > dt_util.as_local(cast(
            datetime, sunrise_today)).date() and SUN_EVENT_SUNRISE in (before,
                                                                       after):
        tomorrow = dt_util.as_local(utcnow + timedelta(days=1)).date()
        sunrise_tomorrow = get_astral_event_date(opp, SUN_EVENT_SUNRISE,
                                                 tomorrow)
        sunrise = sunrise_tomorrow

    if today > dt_util.as_local(cast(
            datetime, sunset_today)).date() and SUN_EVENT_SUNSET in (before,
                                                                     after):
        tomorrow = dt_util.as_local(utcnow + timedelta(days=1)).date()
        sunset_tomorrow = get_astral_event_date(opp, SUN_EVENT_SUNSET,
                                                tomorrow)
        sunset = sunset_tomorrow

    if sunrise is None and SUN_EVENT_SUNRISE in (before, after):
        # There is no sunrise today
        return False

    if sunset is None and SUN_EVENT_SUNSET in (before, after):
        # There is no sunset today
        return False

    if before == SUN_EVENT_SUNRISE and utcnow > cast(datetime,
                                                     sunrise) + before_offset:
        return False

    if before == SUN_EVENT_SUNSET and utcnow > cast(datetime,
                                                    sunset) + before_offset:
        return False

    if after == SUN_EVENT_SUNRISE and utcnow < cast(datetime,
                                                    sunrise) + after_offset:
        return False

    if after == SUN_EVENT_SUNSET and utcnow < cast(datetime,
                                                   sunset) + after_offset:
        return False

    return True
Ejemplo n.º 5
0
    def update_period(self):
        """Parse the templates and store a datetime tuple in _period."""
        start = None
        end = None

        # Parse start
        if self._start is not None:
            try:
                start_rendered = self._start.async_render()
            except (TemplateError, TypeError) as ex:
                HistoryStatsHelper.handle_template_exception(ex, "start")
                return
            if isinstance(start_rendered, str):
                start = dt_util.parse_datetime(start_rendered)
            if start is None:
                try:
                    start = dt_util.as_local(
                        dt_util.utc_from_timestamp(
                            math.floor(float(start_rendered))))
                except ValueError:
                    _LOGGER.error(
                        "Parsing error: start must be a datetime or a timestamp"
                    )
                    return

        # Parse end
        if self._end is not None:
            try:
                end_rendered = self._end.async_render()
            except (TemplateError, TypeError) as ex:
                HistoryStatsHelper.handle_template_exception(ex, "end")
                return
            if isinstance(end_rendered, str):
                end = dt_util.parse_datetime(end_rendered)
            if end is None:
                try:
                    end = dt_util.as_local(
                        dt_util.utc_from_timestamp(
                            math.floor(float(end_rendered))))
                except ValueError:
                    _LOGGER.error(
                        "Parsing error: end must be a datetime or a timestamp")
                    return

        # Calculate start or end using the duration
        if start is None:
            start = end - self._duration
        if end is None:
            end = start + self._duration

        if start > dt_util.now():
            # History hasn't been written yet for this period
            return
        if dt_util.now() < end:
            # No point in making stats of the future
            end = dt_util.now()

        self._period = start, end
Ejemplo n.º 6
0
    def step2_exchange(now):
        """Keep trying to validate the user_code until it expires."""
        if now >= dt.as_local(dev_flow.user_code_expiry):
            opp.components.persistent_notification.create(
                "Authentication code expired, please restart "
                "Open-Peer-Power and try again",
                title=NOTIFICATION_TITLE,
                notification_id=NOTIFICATION_ID,
            )
            listener()

        try:
            credentials = oauth.step2_exchange(device_flow_info=dev_flow)
        except FlowExchangeError:
            # not ready yet, call again
            return

        storage = Storage(opp.config.path(TOKEN_FILE))
        storage.put(credentials)
        do_setup(opp, opp_config, config)
        listener()
        opp.components.persistent_notification.create(
            (f"We are all setup now. Check {YAML_DEVICES} for calendars that have "
             f"been found"),
            title=NOTIFICATION_TITLE,
            notification_id=NOTIFICATION_ID,
        )
Ejemplo n.º 7
0
    def async_set_datetime(self,
                           date=None,
                           time=None,
                           datetime=None,
                           timestamp=None):
        """Set a new date / time."""
        if timestamp:
            datetime = dt_util.as_local(dt_util.utc_from_timestamp(timestamp))

        if datetime:
            date = datetime.date()
            time = datetime.time()

        if not self.has_date:
            date = None

        if not self.has_time:
            time = None

        if not date and not time:
            raise vol.Invalid("Nothing to set")

        if not date:
            date = self._current_datetime.date()

        if not time:
            time = self._current_datetime.time()

        self._current_datetime = py_datetime.datetime.combine(
            date, time, dt_util.DEFAULT_TIME_ZONE)
        self.async_write_op_state()
Ejemplo n.º 8
0
 def extra_state_attributes(self):
     """Return status of device."""
     attrs = self.device.device_status
     attrs["last_heard_from"] = as_local(self.last_update).strftime(
         "%Y-%m-%d %H:%M:%S"
     )
     return attrs
Ejemplo n.º 9
0
    def calculate_next(now: datetime) -> None:
        """Calculate and set the next time the trigger should fire."""
        nonlocal next_time

        localized_now = dt_util.as_local(now) if local else now
        next_time = dt_util.find_next_time_expression_time(
            localized_now, matching_seconds, matching_minutes, matching_hours)
Ejemplo n.º 10
0
def get_location_astral_event_next(
    location: "astral.Location",
    event: str,
    utc_point_in_time: Optional[datetime.datetime] = None,
    offset: Optional[datetime.timedelta] = None,
) -> datetime.datetime:
    """Calculate the next specified solar event."""
    from astral import AstralError

    if offset is None:
        offset = datetime.timedelta()

    if utc_point_in_time is None:
        utc_point_in_time = dt_util.utcnow()

    mod = -1
    while True:
        try:
            next_dt: datetime.datetime = (getattr(location, event)(
                dt_util.as_local(utc_point_in_time).date() +
                datetime.timedelta(days=mod),
                local=False,
            ) + offset)
            if next_dt > utc_point_in_time:
                return next_dt
        except AstralError:
            pass
        mod += 1
Ejemplo n.º 11
0
def get_date(date):
    """Get the dateTime from date or dateTime as a local."""
    if "date" in date:
        return dt.start_of_local_day(
            dt.dt.datetime.combine(dt.parse_date(date["date"]),
                                   dt.dt.time.min))
    return dt.as_local(dt.parse_datetime(date["dateTime"]))
Ejemplo n.º 12
0
def timestamp_local(value):
    """Filter to convert given timestamp to local date/time."""
    try:
        return dt_util.as_local(
            dt_util.utc_from_timestamp(value)).strftime(DATE_STR_FORMAT)
    except (ValueError, TypeError):
        # If timestamp can't be converted
        return value
Ejemplo n.º 13
0
 def to_datetime(obj):
     """Return a datetime."""
     if isinstance(obj, datetime):
         if obj.tzinfo is None:
             # floating value, not bound to any time zone in particular
             # represent same time regardless of which time zone is currently being observed
             return obj.replace(tzinfo=dt.DEFAULT_TIME_ZONE)
         return obj
     return dt.as_local(dt.dt.datetime.combine(obj, dt.dt.time.min))
Ejemplo n.º 14
0
def test_as_local_with_utc_object():
    """Test local time with UTC object."""
    dt_util.set_default_time_zone(dt_util.get_time_zone(TEST_TIME_ZONE))

    utcnow = dt_util.utcnow()
    localnow = dt_util.as_local(utcnow)

    assert localnow == utcnow
    assert localnow.tzinfo != utcnow.tzinfo
Ejemplo n.º 15
0
    def _purge_old(self):
        """Remove states which are older than self._max_age."""
        now = dt_util.utcnow()

        _LOGGER.debug(
            "%s: purging records older then %s(%s)",
            self.entity_id,
            dt_util.as_local(now - self._max_age),
            self._max_age,
        )

        while self.ages and (now - self.ages[0]) > self._max_age:
            _LOGGER.debug(
                "%s: purging record with datetime %s(%s)",
                self.entity_id,
                dt_util.as_local(self.ages[0]),
                (now - self.ages[0]),
            )
            self.ages.popleft()
            self.states.popleft()
Ejemplo n.º 16
0
def timestamp_custom(value, date_format=DATE_STR_FORMAT, local=True):
    """Filter to convert given timestamp to format."""
    try:
        date = dt_util.utc_from_timestamp(value)

        if local:
            date = dt_util.as_local(date)

        return date.strftime(date_format)
    except (ValueError, TypeError):
        # If timestamp can't be converted
        return value
Ejemplo n.º 17
0
    def pattern_time_change_listener(_: datetime) -> None:
        """Listen for matching time_changed events."""
        nonlocal time_listener

        now = time_tracker_utcnow()
        opp.async_run_opp_job(job, dt_util.as_local(now) if local else now)

        time_listener = async_track_point_in_utc_time(
            opp,
            pattern_time_change_listener,
            calculate_next(now + timedelta(seconds=1)),
        )
Ejemplo n.º 18
0
    def __repr__(self) -> str:
        """Return the representation of the states."""
        attrs = (
            "; {}".format(util.repr_helper(self.attributes)) if self.attributes else ""
        )

        return "<state {}={}{} @ {}>".format(
            self.entity_id,
            self.state,
            attrs,
            dt_util.as_local(self.last_changed).isoformat(),
        )
Ejemplo n.º 19
0
 def get_next_interval(self, now=None):
     """Compute next time an update should occur."""
     if now is None:
         now = dt_util.utcnow()
     if self.type == "date":
         now = dt_util.start_of_local_day(dt_util.as_local(now))
         return now + timedelta(seconds=86400)
     if self.type == "beat":
         interval = 86.4
     else:
         interval = 60
     timestamp = int(dt_util.as_timestamp(now))
     delta = interval - (timestamp % interval)
     return now + timedelta(seconds=delta)
Ejemplo n.º 20
0
    async def async_update(self):
        """Get the time and updates the state."""
        today = as_local(utcnow()).date()

        month = int(today.month)
        day = int(today.day)

        for sign in ZODIAC_BY_DATE:
            if (month == sign[0][1] and day >= sign[0][0]) or (
                month == sign[1][1] and day <= sign[1][0]
            ):
                self._state = sign[2]
                self._attrs = sign[3]
                break
Ejemplo n.º 21
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
Ejemplo n.º 22
0
    def pattern_time_change_listener(event: Event) -> None:
        """Listen for matching time_changed events."""
        nonlocal next_time, last_now

        now = event.data[ATTR_NOW]

        if last_now is None or now < last_now:
            # Time rolled back or next time not yet calculated
            calculate_next(now)

        last_now = now

        if next_time <= now:
            opp.async_run_job(action, dt_util.as_local(now) if local else now)
            calculate_next(now + timedelta(seconds=1))
Ejemplo n.º 23
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
Ejemplo n.º 24
0
def relative_time(value):
    """
    Take a datetime and return its "age" as a string.

    The age can be in second, minute, hour, day, month or year. Only the
    biggest unit is considered, e.g. if it's 2 days and 3 hours, "2 days" will
    be returned.
    Make sure date is not in the future, or else it will return None.

    If the input are not a datetime object the input will be returned unmodified.
    """
    if not isinstance(value, datetime):
        return value
    if not value.tzinfo:
        value = dt_util.as_local(value)
    if dt_util.now() < value:
        return value
    return dt_util.get_age(value)
Ejemplo n.º 25
0
    async def async_update(self):
        """Get the latest data and updates the state."""
        _LOGGER.debug("Pulling data from %s sensor", self._name)
        await self._camera.update()

        if self._sensor_type == "last_activity_time":
            last_activity = await self._camera.get_last_activity(force_refresh=True)
            if last_activity is not None:
                last_activity_time = as_local(last_activity.end_time_utc)
                self._state = (
                    f"{last_activity_time.hour:0>2}:{last_activity_time.minute:0>2}"
                )
        else:
            state = getattr(self._camera, self._sensor_type, None)
            if isinstance(state, bool):
                self._state = STATE_ON if state is True else STATE_OFF
            else:
                self._state = state
            self._state = state
Ejemplo n.º 26
0
    def extra_state_attributes(self):
        """Return the state attributes."""
        if self.type.startswith(PRECIPITATION_FORECAST):
            result = {ATTR_ATTRIBUTION: self._attribution}
            if self._timeframe is not None:
                result[TIMEFRAME_LABEL] = "%d min" % (self._timeframe)

            return result

        result = {
            ATTR_ATTRIBUTION: self._attribution,
            SENSOR_TYPES["stationname"][0]: self._stationname,
        }
        if self._measured is not None:
            # convert datetime (Europe/Amsterdam) into local datetime
            local_dt = dt_util.as_local(self._measured)
            result[MEASURED_LABEL] = local_dt.strftime("%c")

        return result
Ejemplo n.º 27
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]]
Ejemplo n.º 28
0
def get_astral_event_date(
    opp: OpenPeerPowerType,
    event: str,
    date: Union[datetime.date, datetime.datetime, None] = None,
) -> Optional[datetime.datetime]:
    """Calculate the astral event time for the specified date."""
    from astral import AstralError

    location = get_astral_location(opp)

    if date is None:
        date = dt_util.now().date()

    if isinstance(date, datetime.datetime):
        date = dt_util.as_local(date).date()

    try:
        return getattr(location, event)(date, local=False)  # type: ignore
    except AstralError:
        # Event never occurs for specified date.
        return None
Ejemplo n.º 29
0
    def get_next_interval(self):
        """Compute next time an update should occur."""
        now = dt_util.utcnow()

        if self.type == "date":
            tomorrow = dt_util.as_local(now) + timedelta(days=1)
            return dt_util.start_of_local_day(tomorrow)

        if self.type == "beat":
            # Add 1 hour because @0 beats is at 23:00:00 UTC.
            timestamp = dt_util.as_timestamp(now + timedelta(hours=1))
            interval = 86.4
        else:
            timestamp = dt_util.as_timestamp(now)
            interval = 60

        delta = interval - (timestamp % interval)
        next_interval = now + timedelta(seconds=delta)
        _LOGGER.debug("%s + %s -> %s (%s)", now, delta, next_interval, self.type)

        return next_interval
Ejemplo n.º 30
0
 def utc_converter(utc_now: datetime) -> None:
     """Convert passed in UTC now to local now."""
     opp.async_run_opp_job(job, dt_util.as_local(utc_now))