Skip to content

Commit

Permalink
Different tests to include priorityArray when defining the device. Do…
Browse files Browse the repository at this point in the history
…esn't

work really well...
  • Loading branch information
ChristianTremblay committed Apr 14, 2018
1 parent 97587ce commit ace882f
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 77 deletions.
22 changes: 15 additions & 7 deletions BAC0/core/devices/Points.py
Expand Up @@ -70,7 +70,8 @@ class Point():

def __init__(self, device=None,
pointType=None, pointAddress=None, pointName=None,
description=None, presentValue=None, units_state=None):
description=None, presentValue=None, units_state=None,
priority_array = None):

self._history = namedtuple('_history', ['timestamp', 'value'])
self.properties = PointProperties()
Expand All @@ -95,6 +96,7 @@ def __init__(self, device=None,

self.properties.description = description
self.properties.units_state = units_state
self.properties.priority_array = priority_array
self.properties.simulated = (False, 0)
self.properties.overridden = (False, 0)

Expand Down Expand Up @@ -455,11 +457,13 @@ class NumericPoint(Point):

def __init__(self, device=None,
pointType=None, pointAddress=None, pointName=None,
description=None, presentValue=None, units_state=None):
description=None, presentValue=None, units_state=None,
priority_array=None):

Point.__init__(self, device=device,
pointType=pointType, pointAddress=pointAddress, pointName=pointName,
description=description, presentValue=presentValue, units_state=units_state)
description=description, presentValue=presentValue, units_state=units_state,
priority_array=priority_array)

@property
def units(self):
Expand Down Expand Up @@ -518,11 +522,13 @@ class BooleanPoint(Point):

def __init__(self, device=None,
pointType=None, pointAddress=None, pointName=None,
description=None, presentValue=None, units_state=None):
description=None, presentValue=None, units_state=None,
priority_array=None):

Point.__init__(self, device=device,
pointType=pointType, pointAddress=pointAddress, pointName=pointName,
description=description, presentValue=presentValue, units_state=units_state)
description=description, presentValue=presentValue, units_state=units_state,
priority_array=priority_array)

@property
def value(self):
Expand Down Expand Up @@ -602,11 +608,13 @@ class EnumPoint(Point):

def __init__(self, device=None,
pointType=None, pointAddress=None, pointName=None,
description=None, presentValue=None, units_state=None):
description=None, presentValue=None, units_state=None,
priority_array=None):

Point.__init__(self, device=device,
pointType=pointType, pointAddress=pointAddress, pointName=pointName,
description=description, presentValue=presentValue, units_state=units_state)
description=description, presentValue=presentValue, units_state=units_state,
priority_array=priority_array)

@property
def enumValue(self):
Expand Down
69 changes: 54 additions & 15 deletions BAC0/core/devices/mixins/read_mixin.py
Expand Up @@ -10,11 +10,13 @@
#--- standard Python modules ---

#--- 3rd party modules ---
from bacpypes import basetypes

#--- this application's modules ---
from ....tasks.Poll import DevicePoll
from ...io.IOExceptions import ReadPropertyMultipleException, NoResponseFromController, SegmentationNotSupported
from ...io.IOExceptions import ReadPropertyMultipleException, NoResponseFromController, SegmentationNotSupported, UnknownObjectError
from ..Points import NumericPoint, BooleanPoint, EnumPoint, OfflinePoint
from ...io.Read import validate_rpm

#------------------------------------------------------------------------------

