I needed a integration with my water supply company in France as they have the data available through REST APIs. I’ve reversed engineered what they have on their website and create a small library for it.
I then embarqued into creating my own custom integration to:
have it configurable (i.e asking for credentials on setup)
create sensors called sensor.agur_water_index_<contract_id> which contains the consumption index of my water usage.
Now, I have followed the getting started guide, the cookiecutter template and various different threads on this forum to end up with something that I can install and configure. It can fetch the data and the sensors are created as expected.
However, the integration page doesn’t display the sensors, like any other integration would and I’m not understanding why. I’ve check the sun and other simple integrations but I cannot find what I’m doing wrong. The code is available on github here: GitHub - tbouron/ha-agur: Home Assistant integration for Agur https://ael.agur.fr
Screenshot of the sensor to show it is created and populated as expected (apologies, I can only send one picture per post since I’m new here, hence the reply)
After more digging, looks like I need a device to associated the sensor with. I have found another thread about the same issue although the author didn’t post the exact solution
Anyway, trying to work this out on my own, I have tried to set the device_info on my sensor using both _attr_device_info and overriding the device_info. Based on the docs, this should auto-magically create the device and link the sensor to it but the device is not created
After even more digging, I have found the magic incantation! The only thing required to attach the sensor to the integration (or domain rather) was to set self._attr_unique_id = unique_id where unique_id = config_entry.entry_id like so
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback):
"""Add Agur sensors from a config_entry."""
coordinator = hass.data[DOMAIN][config_entry.entry_id]
entities = []
for contract_id in coordinator.contract_ids:
_LOGGER.debug(f"Add sensor for Agur contract {contract_id}")
entities.append(WaterSensor(coordinator=coordinator, contract_id=contract_id, unique_id=config_entry.entry_id))
async_add_entities(entities, True)
class WaterSensor(CoordinatorEntity[AgurDataUpdateCoordinator], SensorEntity):
"""Agur water Sensor class."""
_attr_name = "Water index"
_attr_icon = "mdi:water"
_attr_state_class = SensorStateClass.TOTAL_INCREASING
_attr_device_class = SensorDeviceClass.WATER
_attr_native_unit_of_measurement = UnitOfVolume.LITERS
def __init__(self, coordinator: AgurDataUpdateCoordinator, unique_id: str, contract_id: str) -> None:
"""Pass coordinator to CoordinatorEntity."""
super().__init__(coordinator=coordinator)
self.entity_id = f"{SENSOR_PLATFORM}.{DOMAIN}_water_index_{contract_id}"
self._attr_unique_id = unique_id
self._contract_id = contract_id
self._attr_extra_state_attributes = {
"contract_id": contract_id
}
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, contract_id)},
manufacturer=DEFAULT_NAME,
name=DEFAULT_NAME
)
@property
def native_value(self) -> float:
"""Return the state of the sensor."""
return self.coordinator.data[self._contract_id]
Setting to another value doesn’t work BTW. I have absolutely no idea why it needs specifically to be set to config_entry.entry_id though so if you happen to know why, I’m interested