Skip to content

Commit

Permalink
Merge pull request #11 from sushantsaxena/fix-multiple-door-state-issue
Browse files Browse the repository at this point in the history
Move initialization to constructor to solve multiple doors sharing same state and listeners
  • Loading branch information
corporategoth authored Jan 1, 2024
2 parents 745ab7f + fa67d6f commit 9dc130e
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 72 deletions.
5 changes: 3 additions & 2 deletions custom_components/powerpetdoor/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@

class PetDoorButton(ButtonEntity):
_attr_should_poll = False
last_state = None
power = True

def __init__(self,
client: PowerPetDoorClient,
name: str,
device: DeviceInfo | None = None) -> None:
self.client = client

self.last_state = None
self.power = True

self._attr_name = name
self._attr_device_info = device
self._attr_unique_id = f"{client.host}:{client.port}-button"
Expand Down
106 changes: 53 additions & 53 deletions custom_components/powerpetdoor/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,59 +125,6 @@ def make_bool(v: str | int | bool):
return v

class PowerPetDoorClient:
msgId = 1
replyMsgId = None

door_status_listeners: dict[str, Callable[[str], None]] = {}
settings_listeners: dict[str, Callable[[dict], None]] = {}
sensor_listeners: dict[str, dict[str, Callable[[bool], None]]] = {
FIELD_POWER: {},
FIELD_INSIDE: {},
FIELD_OUTSIDE: {},
FIELD_AUTO: {},
FIELD_OUTSIDE_SENSOR_SAFETY_LOCK: {},
FIELD_CMD_LOCKOUT: {},
FIELD_AUTORETRACT: {},
}
notifications_listeners: dict[str, dict[str, Callable[[bool], None]]] = {
FIELD_SENSOR_ON_INDOOR_NOTIFICATIONS: {},
FIELD_SENSOR_OFF_INDOOR_NOTIFICATIONS: {},
FIELD_SENSOR_ON_OUTDOOR_NOTIFICATIONS: {},
FIELD_SENSOR_OFF_OUTDOOR_NOTIFICATIONS: {},
FIELD_LOW_BATTERY_NOTIFICATIONS: {},
}
stats_listeners: dict[str, dict[str, Callable[[int], None]]] = {
FIELD_TOTAL_OPEN_CYCLES: {},
FIELD_TOTAL_AUTO_RETRACTS: {},
}
hw_info_listeners: dict[str, Callable[[dict], None]] = {}
battery_listeners: dict[str, Callable[[dict], None]] = {}

timezone_listeners: dict[str, Callable[[str], None]] = {}
hold_time_listeners: dict[str, Callable[[int], None]] = {}
sensor_trigger_voltage_listeners: dict[str, Callable[[int], None]] = {}
sleep_sensor_trigger_voltage_listeners: dict[str, Callable[[int], None]] = {}

on_connect: dict[str, Callable[[], Awaitable[None]]] = {}
on_disconnect: dict[str, Callable[[], Awaitable[None]]] = {}
on_ping: dict[str, Callable[[int], None]] = {}

_shutdown = False
_ownLoop = False
_eventLoop = None
_transport = None
_keepalive = None
_check_receipt = None
_last_ping = None
_last_command = None
_can_dequeue = False
_last_send = 0
_failed_msg = 0
_failed_pings = 0
_buffer = ''
_outstanding = {}
_queue = queue.SimpleQueue()

