Skip to content

Commit

Permalink
SQuiching bugs and fixing nightmares
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianTremblay committed Jan 11, 2024
1 parent 5bcd3df commit a19bb63
Show file tree
Hide file tree
Showing 19 changed files with 211 additions and 111 deletions.
2 changes: 1 addition & 1 deletion BAC0/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

try:
from . import core, tasks
from .core.devices.Device import Device as device
from .core.devices.Device import device as device
from .core.devices.Device import DeviceLoad as load
from .core.devices.Trends import TrendLog as TrendLog
from .core.utils.notes import update_log_level as log_level
Expand Down
2 changes: 1 addition & 1 deletion BAC0/core/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from . import app, devices, functions, io
# from . import app, devices, functions, io
8 changes: 8 additions & 0 deletions BAC0/core/app/asyncApp.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@ def create_app(self, json_file):
# create a BVLL application service element
bvll_ase = BVLLServiceElement()
bind(bvll_ase, bvll_sap)


class BAC0BBMDDeviceApplication(BAC0Application):
pass


class BAC0ForeignDeviceApplication(BAC0Application):
pass
2 changes: 1 addition & 1 deletion BAC0/core/devices/Device.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def asdict(self):
return self.__dict__


def ADevice(*args, **kwargs):
def device(*args, **kwargs):
dev = Device(*args, **kwargs)
t = asyncio.create_task(dev.new_state(DeviceDisconnected))
while not t.done:
Expand Down
2 changes: 1 addition & 1 deletion BAC0/core/devices/local/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from bacpypes3.object import TrendLogObject
from colorama import Fore

