1 """Support for local power state reporting of entities by emulating TP-Link Kasa smart plugs."""
5 from sense_energy
import PlugInstance, SenseLink
6 import voluptuous
as vol
13 EVENT_HOMEASSISTANT_STARTED,
14 EVENT_HOMEASSISTANT_STOP,
23 from .const
import CONF_POWER, CONF_POWER_ENTITY, DOMAIN
25 _LOGGER = logging.getLogger(__name__)
27 CONFIG_ENTITY_SCHEMA = vol.Schema(
29 vol.Optional(CONF_NAME): cv.string,
30 vol.Optional(CONF_POWER): vol.Any(
34 vol.Optional(CONF_POWER_ENTITY): cv.string,
38 CONFIG_SCHEMA = vol.Schema(
42 vol.Required(CONF_ENTITIES): vol.Schema(
43 {cv.entity_id: CONFIG_ENTITY_SCHEMA}
48 extra=vol.ALLOW_EXTRA,
52 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
53 """Set up the emulated_kasa component."""
54 if not (conf := config.get(DOMAIN)):
56 entity_configs = conf[CONF_ENTITIES]
59 """Devices to be emulated."""
62 server = SenseLink(devices)
64 async
def stop_emulated_kasa(event):
67 async
def start_emulated_kasa(event):
71 except OSError
as error:
72 _LOGGER.error(
"Failed to create UDP server at port 9999: %s", error)
74 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_emulated_kasa)
76 hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, start_emulated_kasa)
82 """Validate that entities exist and ensure templates are ready to use."""
83 entity_registry = er.async_get(hass)
84 for entity_id, entity_config
in entity_configs.items():
85 if (state := hass.states.get(entity_id))
is None:
86 _LOGGER.debug(
"Entity not found: %s", entity_id)
89 if entity := entity_registry.async_get(entity_id):
92 entity_config[CONF_UNIQUE_ID] = entity_id
94 if CONF_POWER
in entity_config:
95 power_val = entity_config[CONF_POWER]
97 entity_config[CONF_POWER] =
Template(power_val, hass)
98 elif CONF_POWER_ENTITY
in entity_config:
99 power_val = entity_config[CONF_POWER_ENTITY]
100 if hass.states.get(power_val)
is None:
101 _LOGGER.debug(
"Sensor Entity not found: %s", power_val)
103 entity_config[CONF_POWER] = power_val
104 elif state.domain == SENSOR_DOMAIN:
107 _LOGGER.debug(
"No power value defined for: %s", entity_id)
111 """Determine the system wide unique_id for an entity."""
112 return f
"{entity.platform}.{entity.domain}.{entity.unique_id}"
116 """Produce list of plug devices from config entities."""
117 for entity_id, entity_config
in entity_configs.items():
118 if (state := hass.states.get(entity_id))
is None:
120 name = entity_config.get(CONF_NAME, state.name)
122 if state.state == STATE_ON
or state.domain == SENSOR_DOMAIN:
123 if CONF_POWER
in entity_config:
124 power_val = entity_config[CONF_POWER]
125 if isinstance(power_val, (float, int)):
126 power =
float(power_val)
127 elif isinstance(power_val, str):
128 power =
float(hass.states.get(power_val).state)
129 elif isinstance(power_val, Template):
130 power =
float(power_val.async_render())
131 elif state.domain == SENSOR_DOMAIN:
132 power =
float(state.state)
135 last_changed = state.last_changed.timestamp()
137 entity_config[CONF_UNIQUE_ID],
138 start_time=last_changed,
bool async_setup(HomeAssistant hass, ConfigType config)
def get_plug_devices(hass, entity_configs)
def get_system_unique_id(er.RegistryEntry entity)
def validate_configs(hass, entity_configs)
dict[str, dict[str, Any]] devices(HomeAssistant hass)
bool is_template_string(str maybe_template)