Expand Down Expand Up @@ -91,6 +93,8 @@ def read_multiple(self, points_list, *, points_per_request=25, discover_request=
big_request = discover_request[0]

for request in self._batches(big_request, points_per_request):
#info_length = len(request)-2
self._log.debug('RPM request len {}'.format(info_length))

try:
request = ('{} {}'.format(self.properties.address, ''.join(request)))
Expand Down Expand Up @@ -180,11 +184,12 @@ def read_single(self, points_list, *, points_per_request=1, discover_request=(No


def _discoverPoints(self, custom_object_list = None):
self._log.debug('Discovering points...')
if custom_object_list:
objList = custom_object_list
else:
try :
objList = self.properties.network.read(
objList = self.properties.network.read(
'{} device {} objectList'.format(self.properties.address, self.properties.device_id))

except NoResponseFromController:
Expand All @@ -202,15 +207,41 @@ def _discoverPoints(self, custom_object_list = None):

points = []


def try_to_add_priorityArray(requests):
new_request = []
length_of_request = 0
for each in requests:
length_of_request = len(each.split(' '))
try:
req_with_pa = each + "priorityArray "
built_req = validate_rpm(req_with_pa)
new_request.append(req_with_pa)
self._log.debug('Can add priority array to {}'.format(new_request))
except (ValueError, UnknownObjectError):
req_with_one_more_property = each + "objectType "
new_request.append(req_with_one_more_property)
self._log.debug('Will read objectIdentifier instead... {}'.format(new_request))
return (new_request, length_of_request)

def retrieve_priority_array_from_response(response):
priority_array = response[-1]
if isinstance(priority_array, basetypes.PriorityArray):
self._log.debug('There a priority array ', priority_array)
return (priority_array, response)
else:
return (False, response)


# Numeric
analog_request = []

list_of_analog = retrieve_type(objList, 'analog')
for analog_points, address in list_of_analog:
analog_request.append('{} {} objectName presentValue units description '.format(analog_points, address))


try:
analog_points_info = self.read_multiple('', discover_request=(analog_request, 4), points_per_request=5)
analog_points_info = self.read_multiple('', discover_request=try_to_add_priorityArray(analog_request), points_per_request=5)
self._log.info(analog_points_info)
except SegmentationNotSupported:
raise
Expand All @@ -220,40 +251,43 @@ def _discoverPoints(self, custom_object_list = None):
point_type = str(each[0])
point_address = str(each[1])
point_infos = analog_points_info[i]

point_priority_array, point_infos = retrieve_priority_array_from_response(point_infos)

if len(point_infos) == 4:
if len(point_infos) == 5:
point_units_state = point_infos[2]
point_description = point_infos[3]

elif len(point_infos) == 3:
elif len(point_infos) == 4:
#we probably get only objectName, presentValue and units
point_units_state = point_infos[2]
point_description = ""

elif len(point_infos) == 2:
elif len(point_infos) == 3:
point_units_state = ""
point_description = ""

else:
#raise ValueError('Not enough values returned', each, point_infos)
# SHOULD SWITCH TO SEGMENTATION_SUPPORTED = FALSE HERE
self._log.warning('Cannot add {} / {} | {}'.format(point_type, point_address, len(point_infos)))
i += 1
continue

i += 1
points.append(
NumericPoint(
pointType=point_type, pointAddress=point_address, pointName=point_infos[0],
description=point_description, presentValue=float(point_infos[1]), units_state=point_units_state,
device=self))
priority_array = point_priority_array, device=self))

multistate_request = []
list_of_multistate = retrieve_type(objList, 'multi')
for multistate_points, address in list_of_multistate:
multistate_request.append('{} {} objectName presentValue stateText description '.format(multistate_points, address))

try:
multistate_points_info= self.read_multiple('', discover_request=(multistate_request, 4), points_per_request=5)
multistate_points_info= self.read_multiple('', discover_request=try_to_add_priorityArray(multistate_request), points_per_request=5)
except SegmentationNotSupported:
raise

Expand All @@ -262,21 +296,24 @@ def _discoverPoints(self, custom_object_list = None):
point_type = str(each[0])
point_address = str(each[1])
point_infos = multistate_points_info[i]

point_priority_array, point_infos = retrieve_priority_array_from_response(point_infos)

i += 1

points.append(
EnumPoint(
pointType=point_type, pointAddress=point_address, pointName=point_infos[0],
description=point_infos[3], presentValue=point_infos[1], units_state=point_infos[2],
device=self))
priority_array = point_priority_array, device=self))

binary_request = []
list_of_binary = retrieve_type(objList, 'binary')
for binary_points, address in list_of_binary:
binary_request.append('{} {} objectName presentValue inactiveText activeText description '.format(binary_points, address))

try:
binary_points_info= self.read_multiple('', discover_request=(binary_request, 5), points_per_request=5)
binary_points_info= self.read_multiple('', discover_request=try_to_add_priorityArray(binary_request), points_per_request=5)
except SegmentationNotSupported:
raise

Expand All @@ -286,19 +323,21 @@ def _discoverPoints(self, custom_object_list = None):
point_address = str(each[1])
point_infos = binary_points_info[i]

if len(point_infos) == 3:
point_priority_array, point_infos = retrieve_priority_array_from_response(point_infos)

if len(point_infos) == 4:
#we probably get only objectName, presentValue and description
point_units_state = ('OFF', 'ON')
point_description = point_infos[2]

elif len(point_infos) == 5:
elif len(point_infos) == 6:
point_units_state = (point_infos[2], point_infos[3])
point_description = point_infos[4]

if point_description is None:
point_description = ""

