This has been driving me crazy, so I figured I’d start here
I have written a few, very simple custom components that work great. One of those is for this fan light I have, which talked to a raspberry pi which used some RF transmitter to turn the light on and off. That works great to this day
I was re-writing the component to be more generic for another device that will be controllable via the raspberry pi (called it a PiBridge). This time, i used async io, where as my previous component wasn’t doing async.
The issue I’m running into is that while my component works (light turns on and off as I flip the state in lovelace) the lights state, once it goes to ‘on’/True, stays ‘on’/True in the front end. I’ve scoured some examples but I can’t figure it out. Some example register callbacks, some don’t, and they all seem to work. I know my Light object’s state is correct (based on Logger prints) but for whatever reason HA thinks the state is always ‘on’
I’ve mucked with the code so much to figure it out, so excuse the ugliness. It’s not that complicated, which is what is driving me crazy.
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Setup a Light Entity controlled by the PiBridge"""
_LOGGER.info("Setting up light entry")
bridge: PiController = hass.data[DOMAIN][config_entry.entry_id]
lightDevices = await bridge.async_get_devices("light")
_LOGGER.info("Devices found in setup_entry: {}".format(lightDevices))
for dev in lightDevices:
_LOGGER.info("{}: {}".format( dev.get("devId", None), dev.get("state", False)))
newLights = [PiLight(hass, bridge, dev.get("devId", None), dev.get("state", False)) for dev in lightDevices]
#component = EntityComponent(_LOGGER, DOMAIN, hass)
#component.async_register_entity_service(SERVICE_SYNC, {}, "async_do_sync")
platform = entity_platform.async_get_current_platform()
platform.async_register_entity_service(
SERVICE_SYNC,
{
},
"async_do_sync",
)
async_add_entities(newLights, update_before_add=True)
return True
class PiLight(LightEntity):
def __init__(self, hass, bridge, devid, state) -> None:
_LOGGER.info("adding light: {} {}".format(devid, state))
self.bridge: PiController = bridge
self.hass = hass
self._state = state
self._unique_id = devid
self.devid = devid
#self._attr_brightness = 0
@property
def is_on(self):
_LOGGER.info(f"SOMEONE ASKED OUR STATE {self._state}")
return self._state
@property
def supported_features(self):
return 0
@property
def unique_id(self):
return self._unique_id
@property
def should_poll(self):
return False
@property
def available(self) -> bool:
"""Return True if entity is available."""
return True
# async def async_update(self) -> None:
# #resp,state = await self.bridge.async_send_get("state", data_dict={"devId": self.devid})
# #_LOGGER.info(f"Update called: {resp}, {state}")
# #if not resp:
# # _LOGGER.error(f"Failed to get light state {resp}")
# # return
# #_LOGGER.info(f"Current state: {self._state}, light state on other side: {state}")
# #self._attr_is_on = state
# #self._state = state
# #self._attr_brightness = 0
# if self.entity_id is None:
# _LOGGER.info("Entity ID was none, skipping update")
# return
# self.async_schedule_update_ha_state()
async def async_turn_on(self, **kwargs):
_LOGGER.info(f"Turning light on. Current State {self._state} id is {self.entity_id}")
_LOGGER.info(f"Light on args: {kwargs}")
if not self._state:
_LOGGER.info(dir(self.bridge))
resp, temp = await self.bridge.async_send_get("flip", data_dict={"devId": self.devid})
_LOGGER.info(f"Got back {resp}, {temp}")
self._state = temp
self.async_write_ha_state()
async def async_turn_off(self, **kwargs):
_LOGGER.info(f"TURN OFF id is {self.entity_id}")
_LOGGER.info("Turning light off. Current State {} {}".format(self._state, self.devid))
if self._state:
_LOGGER.info(dir(self.bridge))
_, resp = await self.bridge.async_send_get("flip", data_dict={"devId": self.devid})
_LOGGER.info(f"Turn off sent, got back {resp}")
self._state = resp
#if not self._state:
#self._attr_brightness = 0
self.async_write_ha_state()
async def async_do_sync(self):
#Someone told us we were off
await self.bridge.sync(self.devid)
#await self.async_update()
#self.async_write_ha_state()
EDIT: made should_poll return False, I had tried True without luck