Skip to content

Commit

Permalink
Reworked ControllerInfo entity to use DataCoordinator
Browse files Browse the repository at this point in the history
  • Loading branch information
twystd committed Jan 17, 2024
1 parent 7cf024a commit c41690a
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 13 deletions.
13 changes: 13 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ KeyboardInterrupt
- [x] sort list by card number
- [x] show menu

- [ ] DataCoordinator
- [ ] async_write_ha_state
- https://developers.home-assistant.io/docs/integration_fetching_data/
- [x] ControllerInfo
- [ ] ControllerDateTime
- [ ] ControllerDoor
- [ ] ControllerDoorOpen
- [ ] ControllerDoorLock
- [ ] ControllerDoorButton
- [ ] CardInfo
- [ ] CardHolder
- [ ] etc.

- [ ] Controller
- [x] generate unique id in config-/option-flow
- [ ] Rework as Device
Expand Down
37 changes: 25 additions & 12 deletions custom_components/uhppoted/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import datetime
import logging

from homeassistant.core import callback
from homeassistant.components.sensor import SensorEntity
from homeassistant.components.datetime import DateTimeEntity
from homeassistant.helpers.update_coordinator import CoordinatorEntity

_LOGGER = logging.getLogger(__name__)

Expand All @@ -15,13 +17,13 @@
from .const import ATTR_FIRMWARE


class ControllerInfo(SensorEntity):
class ControllerInfo(CoordinatorEntity, SensorEntity):
_attr_icon = 'mdi:identifier'
_attr_has_entity_name: True
_attr_translation_key = 'controller_id'

def __init__(self, u, unique_id, controller, serial_no):
super().__init__()
def __init__(self, coordinator, u, unique_id, controller, serial_no):
super().__init__(coordinator)

_LOGGER.debug(f'controller {controller} {serial_no}')

Expand Down Expand Up @@ -62,18 +64,29 @@ def state(self) -> Optional[str]:
def extra_state_attributes(self) -> Dict[str, Any]:
return self._attributes

@callback
def _handle_coordinator_update(self) -> None:
# self._attr_is_on = self.coordinator.data[self.idx]["state"]
# self.async_write_ha_state()
pass

async def async_update(self):
_LOGGER.debug(f'controller:{self.controller} update info')
try:
response = self.uhppote.get_controller(self.serial_no)

if response.controller == self.serial_no:
self._state = response.controller
self._available = True
self._attributes[ATTR_ADDRESS] = f'{response.ip_address}'
self._attributes[ATTR_NETMASK] = f'{response.subnet_mask}'
self._attributes[ATTR_GATEWAY] = f'{response.gateway}'
self._attributes[ATTR_FIRMWARE] = f'{response.version} {response.date:%Y-%m-%d}'
try:
controllers = self.coordinator.controllers
serial_no = self.serial_no

if serial_no in controllers:
state = controllers[serial_no]
self._available = state['available']
self._state = serial_no
self._attributes[ATTR_ADDRESS] = state[ATTR_ADDRESS]
self._attributes[ATTR_NETMASK] = state[ATTR_NETMASK]
self._attributes[ATTR_GATEWAY] = state[ATTR_GATEWAY]
self._attributes[ATTR_FIRMWARE] = state[ATTR_FIRMWARE]
else:
self._available = False

except (Exception):
self._available = False
Expand Down
67 changes: 66 additions & 1 deletion custom_components/uhppoted/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import datetime
import logging
import async_timeout

from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
Expand All @@ -11,9 +12,14 @@
from homeassistant.components.sensor import SensorEntity
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.helpers.update_coordinator import UpdateFailed

from uhppoted import uhppote

_LOGGER = logging.getLogger(__name__)
_INTERVAL = datetime.timedelta(seconds=30)

# Configuration constants
from .const import DOMAIN
Expand Down Expand Up @@ -49,9 +55,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_e
u = configure_driver(options)
entities = []

coordinator = ControllerCoordinator(hass, u)

def f(unique_id, controller, serial_no, address):
entities.extend([
ControllerInfo(u['api'], unique_id, controller, serial_no),
ControllerInfo(coordinator, u['api'], unique_id, controller, serial_no),
])

def g(controller, serial_no, door, door_no):
Expand All @@ -71,4 +79,61 @@ def h(card, name, unique_id):
configure_controllers(options, f)
configure_doors(options, g)
configure_cards(options, h)

await coordinator.async_config_entry_first_refresh()

async_add_entities(entities, update_before_add=True)


class ControllerCoordinator(DataUpdateCoordinator):

def __init__(self, hass, u):
super().__init__(hass, _LOGGER, name="coordinator", update_interval=_INTERVAL)
self.uhppote = u
self._state = {
'controllers': {},
}

@property
def controllers(self):
return self._state['controllers']

async def _async_update_data(self):
try:
async with async_timeout.timeout(10):
return await self._get_controllers()
except Exception as err:
raise UpdateFailed(f"uhppoted API error {err}")

async def _get_controllers(self):
api = self.uhppote['api']
for controller in self.uhppote['controllers']:
_LOGGER.info(f'update controller {controller} info')

info = {
'available': False,
ATTR_ADDRESS: '',
ATTR_NETMASK: '',
ATTR_GATEWAY: '',
ATTR_FIRMWARE: '',
}

if controller in self._state['controllers']:
for attr in [ATTR_ADDRESS, ATTR_NETMASK, ATTR_GATEWAY, ATTR_FIRMWARE]:
if attr in self._state['controllers']:
info[attr] = self._state['controllers'][attr]

try:

response = self.uhppote['api'].get_controller(controller)
if response.controller == controller:
info['available'] = True
info[ATTR_ADDRESS] = f'{response.ip_address}'
info[ATTR_NETMASK] = f'{response.subnet_mask}'
info[ATTR_GATEWAY] = f'{response.gateway}'
info[ATTR_FIRMWARE] = f'{response.version} {response.date:%Y-%m-%d}'

except (Exception):
_LOGGER.exception(f'error retrieving controller {controller} information')

self._state['controllers'][controller] = info

0 comments on commit c41690a

Please sign in to comment.