async def test_states(opp): """Test states of sensors.""" now = dt_util.utc_from_timestamp(1495068856) device = time_date.TimeDateSensor(opp, "time") device._update_internal_state(now) assert device.state == "00:54" device = time_date.TimeDateSensor(opp, "date") device._update_internal_state(now) assert device.state == "2017-05-18" device = time_date.TimeDateSensor(opp, "time_utc") device._update_internal_state(now) assert device.state == "00:54" device = time_date.TimeDateSensor(opp, "date_time") device._update_internal_state(now) assert device.state == "2017-05-18, 00:54" device = time_date.TimeDateSensor(opp, "date_time_utc") device._update_internal_state(now) assert device.state == "2017-05-18, 00:54" device = time_date.TimeDateSensor(opp, "beat") device._update_internal_state(now) assert device.state == "@079" device._update_internal_state(dt_util.utc_from_timestamp(1602952963.2)) assert device.state == "@738" device = time_date.TimeDateSensor(opp, "date_time_iso") device._update_internal_state(now) assert device.state == "2017-05-18T00:54:00"
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
def extra_state_attributes(self) -> dict[str, Any] | None: """Return the state attributes of the device.""" attr = {} if self.vera_device.has_battery: attr[ATTR_BATTERY_LEVEL] = self.vera_device.battery_level if self.vera_device.is_armable: armed = self.vera_device.is_armed attr[ATTR_ARMED] = "True" if armed else "False" if self.vera_device.is_trippable: last_tripped = self.vera_device.last_trip if last_tripped is not None: utc_time = utc_from_timestamp(int(last_tripped)) attr[ATTR_LAST_TRIP_TIME] = utc_time.isoformat() else: attr[ATTR_LAST_TRIP_TIME] = None tripped = self.vera_device.is_tripped attr[ATTR_TRIPPED] = "True" if tripped else "False" power = self.vera_device.power if power: attr[ATTR_CURRENT_POWER_W] = convert(power, float, 0.0) energy = self.vera_device.energy if energy: attr[ATTR_CURRENT_ENERGY_KWH] = convert(energy, float, 0.0) attr["Vera Device Id"] = self.vera_device.vera_device_id return attr
def timestamp_utc(value): """Filter to convert given timestamp to UTC date/time.""" try: return dt_util.utc_from_timestamp(value).strftime(DATE_STR_FORMAT) except (ValueError, TypeError): # If timestamp can't be converted return value
def update(self): """Update sensor with new departures times.""" # Note: using Multi because there is a bug with the single stop impl results = self._client.get_predictions_for_multi_stops( [{ "stop_tag": self.stop, "route_tag": self.route }], self.agency) self._log_debug("Predictions results: %s", results) if "Error" in results: self._log_debug("Could not get predictions: %s", results) if not results.get("predictions"): self._log_debug("No predictions available") self._state = None # Remove attributes that may now be outdated self._attributes.pop("upcoming", None) return results = results["predictions"] # Set detailed attributes self._attributes.update({ "agency": results.get("agencyTitle"), "route": results.get("routeTitle"), "stop": results.get("stopTitle"), }) # List all messages in the attributes messages = listify(results.get("message", [])) self._log_debug("Messages: %s", messages) self._attributes["message"] = " -- ".join( message.get("text", "") for message in messages) # List out all directions in the attributes directions = listify(results.get("direction", [])) self._attributes["direction"] = ", ".join( direction.get("title", "") for direction in directions) # Chain all predictions together predictions = list( chain(*(listify(direction.get("prediction", [])) for direction in directions))) # Short circuit if we don't have any actual bus predictions if not predictions: self._log_debug("No upcoming predictions available") self._state = None self._attributes["upcoming"] = "No upcoming predictions" return # Generate list of upcoming times self._attributes["upcoming"] = ", ".join( sorted(p["minutes"] for p in predictions)) latest_prediction = maybe_first(predictions) self._state = utc_from_timestamp( int(latest_prediction["epochTime"]) / 1000).isoformat()
def forecast(self) -> list[dict[str, Any]] | None: """Return the forecast array.""" if not self.coordinator.forecast: return None # remap keys from library to keys understood by the weather component forecast = [{ ATTR_FORECAST_TIME: utc_from_timestamp(item["EpochDate"]).isoformat(), ATTR_FORECAST_TEMP: item["TemperatureMax"]["Value"], ATTR_FORECAST_TEMP_LOW: item["TemperatureMin"]["Value"], ATTR_FORECAST_PRECIPITATION: self._calc_precipitation(item), ATTR_FORECAST_PRECIPITATION_PROBABILITY: round( mean([ item["PrecipitationProbabilityDay"], item["PrecipitationProbabilityNight"], ])), ATTR_FORECAST_WIND_SPEED: item["WindDay"]["Speed"]["Value"], ATTR_FORECAST_WIND_BEARING: item["WindDay"]["Direction"]["Degrees"], ATTR_FORECAST_CONDITION: [k for k, v in CONDITION_CLASSES.items() if item["IconDay"] in v][0], } for item in self.coordinator.data[ATTR_FORECAST]] return forecast
def state(self) -> datetime: """Return the uptime of the client.""" if self.client.uptime < 1000000000: return (dt_util.now() - timedelta(seconds=self.client.uptime)).isoformat() return dt_util.utc_from_timestamp(float( self.client.uptime)).isoformat()
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()
def __init__( self, poller, parameter, name, unit, icon, device_class, force_update, median, go_unavailable_timeout, ): """Initialize the sensor.""" self.poller = poller self.parameter = parameter self._unit = unit self._icon = icon self._name = name self._state = None self._device_class = device_class self.data = [] self._force_update = force_update self.go_unavailable_timeout = go_unavailable_timeout self.last_successful_update = dt_util.utc_from_timestamp(0) # Median is used to filter out outliers. median of 3 will filter # single outliers, while median of 5 will filter double outliers # Use median_count = 1 if no filtering is required. self.median_count = median
def extra_state_attributes(self) -> dict[str, Any]: """Return device specific state attributes.""" return { dt_util.utc_from_timestamp(call["datetime"]).isoformat(): call["name"] for call in self._call_list_for_type }
def get_time_until(departure_time=None): """Calculate the time between now and a train's departure time.""" if departure_time is None: return 0 delta = dt_util.utc_from_timestamp(int(departure_time)) - dt_util.now() return round(delta.total_seconds() / 60)
def _convert_forecast(self, entry): forecast = { ATTR_FORECAST_TIME: dt.utc_from_timestamp(entry.reference_time("unix")).isoformat(), ATTR_FORECAST_PRECIPITATION: self._calc_precipitation(entry.rain, entry.snow), ATTR_FORECAST_PRECIPITATION_PROBABILITY: (round(entry.precipitation_probability * 100)), ATTR_FORECAST_PRESSURE: entry.pressure.get("press"), ATTR_FORECAST_WIND_SPEED: entry.wind().get("speed"), ATTR_FORECAST_WIND_BEARING: entry.wind().get("deg"), ATTR_FORECAST_CONDITION: self._get_condition(entry.weather_code, entry.reference_time("unix")), ATTR_API_CLOUDS: entry.clouds, } temperature_dict = entry.temperature("celsius") if "max" in temperature_dict and "min" in temperature_dict: forecast[ATTR_FORECAST_TEMP] = entry.temperature("celsius").get( "max") forecast[ATTR_FORECAST_TEMP_LOW] = entry.temperature( "celsius").get("min") else: forecast[ATTR_FORECAST_TEMP] = entry.temperature("celsius").get( "temp") return forecast
def _get_oauth_token(self) -> OAuth2TokenResponse: tokens = {**self._oauth_session.token} issued = tokens["expires_at"] - tokens["expires_in"] del tokens["expires_at"] token_response = OAuth2TokenResponse.parse_obj(tokens) token_response.issued = utc_from_timestamp(issued) return token_response
async def test_states_non_default_timezone(opp): """Test states of sensors in a timezone other than UTC.""" new_tz = dt_util.get_time_zone("America/New_York") assert new_tz is not None dt_util.set_default_time_zone(new_tz) now = dt_util.utc_from_timestamp(1495068856) device = time_date.TimeDateSensor(opp, "time") device._update_internal_state(now) assert device.state == "20:54" device = time_date.TimeDateSensor(opp, "date") device._update_internal_state(now) assert device.state == "2017-05-17" device = time_date.TimeDateSensor(opp, "time_utc") device._update_internal_state(now) assert device.state == "00:54" device = time_date.TimeDateSensor(opp, "date_time") device._update_internal_state(now) assert device.state == "2017-05-17, 20:54" device = time_date.TimeDateSensor(opp, "date_time_utc") device._update_internal_state(now) assert device.state == "2017-05-18, 00:54" device = time_date.TimeDateSensor(opp, "beat") device._update_internal_state(now) assert device.state == "@079" device = time_date.TimeDateSensor(opp, "date_time_iso") device._update_internal_state(now) assert device.state == "2017-05-17T20:54:00"
def __init__(self, opp, config): """Initialize a proxy camera component.""" super().__init__() self.opp = opp self._proxied_camera = config.get(CONF_ENTITY_ID) self._name = ( config.get(CONF_NAME) or f"{DEFAULT_BASENAME} - {self._proxied_camera}" ) self._image_opts = ImageOpts( config.get(CONF_MAX_IMAGE_WIDTH), config.get(CONF_MAX_IMAGE_HEIGHT), config.get(CONF_IMAGE_LEFT), config.get(CONF_IMAGE_TOP), config.get(CONF_IMAGE_QUALITY), config.get(CONF_FORCE_RESIZE), ) self._stream_opts = ImageOpts( config.get(CONF_MAX_STREAM_WIDTH), config.get(CONF_MAX_STREAM_HEIGHT), config.get(CONF_IMAGE_LEFT), config.get(CONF_IMAGE_TOP), config.get(CONF_STREAM_QUALITY), True, ) self._image_refresh_rate = config.get(CONF_IMAGE_REFRESH_RATE) self._cache_images = bool( config.get(CONF_IMAGE_REFRESH_RATE) or config.get(CONF_CACHE_IMAGES) ) self._last_image_time = dt_util.utc_from_timestamp(0) self._last_image = None self._mode = config.get(CONF_MODE)
def forecast(self): """Return the forecast array.""" # Per conversation with Joshua Reyes of Dark Sky, to get the total # forecasted precipitation, you have to multiple the intensity by # the hours for the forecast interval def calc_precipitation(intensity, hours): amount = None if intensity is not None: amount = round((intensity * hours), 1) return amount if amount > 0 else None data = None if self._mode == "daily": data = [ { ATTR_FORECAST_TIME: utc_from_timestamp( entry.d.get("time") ).isoformat(), ATTR_FORECAST_TEMP: entry.d.get("temperatureHigh"), ATTR_FORECAST_TEMP_LOW: entry.d.get("temperatureLow"), ATTR_FORECAST_PRECIPITATION: calc_precipitation( entry.d.get("precipIntensity"), 24 ), ATTR_FORECAST_WIND_SPEED: entry.d.get("windSpeed"), ATTR_FORECAST_WIND_BEARING: entry.d.get("windBearing"), ATTR_FORECAST_CONDITION: MAP_CONDITION.get(entry.d.get("icon")), } for entry in self._ds_daily.data ] else: data = [ { ATTR_FORECAST_TIME: utc_from_timestamp( entry.d.get("time") ).isoformat(), ATTR_FORECAST_TEMP: entry.d.get("temperature"), ATTR_FORECAST_PRECIPITATION: calc_precipitation( entry.d.get("precipIntensity"), 1 ), ATTR_FORECAST_CONDITION: MAP_CONDITION.get(entry.d.get("icon")), } for entry in self._ds_hourly.data ] return data
def _get_last_online(self): """Convert last_online from the steam module into timestamp UTC.""" last_online = utc_from_timestamp(mktime(self._profile.last_online)) if last_online: return last_online return None
def __init__(self, point_client, device_id, device_class): """Initialize the entity.""" self._async_unsub_dispatcher_connect = None self._client = point_client self._id = device_id self._name = self.device.name self._device_class = device_class self._updated = utc_from_timestamp(0) self._value = None
def state(self): """Return the state.""" # search first cadran with rain next_rain = next( (cadran for cadran in self.coordinator.data.forecast if cadran["rain"] > 1), None, ) return (dt_util.utc_from_timestamp(next_rain["dt"]).isoformat() if next_rain else None)
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
def test_as_timestamp(): """Test as_timestamp method.""" ts = 1462401234 utc_dt = dt_util.utc_from_timestamp(ts) assert ts == dt_util.as_timestamp(utc_dt) utc_iso = utc_dt.isoformat() assert ts == dt_util.as_timestamp(utc_iso) # confirm the ability to handle a string passed in delta = dt_util.as_timestamp("2016-01-01 12:12:12") delta -= dt_util.as_timestamp("2016-01-01 12:12:11") assert delta == 1
def extra_state_attributes(self): """Return the state attributes.""" reference_dt = self.coordinator.data.forecast[0]["dt"] return { ATTR_NEXT_RAIN_DT_REF: dt_util.utc_from_timestamp(reference_dt).isoformat(), ATTR_NEXT_RAIN_1_HOUR_FORECAST: { f"{int((item['dt'] - reference_dt) / 60)} min": item["desc"] for item in self.coordinator.data.forecast }, ATTR_ATTRIBUTION: ATTRIBUTION, }
def _get_condition(self, weather_code, timestamp=None): """Get weather condition from weather data.""" if weather_code == WEATHER_CODE_SUNNY_OR_CLEAR_NIGHT: if timestamp: timestamp = dt.utc_from_timestamp(timestamp) if sun.is_up(self.opp, timestamp): return ATTR_CONDITION_SUNNY return ATTR_CONDITION_CLEAR_NIGHT return [k for k, v in CONDITION_CLASSES.items() if weather_code in v][0]
def __init__(self, client, controller): """Set up tracked client.""" super().__init__(client, controller) self.heartbeat_check = False self._is_connected = False self._controller_connection_state_changed = False if client.last_seen: self._is_connected = ( self.is_wired == client.is_wired and dt_util.utcnow() - dt_util.utc_from_timestamp(float(client.last_seen)) < controller.option_detection_time) self.schedule_update = self._is_connected
def update(self): """Get the latest data and updates the states.""" mydata = self.opp.data[DATA_HYDRAWISE].data _LOGGER.debug("Updating Hydrawise sensor: %s", self._name) relay_data = mydata.relays[self.data["relay"] - 1] if self._sensor_type == "watering_time": if relay_data["timestr"] == "Now": self._state = int(relay_data["run"] / 60) else: self._state = 0 else: # _sensor_type == 'next_cycle' next_cycle = min(relay_data["time"], TWO_YEAR_SECONDS) _LOGGER.debug("New cycle time: %s", next_cycle) self._state = dt.utc_from_timestamp( dt.as_timestamp(dt.now()) + next_cycle).isoformat()
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
async def test_timezone_intervals(opp): """Test date sensor behavior in a timezone besides UTC.""" new_tz = dt_util.get_time_zone("America/New_York") assert new_tz is not None dt_util.set_default_time_zone(new_tz) device = time_date.TimeDateSensor(opp, "date") now = dt_util.utc_from_timestamp(50000) with patch("openpeerpower.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() # start of local day in EST was 18000.0 # so the second day was 18000 + 86400 assert next_time.timestamp() == 104400 new_tz = dt_util.get_time_zone("America/Edmonton") assert new_tz is not None dt_util.set_default_time_zone(new_tz) now = dt_util.parse_datetime("2017-11-13 19:47:19-07:00") device = time_date.TimeDateSensor(opp, "date") with patch("openpeerpower.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp("2017-11-14 00:00:00-07:00") # Entering DST new_tz = dt_util.get_time_zone("Europe/Prague") assert new_tz is not None dt_util.set_default_time_zone(new_tz) now = dt_util.parse_datetime("2020-03-29 00:00+01:00") with patch("openpeerpower.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp("2020-03-30 00:00+02:00") now = dt_util.parse_datetime("2020-03-29 03:00+02:00") with patch("openpeerpower.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp("2020-03-30 00:00+02:00") # Leaving DST now = dt_util.parse_datetime("2020-10-25 00:00+02:00") with patch("openpeerpower.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp("2020-10-26 00:00:00+01:00") now = dt_util.parse_datetime("2020-10-25 23:59+01:00") with patch("openpeerpower.util.dt.utcnow", return_value=now): next_time = device.get_next_interval() assert next_time.timestamp() == dt_util.as_timestamp("2020-10-26 00:00:00+01:00")
async def async_update(self, *, tries=0): """Get the latest data from maps.yandex.ru and update the states.""" attrs = {} closer_time = None yandex_reply = await self.requester.get_stop_info(self._stop_id) try: data = yandex_reply["data"] except KeyError as key_error: _LOGGER.warning( "Exception KeyError was captured, missing key is %s. Yandex returned: %s", key_error, yandex_reply, ) if tries > 0: return await self.requester.set_new_session() await self.async_update(tries=tries + 1) return stop_name = data["name"] transport_list = data["transports"] for transport in transport_list: route = transport["name"] for thread in transport["threads"]: if self._routes and route not in self._routes: # skip unnecessary route info continue if "Events" not in thread["BriefSchedule"]: continue for event in thread["BriefSchedule"]["Events"]: if "Estimated" not in event: continue posix_time_next = int(event["Estimated"]["value"]) if closer_time is None or closer_time > posix_time_next: closer_time = posix_time_next if route not in attrs: attrs[route] = [] attrs[route].append(event["Estimated"]["text"]) attrs[STOP_NAME] = stop_name attrs[ATTR_ATTRIBUTION] = ATTRIBUTION if closer_time is None: self._state = None else: self._state = dt_util.utc_from_timestamp(closer_time).isoformat( timespec="seconds") self._attrs = attrs
def forecast(self): """Return the forecast.""" forecast_data = [] if self._mode == FORECAST_MODE_HOURLY: today = time.time() for forecast in self.coordinator.data.forecast: # Can have data in the past if forecast["dt"] < today: continue forecast_data.append({ ATTR_FORECAST_TIME: dt_util.utc_from_timestamp(forecast["dt"]).isoformat(), ATTR_FORECAST_CONDITION: format_condition(forecast["weather"]["desc"]), ATTR_FORECAST_TEMP: forecast["T"]["value"], ATTR_FORECAST_PRECIPITATION: forecast["rain"].get("1h"), ATTR_FORECAST_WIND_SPEED: forecast["wind"]["speed"], ATTR_FORECAST_WIND_BEARING: forecast["wind"]["direction"] if forecast["wind"]["direction"] != -1 else None, }) else: for forecast in self.coordinator.data.daily_forecast: # stop when we don't have a weather condition (can happen around last days of forcast, max 14) if not forecast.get("weather12H"): break forecast_data.append({ ATTR_FORECAST_TIME: self.coordinator.data.timestamp_to_locale_time( forecast["dt"]), ATTR_FORECAST_CONDITION: format_condition(forecast["weather12H"]["desc"]), ATTR_FORECAST_TEMP: forecast["T"]["max"], ATTR_FORECAST_TEMP_LOW: forecast["T"]["min"], ATTR_FORECAST_PRECIPITATION: forecast["precipitation"]["24h"], }) return forecast_data
async def get_cert_expiry_timestamp(opp, hostname, port): """Return the certificate's expiration timestamp.""" try: cert = await opp.async_add_executor_job(get_cert, hostname, port) except socket.gaierror as err: raise ResolveFailed(f"Cannot resolve hostname: {hostname}") from err except socket.timeout as err: raise ConnectionTimeout( f"Connection timeout with server: {hostname}:{port}") from err except ConnectionRefusedError as err: raise ConnectionRefused( f"Connection refused by server: {hostname}:{port}") from err except ssl.CertificateError as err: raise ValidationFailure(err.verify_message) from err except ssl.SSLError as err: raise ValidationFailure(err.args[0]) from err ts_seconds = ssl.cert_time_to_seconds(cert["notAfter"]) return dt.utc_from_timestamp(ts_seconds)