Skip to content

Commit

Permalink
v1.5.1b2
Browse files Browse the repository at this point in the history
  • Loading branch information
GravySeal committed Aug 24, 2024
1 parent 1d685f6 commit 542b964
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 12 deletions.
5 changes: 3 additions & 2 deletions bacnetinterface_dev/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<!-- https://developers.home-assistant.io/docs/add-ons/presentation#keeping-a-changelog -->

# 1.5.1b1
18/08/2024
# 1.5.1b2
24/08/2024

## Fixed
- Fixed monitoring of CoV subscriptions failing due to loss of connection. CoV tasks will now get removed after trying to resub without response when the CoV lifetime has passed.
- If address changed since last I Am request, it'll get updated internally now.

## Added
- Added resubscribing CoV to an object after the subscription had been timed out due to no response. [#52](https://github.com/Bepacom-Raalte/bepacom-HA-Addons/issues/52)
- `resub_on_iam` and `reread_on_iam` options under `devices_setup` in the add-on configuration. [#57](https://github.com/Bepacom-Raalte/bepacom-HA-Addons/issues/57)

## Dependencies
- ⬆️ Bumped base-python image to version v14.0.1.
Expand Down
3 changes: 3 additions & 0 deletions bacnetinterface_dev/DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ multiStateValue
- `quick_poll_list` This key contains a list containing each object identifier the add-on has to poll at the poll rate defined above. The list can be empty if no quick polling is desired.
- `slow_poll_rate` This key contains the rate at which quick poll objects have to be read. This is in seconds, between 30 and 3000.
- `slow_poll_list` This key contains a list containing each object identifier the add-on has to poll at the poll rate defined above. The list can be empty if no slow polling is desired. A special "all" key will make the add-on poll all objects of the device.
- `resub_on_iam` Resubscribe to an object with CoV when an I-Am request has been received. When the lifetime of the object has passed, enabling this key will result in the resubscription of a CoV subscription. Otherwise it'll just update any new information of the device.
- `reread_on_iam` Reread the object list when an I-Am request has been received. This key will result in all objects of this device to be read again.

The following properties will be read each poll:
- presentValue
Expand Down Expand Up @@ -272,6 +274,7 @@ The amount of segments that the device can accept at most for a single service r
Maximum size a BACnet message/segment is allowed to be.
A common BACnet/IP value and the default for the add-on is 1476, and a common BACnet/MSTP value is 480.


### Network port: `80/TCP`
Port which the integration should connect to. If you leave this empty, the integration should connect to port 8099.

Expand Down
6 changes: 3 additions & 3 deletions bacnetinterface_dev/config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# https://developers.home-assistant.io/docs/add-ons/configuration#add-on-config
name: Bepacom BACnet/IP Interface Development Version
version: "1.5.1b1"
version: "1.5.1b2"
slug: bacnetinterface_dev
description: Bepacom BACnet/IP interface for the Bepacom EcoPanel. Allows BACnet/IP devices to be available to Home Assistant through an API
url: "https://github.com/Bepacom-Raalte/bepacom-HA-Addons/tree/main/bacnetinterface"
Expand Down Expand Up @@ -63,8 +63,8 @@ schema:
slow_poll_rate: int(30,3000)?
slow_poll_list:
- str?
resub_on_iam: bool? #idk
reread_on_iam: bool? #idk
resub_on_iam: bool?
reread_on_iam: bool?
entity_list:
- str?
api_accessible: bool?
Expand Down
56 changes: 49 additions & 7 deletions bacnetinterface_dev/rootfs/usr/bin/BACnetIOHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,38 @@ def __init__(
self.update_event = update_event
self.vendor_info = get_vendor_info(0)
asyncio.get_event_loop().create_task(self.IAm_handler())
self.addon_device_config = addon_device_config
self.addon_device_config = (
addon_device_config if addon_device_config else list()
)
self.startup_complete.set()
LOGGER.debug("Application initialised")

def get_config_from_addon_config(self, device_identifier: ObjectIdentifier) -> dict:
specific_config = next(
(
config
for config in self.addon_device_config
if config.get("deviceID")
== f"{device_identifier[0]}:{device_identifier[1]}"
),
None,
)
if specific_config:
return specific_config

all_config = next(
(
config
for config in self.addon_device_config
if config.get("deviceID") == f"all"
),
None,
)
if all_config:
return all_config

return dict()

async def generate_specific_tasks(
self, device_identifier: ObjectIdentifier
) -> None:
Expand Down Expand Up @@ -522,30 +550,44 @@ async def do_IAmRequest(self, apdu) -> None:

if not in_cache:
await self.i_am_queue.put(apdu)
else:
return

config = self.get_config_from_addon_config(apdu.iAmDeviceIdentifier)

if config.get("resub_on_iam", True):
# Check if object list is still the same, otherwise read entire dict again
await self.handle_object_list_check(apdu)

if config.get("reread_on_iam", True):
# Check if CoV tasks are still active, otherwise resub.
await self.handle_cov_check(apdu.iAmDeviceIdentifier)

async def handle_object_list_check(self, apdu) -> None:

device_id = apdu.iAmDeviceIdentifier[1]

object_list = self.bacnet_device_dict[f"device:{apdu.iAmDeviceIdentifier[1]}"][
old_object_list = self.bacnet_device_dict[
f"device:{apdu.iAmDeviceIdentifier[1]}"
].get("objectList")
][f"device:{apdu.iAmDeviceIdentifier[1]}"].get("objectList")

if not await self.read_multiple_device_props(apdu=apdu):
LOGGER.warning(f"Failed to get: {device_id}, {device_id}")
if self.bacnet_device_dict.get(f"device:{device_id}"):
self.bacnet_device_dict.pop(f"device:{device_id}")

if object_list != self.bacnet_device_dict[
new_object_list = self.bacnet_device_dict[
f"device:{apdu.iAmDeviceIdentifier[1]}"
][f"device:{apdu.iAmDeviceIdentifier[1]}"].get("objectList"):
LOGGER.warning(f"Not implemented yet: object lists aren't equal!")
][f"device:{apdu.iAmDeviceIdentifier[1]}"].get("objectList")

if apdu.iAmDeviceIdentifier in new_object_list:
new_object_list.remove(apdu.iAmDeviceIdentifier)

if list(old_object_list) != list(new_object_list):
LOGGER.debug(
f"Object lists aren't equal!... {old_object_list} -> {new_object_list}"
)

await self.read_multiple_objects(apdu.iAmDeviceIdentifier)

def identifier_to_string(self, object_identifier) -> str:
return f"{object_identifier[0].attr}:{object_identifier[1]}"
Expand Down

0 comments on commit 542b964

Please sign in to comment.