1 """Support for the NOAA Tides and Currents API."""
3 from __future__
import annotations
5 from datetime
import datetime, timedelta
7 from typing
import TYPE_CHECKING, Any, Literal, TypedDict
9 import noaa_coops
as coops
11 import voluptuous
as vol
14 PLATFORM_SCHEMA
as SENSOR_PLATFORM_SCHEMA,
26 from pandas
import Timestamp
28 _LOGGER = logging.getLogger(__name__)
30 CONF_STATION_ID =
"station_id"
32 DEFAULT_NAME =
"NOAA Tides"
33 DEFAULT_TIMEZONE =
"lst_ldt"
37 TIMEZONES = [
"gmt",
"lst",
"lst_ldt"]
38 UNIT_SYSTEMS = [
"english",
"metric"]
40 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
42 vol.Required(CONF_STATION_ID): cv.string,
43 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
44 vol.Optional(CONF_TIME_ZONE, default=DEFAULT_TIMEZONE): vol.In(TIMEZONES),
45 vol.Optional(CONF_UNIT_SYSTEM): vol.In(UNIT_SYSTEMS),
53 add_entities: AddEntitiesCallback,
54 discovery_info: DiscoveryInfoType |
None =
None,
56 """Set up the NOAA Tides and Currents sensor."""
57 station_id = config[CONF_STATION_ID]
58 name = config.get(CONF_NAME)
59 timezone = config.get(CONF_TIME_ZONE)
61 if CONF_UNIT_SYSTEM
in config:
62 unit_system = config[CONF_UNIT_SYSTEM]
63 elif hass.config.units
is METRIC_SYSTEM:
64 unit_system = UNIT_SYSTEMS[1]
66 unit_system = UNIT_SYSTEMS[0]
69 station = coops.Station(station_id, unit_system)
71 _LOGGER.error(
"NOAA Tides Sensor station_id %s does not exist", station_id)
73 except requests.exceptions.ConnectionError
as exception:
75 "Connection error during setup in NOAA Tides Sensor for station_id: %s",
78 raise PlatformNotReady
from exception
81 name, station_id, timezone, unit_system, station
88 """Representation of a single tide."""
90 time_stamp: list[Timestamp]
91 hi_lo: list[Literal[
"L",
"H"]]
92 predicted_wl: list[float]
96 """Representation of a NOAA Tides and Currents sensor."""
98 _attr_attribution =
"Data provided by NOAA"
100 def __init__(self, name, station_id, timezone, unit_system, station) -> None:
101 """Initialize the sensor."""
107 self.
datadata: NOAATidesData |
None =
None
111 """Return the name of the sensor."""
112 return self.
_name_name
116 """Return the state attributes of this device."""
117 attr: dict[str, Any] = {}
118 if self.
datadata
is None:
120 if self.
datadata[
"hi_lo"][1] ==
"H":
121 attr[
"high_tide_time"] = self.
datadata[
"time_stamp"][1].strftime(
124 attr[
"high_tide_height"] = self.
datadata[
"predicted_wl"][1]
125 attr[
"low_tide_time"] = self.
datadata[
"time_stamp"][2].strftime(
128 attr[
"low_tide_height"] = self.
datadata[
"predicted_wl"][2]
129 elif self.
datadata[
"hi_lo"][1] ==
"L":
130 attr[
"low_tide_time"] = self.
datadata[
"time_stamp"][1].strftime(
133 attr[
"low_tide_height"] = self.
datadata[
"predicted_wl"][1]
134 attr[
"high_tide_time"] = self.
datadata[
"time_stamp"][2].strftime(
137 attr[
"high_tide_height"] = self.
datadata[
"predicted_wl"][2]
142 """Return the state of the device."""
143 if self.
datadata
is None:
145 api_time = self.
datadata[
"time_stamp"][0]
146 if self.
datadata[
"hi_lo"][0] ==
"H":
147 tidetime = api_time.strftime(
"%-I:%M %p")
148 return f
"High tide at {tidetime}"
149 if self.
datadata[
"hi_lo"][0] ==
"L":
150 tidetime = api_time.strftime(
"%-I:%M %p")
151 return f
"Low tide at {tidetime}"
155 """Get the latest data from NOAA Tides and Currents API."""
156 begin = datetime.now()
160 df_predictions = self.
_station_station.get_data(
161 begin_date=begin.strftime(
"%Y%m%d %H:%M"),
162 end_date=end.strftime(
"%Y%m%d %H:%M"),
163 product=
"predictions",
169 api_data = df_predictions.head()
171 time_stamp=
list(api_data.index),
172 hi_lo=
list(api_data[
"hi_lo"].values),
173 predicted_wl=
list(api_data[
"predicted_wl"].values),
175 _LOGGER.debug(
"Data = %s", api_data)
177 "Recent Tide data queried with start time set to %s",
178 begin.strftime(
"%m-%d-%Y %H:%M"),
180 except ValueError
as err:
181 _LOGGER.error(
"Check NOAA Tides and Currents: %s", err.args)
dict[str, Any] extra_state_attributes(self)
None __init__(self, name, station_id, timezone, unit_system, station)
def add_entities(account, async_add_entities, tracked)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)