33import logging
44
55# Third party libraries
6+ from homeassistant .components .energy .sensor import (
7+ SOURCE_ADAPTERS ,
8+ SourceAdapter ,
9+ )
610from homeassistant .components .select import DOMAIN as SELECT_DOMAIN
711from homeassistant .components .sensor import DOMAIN as SENSOR_DOMAIN
812from homeassistant .components .utility_meter import (
2428import voluptuous as vol
2529
2630from .const import (
31+ CONF_ADAPTER ,
2732 CONF_CONF ,
2833 CONF_PRICE ,
2934 CONF_PRICE_ENTITY ,
35+ CONF_SOURCE_TYPE ,
3036 CONF_UTILITY_METER ,
3137 DATA_ENERGY_METER ,
3238 DOMAIN ,
3642_LOGGER = logging .getLogger (__name__ )
3743
3844
45+ SOURCE_TYPE_TO_SOURCE_ADAPTER = {
46+ "from_grid" : ("grid" , "flow_from" ),
47+ "to_grid" : ("grid" , "flow_to" ),
48+ "gas" : ("gas" , None ),
49+ "water" : ("water" , None ),
50+ }
51+
52+
3953# update the default schema w/ new options
4054ENERGY_METER_CONFIG_SCHEMA = vol .Schema (
4155 vol .All (
4458 vol .Optional (CONF_PRICE ): cv .positive_float ,
4559 vol .Optional (CONF_PRICE_ENTITY ): cv .entity_id ,
4660 vol .Optional (CONF_UTILITY_METER ): cv .boolean ,
61+ vol .Optional (CONF_SOURCE_TYPE ): vol .Any (
62+ * SOURCE_TYPE_TO_SOURCE_ADAPTER .keys (),
63+ ),
4764 },
4865 ),
4966 * METER_CONFIG_SCHEMA .schema .validators [1 :],
@@ -92,11 +109,21 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
92109 # - for fixed price, cost sensor is bound to the meter id
93110 # - for entity price, cost sensor is bound to the entity
94111 # price id
95- cache_key = conf_to_cost_sensor_id (meter , conf )
112+ sensor_id = conf_to_cost_sensor_id (meter , conf )
113+ if (adapter := get_energy_cost_sensor_adapter (conf )) is None :
114+ # stop here as we cannot create a cost sensor
115+ continue
116+ cache_key = (sensor_id , adapter .entity_id_suffix )
96117 if cache_key in hass .data [DATA_ENERGY_METER ]:
97118 cost_entity = hass .data [DATA_ENERGY_METER ][cache_key ]
98119 else :
99- cost_entity = await setup_energy_cost_sensor (hass , config , meter , conf )
120+ cost_entity = await setup_energy_cost_sensor (
121+ hass ,
122+ config ,
123+ meter ,
124+ conf ,
125+ adapter ,
126+ )
100127 hass .data [DATA_ENERGY_METER ][cache_key ] = cost_entity
101128
102129 if create_utility_meter :
@@ -108,17 +135,19 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
108135 name = um_conf .get (CONF_NAME )
109136 if not name :
110137 name = meter .replace ("_" , " " )
111- um_conf [CONF_NAME ] = f"{ name } Cost "
138+ um_conf [CONF_NAME ] = f"{ name } { adapter . name_suffix } "
112139
113140 # Prevent the reuse of the same unique_id as the
114141 # utility_meter sensors
115142 if um_conf .get (CONF_UNIQUE_ID ):
116- um_conf [CONF_UNIQUE_ID ] = f"{ um_conf [CONF_UNIQUE_ID ]} _cost"
143+ um_conf [
144+ CONF_UNIQUE_ID
145+ ] = f"{ um_conf [CONF_UNIQUE_ID ]} _{ adapter .entity_id_suffix } "
117146
118147 await setup_utility_meter_sensors (
119148 hass ,
120149 config ,
121- f"{ meter } _cost " ,
150+ f"{ meter } _ { adapter . entity_id_suffix } " ,
122151 um_conf ,
123152 select_entity ,
124153 )
@@ -217,6 +246,7 @@ async def setup_energy_cost_sensor(
217246 config : ConfigType ,
218247 meter : str ,
219248 meter_conf : dict ,
249+ adapter : SourceAdapter ,
220250):
221251 """Create a cost sensor to follow an energy sensor."""
222252 _LOGGER .debug (
@@ -229,8 +259,43 @@ async def setup_energy_cost_sensor(
229259 hass ,
230260 SENSOR_DOMAIN ,
231261 DOMAIN ,
232- {CONF_METER : meter , CONF_CONF : meter_conf },
262+ {CONF_METER : meter , CONF_CONF : meter_conf , CONF_ADAPTER : adapter },
233263 config ,
234264 ),
235265 )
236- return f"sensor.{ '_' .join (conf_to_cost_sensor_id (meter , meter_conf ))} _cost"
266+ # return the entity id
267+ return (
268+ f"sensor."
269+ f"{ '_' .join (conf_to_cost_sensor_id (meter , meter_conf ))} "
270+ f"_{ adapter .entity_id_suffix } "
271+ )
272+
273+
274+ def get_energy_cost_sensor_adapter (conf : dict ):
275+ """Resolve the SourceAdapter from config."""
276+ # resolve source adapter from source_type
277+ source_type = conf .get (CONF_SOURCE_TYPE , "from_grid" )
278+ _LOGGER .debug ("Setup %s: setup energy cost sensor of type %s" , DOMAIN , source_type )
279+
280+ if source_type not in SOURCE_TYPE_TO_SOURCE_ADAPTER :
281+ # should never happen if config validation is correctly set
282+ _LOGGER .error (
283+ "Setup %s: Unknown source type configured: %s" ,
284+ DOMAIN ,
285+ source_type ,
286+ )
287+ return None
288+
289+ source_adapter = SOURCE_TYPE_TO_SOURCE_ADAPTER [source_type ]
290+
291+ for adapter in SOURCE_ADAPTERS :
292+ # find the right
293+ if (adapter .source_type , adapter .flow_type ) == source_adapter :
294+ return adapter
295+ # should not happened unless builtin adapter changes
296+ _LOGGER .error (
297+ "Setup %s: Failed to find an appropriate source adapter for type %s" ,
298+ DOMAIN ,
299+ source_type ,
300+ )
301+ return None
0 commit comments