From 9e318177b46f8eeff0b706699512b1b7de87338f Mon Sep 17 00:00:00 2001 From: Christian Tremblay Date: Fri, 23 Aug 2019 11:10:04 -0400 Subject: [PATCH] Attempt to implement the feature where some properties must be writable when OutOfService is set to True. I've added a new parameter to ReadProperty and OptionalProperty named writable_if_oos that propagate to the property. Then at the object level, it is possible to look this parameter in the property then check the outOfService value to change mutability of the property on the fly. In the ReadProperty function, I will also check the OutOfService property to reset mutability if no longer needed. Internally, in the app, if writing to the presentValue directly, a validation of the OutOfService property will be possible when this parameter is True so the program won't update the value of the property as long as the OutOfService property is True. It could also be a good practice that the program can reset the mutability as soon as OutOfService is set to false in the logic of the program... not necessarely fast enough to wait for a network Read on the property. Signed-off-by: Christian Tremblay --- py34/bacpypes/object.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/py34/bacpypes/object.py b/py34/bacpypes/object.py index 223d5ba..3e345e6 100644 --- a/py34/bacpypes/object.py +++ b/py34/bacpypes/object.py @@ -150,7 +150,7 @@ def get_datatype(object_type, propid, vendor_id=0): @bacpypes_debugging class Property: - def __init__(self, identifier, datatype, default=None, optional=True, mutable=True): + def __init__(self, identifier, datatype, default=None, optional=True, mutable=True, writable_if_oos=False): if _debug: Property._debug("__init__ %s %s default=%r optional=%r mutable=%r", identifier, datatype, default, optional, mutable @@ -167,6 +167,7 @@ class Property: self.optional = optional self.mutable = mutable self.default = default + self.writable_if_oos = writable_if_oos def ReadProperty(self, obj, arrayIndex=None): if _debug: @@ -360,7 +361,7 @@ class Property: @bacpypes_debugging class StandardProperty(Property): - def __init__(self, identifier, datatype, default=None, optional=True, mutable=True): + def __init__(self, identifier, datatype, default=None, optional=True, mutable=True, writable_if_oos=False): if _debug: StandardProperty._debug("__init__ %s %s default=%r optional=%r mutable=%r", identifier, datatype, default, optional, mutable @@ -375,7 +376,7 @@ class StandardProperty(Property): raise ConfigurationError("unknown standard property identifier: %s" % (identifier,)) # continue with the initialization - Property.__init__(self, identifier, datatype, default, optional, mutable) + Property.__init__(self, identifier, datatype, default, optional, mutable, writable_if_oos) # # OptionalProperty @@ -386,14 +387,14 @@ class OptionalProperty(StandardProperty): """The property is required to be present and readable using BACnet services.""" - def __init__(self, identifier, datatype, default=None, optional=True, mutable=False): + def __init__(self, identifier, datatype, default=None, optional=True, mutable=False, writable_if_oos=False): if _debug: OptionalProperty._debug("__init__ %s %s default=%r optional=%r mutable=%r", identifier, datatype, default, optional, mutable ) # continue with the initialization - StandardProperty.__init__(self, identifier, datatype, default, optional, mutable) + StandardProperty.__init__(self, identifier, datatype, default, optional, mutable, writable_if_oos) # # ReadableProperty @@ -404,14 +405,14 @@ class ReadableProperty(StandardProperty): """The property is required to be present and readable using BACnet services.""" - def __init__(self, identifier, datatype, default=None, optional=False, mutable=False): + def __init__(self, identifier, datatype, default=None, optional=False, mutable=False, writable_if_oos=False): if _debug: ReadableProperty._debug("__init__ %s %s default=%r optional=%r mutable=%r", identifier, datatype, default, optional, mutable ) # continue with the initialization - StandardProperty.__init__(self, identifier, datatype, default, optional, mutable) + StandardProperty.__init__(self, identifier, datatype, default, optional, mutable, writable_if_oos) # # WritableProperty @@ -590,6 +591,11 @@ class Object: if not prop: raise PropertyError(propid) + if prop.writable_if_oos: + # Reset mutability if no longer needed + if not self._properties.get("outOfService"): + prop.mutable = False + # defer to the property to get the value return prop.ReadProperty(self, arrayIndex) @@ -601,6 +607,13 @@ class Object: if not prop: raise PropertyError(propid) + if prop.writable_if_oos: + if self._properties.get("outOfService"): + # Turn on mutability as OutOfService is true + prop.mutable = True + else: + prop.mutable = False + # defer to the property to set the value return prop.WriteProperty(self, value, arrayIndex, priority, direct) @@ -949,11 +962,11 @@ class AlertEnrollmentObject(Object): class AnalogInputObject(Object): objectType = 'analogInput' properties = \ - [ ReadableProperty('presentValue', Real) + [ ReadableProperty('presentValue', Real, writable_if_oos=True) , OptionalProperty('deviceType', CharacterString) , ReadableProperty('statusFlags', StatusFlags) , ReadableProperty('eventState', EventState) - , OptionalProperty('reliability', Reliability) + , OptionalProperty('reliability', Reliability, writable_if_oos=True) , ReadableProperty('outOfService', Boolean) , OptionalProperty('updateInterval', Unsigned) , ReadableProperty('units', EngineeringUnits)