def __init__(self, host: str, port: int, keepalive: float, timeout: float,
reconnect: float, loop: EventLoop | None = None) -> None:
self.cfg_host = host
Expand All @@ -194,6 +141,59 @@ def __init__(self, host: str, port: int, keepalive: float, timeout: float,
self._ownLoop = True
self._eventLoop = asyncio.new_event_loop()

self.msgId = 1
self.replyMsgId = None

self.door_status_listeners: dict[str, Callable[[str], None]] = {}
self.settings_listeners: dict[str, Callable[[dict], None]] = {}
self.sensor_listeners: dict[str, dict[str, Callable[[bool], None]]] = {
FIELD_POWER: {},
FIELD_INSIDE: {},
FIELD_OUTSIDE: {},
FIELD_AUTO: {},
FIELD_OUTSIDE_SENSOR_SAFETY_LOCK: {},
FIELD_CMD_LOCKOUT: {},
FIELD_AUTORETRACT: {},
}
self.notifications_listeners: dict[str, dict[str, Callable[[bool], None]]] = {
FIELD_SENSOR_ON_INDOOR_NOTIFICATIONS: {},
FIELD_SENSOR_OFF_INDOOR_NOTIFICATIONS: {},
FIELD_SENSOR_ON_OUTDOOR_NOTIFICATIONS: {},
FIELD_SENSOR_OFF_OUTDOOR_NOTIFICATIONS: {},
FIELD_LOW_BATTERY_NOTIFICATIONS: {},
}
self.stats_listeners: dict[str, dict[str, Callable[[int], None]]] = {
FIELD_TOTAL_OPEN_CYCLES: {},
FIELD_TOTAL_AUTO_RETRACTS: {},
}
self.hw_info_listeners: dict[str, Callable[[dict], None]] = {}
self.battery_listeners: dict[str, Callable[[dict], None]] = {}

self.timezone_listeners: dict[str, Callable[[str], None]] = {}
self.hold_time_listeners: dict[str, Callable[[int], None]] = {}
self.sensor_trigger_voltage_listeners: dict[str, Callable[[int], None]] = {}
self.sleep_sensor_trigger_voltage_listeners: dict[str, Callable[[int], None]] = {}

self.on_connect: dict[str, Callable[[], Awaitable[None]]] = {}
self.on_disconnect: dict[str, Callable[[], Awaitable[None]]] = {}
self.on_ping: dict[str, Callable[[int], None]] = {}

self._shutdown = False
self._ownLoop = False
self._eventLoop = None
self._transport = None
self._keepalive = None
self._check_receipt = None
self._last_ping = None
self._last_command = None
self._can_dequeue = False
self._last_send = 0
self._failed_msg = 0
self._failed_pings = 0
self._buffer = ''
self._outstanding = {}
self._queue = queue.SimpleQueue()

# Theses functions wrap asyncio but ensure the loop is correct!
def ensure_future(self, *args: Any, **kwargs: Any):
return asyncio.ensure_future(*args, loop=self._eventLoop, **kwargs)
Expand Down
6 changes: 3 additions & 3 deletions custom_components/powerpetdoor/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,6 @@ class PetDoor(CoordinatorEntity, CoverEntity):
_attr_supported_features = (SUPPORT_CLOSE | SUPPORT_OPEN)
_attr_position = None

last_change = None
power = True

def __init__(self,
hass: HomeAssistant,
client: PowerPetDoorClient,
Expand All @@ -62,6 +59,9 @@ def __init__(self,
super().__init__(coordinator)
self.client = client

self.last_change = None
self.power = True

self._attr_name = name
self._attr_device_info = device
self._attr_unique_id = f"{client.host}:{client.port}-door"
Expand Down
6 changes: 3 additions & 3 deletions custom_components/powerpetdoor/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,6 @@
}

class PetDoorNumber(CoordinatorEntity, NumberEntity):
last_change = None
power = True

def __init__(self,
client: PowerPetDoorClient,
name: str,
Expand All @@ -98,6 +95,9 @@ def __init__(self,
self.client = client
self.number = number

self.last_change = None
self.power = True

self.multiplier = number.get("multiplier", 1.0)

self._attr_name = name
Expand Down
6 changes: 3 additions & 3 deletions custom_components/powerpetdoor/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,6 @@ def collapse_split_field(xsched: dict) -> list:


class PetDoorSchedule(CoordinatorEntity, Schedule):
last_change = None
power = True

def __init__(self,
client: PowerPetDoorClient,
name: str,
Expand All @@ -232,6 +229,9 @@ def __init__(self,
self.client = client
self.schedule = schedule

self.last_change = None
self.power = True

if "category" in schedule:
self._attr_entity_category = schedule["category"]
if "disabled" in schedule:
Expand Down
9 changes: 5 additions & 4 deletions custom_components/powerpetdoor/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ class PetDoorBattery(CoordinatorEntity, SensorEntity):
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = PERCENTAGE

last_change = None
def __init__(self,
hass: HomeAssistant,
client: PowerPetDoorClient,
Expand All @@ -186,6 +185,8 @@ def __init__(self,

self.client = client

self.last_change = None

self._attr_name = name
self._attr_device_info = device
self._attr_unique_id = f"{client.host}:{client.port}-battery"
Expand Down Expand Up @@ -299,9 +300,6 @@ def ac_present(self) -> bool:
return self.coordinator.data.get(FIELD_AC_PRESENT) if self.coordinator.data else None

class PetDoorStats(CoordinatorEntity, SensorEntity):
last_change = None
power = True

def __init__(self,
client: PowerPetDoorClient,
name: str,
Expand All @@ -312,6 +310,9 @@ def __init__(self,
self.client = client
self.sensor = sensor

self.last_change = None
self.power = True

self._attr_name = name
self._attr_entity_category = sensor.get("category")
self._attr_state_class = sensor.get("class")
Expand Down
10 changes: 6 additions & 4 deletions custom_components/powerpetdoor/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,6 @@

class PetDoorSwitch(CoordinatorEntity, ToggleEntity):
_attr_device_class = SwitchDeviceClass.SWITCH
last_change = None
power = True

def __init__(self,
client: PowerPetDoorClient,
Expand All @@ -177,6 +175,9 @@ def __init__(self,
self.client = client
self.switch = switch

self.last_change = None
self.power = True

self._attr_name = name
self._attr_entity_category = switch.get("category")
self._attr_entity_registry_enabled_default = not switch.get("disabled", False)
Expand Down Expand Up @@ -250,8 +251,6 @@ async def async_turn_off(self) -> None:
class PetDoorNotificationSwitch(CoordinatorEntity, ToggleEntity):
_attr_device_class = SwitchDeviceClass.SWITCH
_attr_entity_category = EntityCategory.CONFIG
last_change = None
power = True

def __init__(self,
client: PowerPetDoorClient,
Expand All @@ -263,6 +262,9 @@ def __init__(self,
self.client = client
self.switch = switch

self.last_change = None
self.power = True

self._attr_name = name
if "disabled" in switch:
self._attr_entity_registry_enabled_default = not switch["disabled"]
Expand Down

0 comments on commit 9dc130e

Please sign in to comment.