from BAC0.core.app.ScriptApplication import (
from BAC0.core.app.asyncApp import (
BAC0BBMDDeviceApplication,
BAC0ForeignDeviceApplication,
)
Expand Down
31 changes: 28 additions & 3 deletions BAC0/core/devices/mixins/read_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,10 @@ async def _process_new_objects(
raise ValueError("Unsupported objectType")

for points, address in retrieve_type(objList, obj_type):
request.append("{} {} {} ".format(points, address, prop_list))
request.append(f"{points} {address} {prop_list} ")

def _find_propid_index(key):
self._log.debug(f"Prop List : {prop_list}")
_prop_list = prop_list.split(" ")
for i, each in enumerate(_prop_list):
if key == each:
Expand All @@ -296,6 +297,7 @@ def _find_propid_index(key):
discover_request=(request, len(prop_list.split(" "))),
points_per_request=points_per_request,
)
self._log.debug(f"Points Info : {points_info}")
except SegmentationNotSupported:
raise
# Process responses and create point
Expand All @@ -305,9 +307,14 @@ def _find_propid_index(key):
point_address = str(each[1])
point_infos = points_info[i]
i += 1

self._log.debug(
f"Retrieved Type {point_type} {point_address} {point_infos}"
)
pointName = point_infos[_find_propid_index("objectName")]
presentValue = point_infos[_find_propid_index("presentValue")]
self._log.debug(
f"Reading {pointName} gave {presentValue} of type {obj_type}"
)
if presentValue is not None:
if obj_type == "analog" or obj_type == "loop":
presentValue = float(presentValue)
Expand Down Expand Up @@ -426,7 +433,7 @@ async def read_multiple(
*,
points_per_request=25,
discover_request=(None, 6),
force_single=False
force_single=False,
):
"""
Read points from a device using a ReadPropertyMultiple request.
Expand Down Expand Up @@ -472,6 +479,21 @@ async def read_multiple(
)
except SegmentationNotSupported:
raise
except ValueError as error:
# high limit ?
self._log.warning(
f"Got a value error of {error} for request : {request}"
)
self._log.warning(
"We will use single point reading to create device and turn off segmentation support"
)
self.properties.segmentation_supported = False
await self.read_multiple(
points_list,
points_per_request=1,
discover_request=discover_request,
)
break

# print('val : ', val, len(val), type(val))
if val is None:
Expand All @@ -483,6 +505,9 @@ async def read_multiple(

except SegmentationNotSupported:
self.properties.segmentation_supported = False
self._log.warning(
"Looks like segmentation is not supported. Turning that off."
)
# self.read_multiple(points_list,points_per_request=1, discover_request=discover_request)
self._log.warning("Segmentation not supported")
self._log.warning("Request too big...will reduce it")
Expand Down
33 changes: 7 additions & 26 deletions BAC0/core/io/Read.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,39 +256,20 @@ async def readMultiple(
except ErrorRejectAbortNack as err:
# construction error
response = err
self._log.exception(f"exception: {err!r}")

"""
Other Except if BAC0 can catch them
Which is not the case actually
# note: the return types along this pass don't appear to be consistent
# not sure if this is a real problem or not, leaving as-is and ignoring errors
if iocb.ioError: # unsuccessful: error/reject/abort
apdu = iocb.ioError
reason = find_reason(apdu)
self._log.warning("APDU Abort Reject Reason : {}".format(reason))
self._log.debug("The Request was : {}".format(args))
if reason == "unrecognizedService":
self._log.exception(f"exception: {err.reason}")
if "segmentation-not-supported" in str(err.reason):
raise SegmentationNotSupported
if "unrecognized-service" in str(err.reason):
raise UnrecognizedService()
elif reason == "segmentationNotSupported":
# value = self._split_the_read_request(args, arr_index)
# return value
self.segmentation_supported = False
raise SegmentationNotSupported()
elif reason == "unknownObject":
if "unknown-object" in str(err.reason):
self._log.warning("Unknown object {}".format(args))
raise UnknownObjectError("Unknown object {}".format(args))
elif reason == "unknownProperty":
self._log.warning("Unknown property {}".format(args))
if "unknown-property" in str(err.reason):
values.append("") # type: ignore[arg-type]
return values
else:
self._log.warning("No response from controller {}".format(reason))
if "no-response" in str(err.reason):
values.append("") # type: ignore[arg-type]
return values
"""

if not isinstance(response, ErrorRejectAbortNack):
# Dealt in bp3
Expand Down
23 changes: 12 additions & 11 deletions BAC0/core/proprietary_objects/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
from .legacy.jci import (
JCIAnalogInputObject,
JCIAnalogOutputObject,
JCIAnalogValueObject,
JCIDeviceObject,
)
from .object import create_proprietary_object
# from .legacy.jci import (
# JCIAnalogInputObject,
# JCIAnalogOutputObject,
# JCIAnalogValueObject,
# JCIDeviceObject,
# )
# from .object import create_proprietary_object##

create_proprietary_object(JCIAnalogValueObject)
create_proprietary_object(JCIAnalogInputObject)
create_proprietary_object(JCIAnalogOutputObject)
create_proprietary_object(JCIDeviceObject)
# create_proprietary_object(JCIAnalogValueObject)
# create_proprietary_object(JCIAnalogInputObject)
# create_proprietary_object(JCIAnalogOutputObject)
# create_proprietary_object(JCIDeviceObject)
import jci
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Dict

from bacpypes.object import (
from bacpypes3.object import (
Object,
Property,
register_object_type,
Expand Down
62 changes: 62 additions & 0 deletions BAC0/tools/jci_tec_points_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
def tec_short_point_list(unit_type="2-pipe"):
"""
unit_type can be :
- 4-pipe
- 2-pipe
- VAV
"""
_lst = [
("binaryInput", 30827),
("binaryInput", 30828),
("binaryOutput", 86908),
("binaryOutput", 86909),
("binaryOutput", 86910),
("binaryOutput", 86911),
("binaryOutput", 86912),
("binaryOutput", 87101),
("binaryOutput", 87102),
("multiStateValue", 29501),
("multiStateValue", 29500),
("multiStateValue", 29509),
("multiStateValue", 29517),
("multiStateValue", 29518),
("multiStateValue", 29519),
("multiStateValue", 29520),
("multiStateValue", 29524),
("multiStateValue", 29525),
("multiStateValue", 29527),
("multiStateValue", 29712),
("multiStateValue", 29700),
("multiStateValue", 29709),
("multiStateValue", 29708),
("analogValue", 29505),
# ("analogValue", 29502),
# ("analogValue", 29503),
("analogValue", 29504),
("analogValue", 29506),
("analogValue", 29507),
("analogValue", 29508),
("analogValue", 29515),
("analogValue", 29522),
("analogValue", 29529),
("analogValue", 29530),
("analogValue", 29532),
("analogValue", 29701),
("analogValue", 29703),
("analogValue", 29705),
("analogValue", 29706),
("analogValue", 29707),
("analogValue", 29714),
("analogValue", 29717),
("analogValue", 29725),
("analogValue", 29726),
("analogValue", 29727),
("analogOutput", 86905),
("multiStateValue", 6),
("trendLog", 101010),
]
if unit_type == "4-pipe":
_lst.append(("analogOutput", 86914))
_lst.append(("analogOutput", 86915))

return _lst
68 changes: 65 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,26 @@
import pytest_asyncio

import BAC0
from BAC0.core.devices.local.models import (
analog_input,
analog_output,
analog_value,
binary_input,
binary_output,
binary_value,
character_string,
date_value,
datetime_value,
humidity_input,
humidity_value,
make_state_text,
multistate_input,
multistate_output,
multistate_value,
temperature_input,
temperature_value,
)
from BAC0.core.devices.local.object import ObjectFactory

# All test coroutines will be treated as marked.
pytestmark = pytest.mark.asyncio
Expand All @@ -26,16 +46,58 @@ def event_loop():
loop.close()


def add_points(qty_per_type, device):
# Start from fresh
ObjectFactory.clear_objects()
basic_qty = qty_per_type - 1
# Analog Inputs
# Default... percent
for _ in range(basic_qty):
_new_objects = analog_input(presentValue=99.9)
_new_objects = multistate_value(presentValue=1)

# Supplemental with more details, for demonstration
_new_objects = analog_input(
name="ZN-T",
properties={"units": "degreesCelsius"},
description="Zone Temperature",
presentValue=21,
)

states = make_state_text(["Normal", "Alarm", "Super Emergency"])
_new_objects = multistate_value(
description="An Alarm Value",
properties={"stateText": states},
name="BIG-ALARM",
is_commandable=True,
)

# All others using default implementation
for _ in range(qty_per_type):
_new_objects = analog_output(presentValue=89.9)
_new_objects = analog_value(presentValue=79.9)
_new_objects = binary_input()
_new_objects = binary_output()
_new_objects = binary_value()
_new_objects = multistate_input()
_new_objects = multistate_output()
_new_objects = date_value()
_new_objects = datetime_value()
_new_objects = character_string(presentValue="test")

_new_objects.add_objects_to_application(device)


@pytest_asyncio.fixture(scope="session")
async def async_network_and_devices(event_loop):
assert event_loop is asyncio.get_running_loop()
# This is the BACnet network and the "client" instance used to interact with
# devices that will be created.
bacnet = BAC0.Async()
bacnet = BAC0.lite()

# We'll use 3 devices with our first instance
device_app = BAC0.Async(port=47809, deviceId=101)
device30_app = BAC0.Async(port=47810, deviceId=102)
device_app = BAC0.lite(port=47809, deviceId=101)
device30_app = BAC0.lite(port=47810, deviceId=102)
# device300_app = BAC0.lite(port=47811, deviceId=103)
# time.sleep(0.01)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
Unsigned,
)

from BAC0.core.proprietary_objects.object import create_proprietary_object
from BAC0.core.proprietary_objects.legacy.object import create_proprietary_object

MyDeviceProprietaryProperties = {
"name": "MyDeviceProprietaryProperties",
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion tests/manual_test_create_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def main():
boid_300 = device300_app.Boid

# Connect to test device using main network
test_device = BAC0.ADevice("{}:47809".format(ip), boid, bacnet, poll=10)
test_device = BAC0.device("{}:47809".format(ip), boid, bacnet, poll=10)
# test_device_30 = BAC0.device("{}:47810".format(ip_30), boid_30, bacnet, poll=0)
# test_device_300 = BAC0.device("{}:47811".format(ip_300), boid_300, bacnet, poll=0)
while True:
Expand Down
14 changes: 8 additions & 6 deletions tests/manual_test_history_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import BAC0

bacnet = BAC0.Async()
bacnet = BAC0.lite()

pcv = BAC0.ADevice("303:12", 5012, bacnet)
for _ in range(4):
pcv["SUPHTG1-C"] = True
time.sleep(1)

pcv.backup_histories_df()
async def etst_history_sql():
pcv = await BAC0.device("303:12", 5012, bacnet)
for _ in range(4):
pcv["SUPHTG1-C"] = True
time.sleep(1)

pcv.backup_histories_df()
Loading

0 comments on commit a19bb63

Please sign in to comment.