elif len(point_infos) == 2:
elif len(point_infos) == 3:
point_units_state = ('OFF', 'ON')
point_description = ""

Expand All @@ -313,7 +352,7 @@ def _discoverPoints(self, custom_object_list = None):
BooleanPoint(
pointType=point_type, pointAddress=point_address, pointName=point_infos[0],
description=point_description, presentValue=point_infos[1], units_state=point_units_state,
device=self))
priority_array = point_priority_array, device=self))

self._log.info('Ready!')
return (objList, points)
Expand Down
112 changes: 59 additions & 53 deletions BAC0/core/io/Read.py
Expand Up @@ -318,7 +318,8 @@ def build_rp_request(self, args, arr_index=None, vendor_id=0, bacoid=None):
prop_id = int(prop_id)
datatype = get_datatype(obj_type, prop_id, vendor_id=vendor_id)
if not datatype:
raise ValueError("invalid property for object type")
raise ValueError("invalid property for object type : {} | {}".format(
obj_type, prop_id))

# build a request
request = ReadPropertyRequest(
Expand All @@ -338,71 +339,76 @@ def build_rpm_request(self, args):
"""
Build request from args
"""
i = 0
addr = args[i]
i += 1

read_access_spec_list = []
while i < len(args):
obj_type = args[i]
i += 1

if obj_type.isdigit():
obj_type = int(obj_type)
elif not get_object_class(obj_type):
raise ValueError("unknown object type")
read_access_spec_list, addr = validate_rpm(args)
# build the request
request = ReadPropertyMultipleRequest(
listOfReadAccessSpecs=read_access_spec_list)
request.pduDestination = Address(addr)
self._log.debug("{:<20} {!r}".format(
'REQUEST', request))
return request

obj_inst = int(args[i])
i += 1

prop_reference_list = []
while i < len(args):
prop_id = args[i]
if prop_id not in PropertyIdentifier.enumerations:
break
def validate_rpm(args):
i = 0
addr = args[i]
i += 1

i += 1
if prop_id in ('all', 'required', 'optional'):
pass
else:
datatype = get_datatype(obj_type, prop_id)
if not datatype:
raise ValueError(
"invalid property for object type : {} | {}".format(
(obj_type, prop_id)))
read_access_spec_list = []
while i < len(args):
obj_type = args[i]
i += 1

# build a property reference
prop_reference = PropertyReference(propertyIdentifier=prop_id)
if obj_type.isdigit():
obj_type = int(obj_type)
elif not get_object_class(obj_type):
raise ValueError("unknown object type")

# check for an array index
if (i < len(args)) and args[i].isdigit():
prop_reference.propertyArrayIndex = int(args[i])
i += 1
obj_inst = int(args[i])
i += 1

prop_reference_list.append(prop_reference)
prop_reference_list = []
while i < len(args):
prop_id = args[i]
if prop_id not in PropertyIdentifier.enumerations:
break

if not prop_reference_list:
raise ValueError("provide at least one property")
i += 1
if prop_id in ('all', 'required', 'optional'):
pass
else:
datatype = get_datatype(obj_type, prop_id)
if not datatype:
raise ValueError(
"invalid property for object type : {} | {}".format(
obj_type, prop_id))

# build a property reference
prop_reference = PropertyReference(propertyIdentifier=prop_id)

# check for an array index
if (i < len(args)) and args[i].isdigit():
prop_reference.propertyArrayIndex = int(args[i])
i += 1

# build a read access specification
read_access_spec = ReadAccessSpecification(
objectIdentifier=(obj_type, obj_inst),
listOfPropertyReferences=prop_reference_list)
prop_reference_list.append(prop_reference)

read_access_spec_list.append(read_access_spec)
if not prop_reference_list:
raise ValueError("provide at least one property")

if not read_access_spec_list:
raise RuntimeError(
"at least one read access specification required")
# build a read access specification
read_access_spec = ReadAccessSpecification(
objectIdentifier=(obj_type, obj_inst),
listOfPropertyReferences=prop_reference_list)

# build the request
request = ReadPropertyMultipleRequest(
listOfReadAccessSpecs=read_access_spec_list)
request.pduDestination = Address(addr)
self._log.debug("{:<20} {!r}".format(
'REQUEST', request))
return request
read_access_spec_list.append(read_access_spec)

if not read_access_spec_list:
raise RuntimeError(
"at least one read access specification required")

return (read_access_spec_list, addr)

def find_reason(apdu):
if apdu.pduType == RejectPDU.pduType:
Expand Down

0 comments on commit ace882f

Please sign in to comment.