1 """Amber Electric Sensor definitions."""
7 from __future__
import annotations
11 from amberelectric.models.channel
import ChannelType
12 from amberelectric.models.current_interval
import CurrentInterval
13 from amberelectric.models.forecast_interval
import ForecastInterval
17 SensorEntityDescription,
25 from .
import AmberConfigEntry
26 from .const
import ATTRIBUTION
27 from .coordinator
import AmberUpdateCoordinator, normalize_descriptor
29 UNIT = f
"{CURRENCY_DOLLAR}/{UnitOfEnergy.KILO_WATT_HOUR}"
33 """Return a formatted conversion from cents to dollars."""
34 return round(cents / 100, 2)
38 """Return a human readable version of the channel type."""
39 if channel_type ==
"controlled_load":
40 return "Controlled Load"
41 if channel_type ==
"feed_in":
47 """Amber Base Sensor."""
49 _attr_attribution = ATTRIBUTION
53 coordinator: AmberUpdateCoordinator,
54 description: SensorEntityDescription,
57 """Initialize the Sensor."""
64 f
"{self.site_id}-{self.entity_description.key}-{self.channel_type}"
69 """Amber Price Sensor."""
73 """Return the current price in $/kWh."""
76 if interval.channel_type == ChannelType.FEEDIN:
82 """Return additional pieces of information about the price."""
85 data: dict[str, Any] = {}
89 data[
"duration"] = interval.duration
90 data[
"date"] = interval.var_date.isoformat()
92 if interval.channel_type == ChannelType.FEEDIN:
93 data[
"per_kwh"] = data[
"per_kwh"] * -1
94 data[
"nem_date"] = interval.nem_time.isoformat()
96 data[
"start_time"] = interval.start_time.isoformat()
97 data[
"end_time"] = interval.end_time.isoformat()
98 data[
"renewables"] = round(interval.renewables)
99 data[
"estimate"] = interval.estimate
100 data[
"spike_status"] = interval.spike_status.value
101 data[
"channel_type"] = interval.channel_type.value
103 if interval.range
is not None:
111 """Amber Forecast Sensor."""
115 """Return the first forecast price in $/kWh."""
121 interval = intervals[0]
123 if interval.channel_type == ChannelType.FEEDIN:
129 """Return additional pieces of information about the price."""
139 "channel_type": intervals[0].channel_type.value,
142 for interval
in intervals:
144 datum[
"duration"] = interval.duration
145 datum[
"date"] = interval.var_date.isoformat()
146 datum[
"nem_date"] = interval.nem_time.isoformat()
148 if interval.channel_type == ChannelType.FEEDIN:
149 datum[
"per_kwh"] = datum[
"per_kwh"] * -1
151 datum[
"start_time"] = interval.start_time.isoformat()
152 datum[
"end_time"] = interval.end_time.isoformat()
153 datum[
"renewables"] = round(interval.renewables)
154 datum[
"spike_status"] = interval.spike_status.value
157 if interval.range
is not None:
161 data[
"forecasts"].append(datum)
167 """Amber Price Descriptor Sensor."""
171 """Return the current price descriptor."""
176 """Sensor to show single grid specific values."""
178 _attr_attribution = ATTRIBUTION
182 coordinator: AmberUpdateCoordinator,
183 description: SensorEntityDescription,
185 """Initialize the Sensor."""
193 """Return the value of the sensor."""
199 entry: AmberConfigEntry,
200 async_add_entities: AddEntitiesCallback,
202 """Set up a config entry."""
203 coordinator = entry.runtime_data
205 current: dict[str, CurrentInterval] = coordinator.data[
"current"]
206 forecasts: dict[str, list[ForecastInterval]] = coordinator.data[
"forecasts"]
208 entities: list[SensorEntity] = []
209 for channel_type
in current:
212 name=f
"{entry.title} - {friendly_channel_type(channel_type)} Price",
213 native_unit_of_measurement=UNIT,
214 state_class=SensorStateClass.MEASUREMENT,
215 translation_key=channel_type,
219 for channel_type
in current:
223 f
"{entry.title} - {friendly_channel_type(channel_type)} Price"
226 translation_key=channel_type,
232 for channel_type
in forecasts:
235 name=f
"{entry.title} - {friendly_channel_type(channel_type)} Forecast",
236 native_unit_of_measurement=UNIT,
237 state_class=SensorStateClass.MEASUREMENT,
238 translation_key=channel_type,
244 name=f
"{entry.title} - Renewables",
245 native_unit_of_measurement=PERCENTAGE,
246 state_class=SensorStateClass.MEASUREMENT,
247 translation_key=
"renewables",
float|None native_value(self)
dict[str, Any]|None extra_state_attributes(self)
str|None native_value(self)
None __init__(self, AmberUpdateCoordinator coordinator, SensorEntityDescription description)
str|None native_value(self)
dict[str, Any]|None extra_state_attributes(self)
float|None native_value(self)
None __init__(self, AmberUpdateCoordinator coordinator, SensorEntityDescription description, str channel_type)
str|None normalize_descriptor(PriceDescriptor|None descriptor)
float format_cents_to_dollars(float cents)
None async_setup_entry(HomeAssistant hass, AmberConfigEntry entry, AddEntitiesCallback async_add_entities)
str friendly_channel_type(str channel_type)
web.Response get(self, web.Request request, str config_key)