1
0
mirror of https://github.com/JoelBender/bacpypes synced 2025-09-28 22:15:23 +08:00

0.18.0 releasd

This commit is contained in:
Joel Bender 2020-01-29 15:46:08 -05:00
parent 792041b3ca
commit 5c7da58ad6
28 changed files with 902 additions and 220 deletions

View File

@ -18,7 +18,7 @@ if _sys.platform not in _supported_platforms:
# Project Metadata
#
__version__ = '0.17.7'
__version__ = '0.18.0'
__author__ = 'Joel Bender'
__email__ = 'joel@carrickbender.com'

View File

@ -419,7 +419,7 @@ class ApplicationIOController(IOController, Application):
# look up the queue
queue = self.queue_by_address.get(destination_address, None)
if not queue:
queue = SieveQueue(self.request, destination_address)
queue = SieveQueue(self._app_request, destination_address)
self.queue_by_address[destination_address] = queue
if _debug: ApplicationIOController._debug(" - queue: %r", queue)
@ -455,16 +455,27 @@ class ApplicationIOController(IOController, Application):
if _debug: ApplicationIOController._debug(" - queue is empty")
del self.queue_by_address[address]
def request(self, apdu):
if _debug: ApplicationIOController._debug("request %r", apdu)
def _app_request(self, apdu):
if _debug: ApplicationIOController._debug("_app_request %r", apdu)
# send it downstream
# send it downstream, bypass the guard
super(ApplicationIOController, self).request(apdu)
# if this was an unconfirmed request, it's complete, no message
if isinstance(apdu, UnconfirmedRequestPDU):
self._app_complete(apdu.pduDestination, None)
def request(self, apdu):
if _debug: ApplicationIOController._debug("request %r", apdu)
# if this is not unconfirmed request, tell the application to use
# the IOCB interface
if not isinstance(apdu, UnconfirmedRequestPDU):
raise RuntimeError("use IOCB for confirmed requests")
# send it downstream
super(ApplicationIOController, self).request(apdu)
def confirmation(self, apdu):
if _debug: ApplicationIOController._debug("confirmation %r", apdu)

View File

@ -84,7 +84,7 @@ class SSM(OneShotTask, DebugContents):
self.apduTimeout = getattr(sap.localDevice, 'apduTimeout', sap.apduTimeout)
self.segmentationSupported = getattr(sap.localDevice, 'segmentationSupported', sap.segmentationSupported)
self.segmentTimeout = getattr(sap.localDevice, 'segmentTimeout', sap.segmentTimeout)
self.segmentTimeout = getattr(sap.localDevice, 'apduSegmentTimeout', sap.segmentTimeout)
self.maxSegmentsAccepted = getattr(sap.localDevice, 'maxSegmentsAccepted', sap.maxSegmentsAccepted)
self.maxApduLengthAccepted = getattr(sap.localDevice, 'maxApduLengthAccepted', sap.maxApduLengthAccepted)
@ -530,7 +530,11 @@ class ClientSSM(SSM):
self.segmentRetryCount += 1
self.start_timer(self.segmentTimeout)
self.fill_window(self.initialSequenceNumber)
if self.initialSequenceNumber == 0:
self.request(self.get_segment(0))
else:
self.fill_window(self.initialSequenceNumber)
else:
if _debug: ClientSSM._debug(" - abort, no response from the device")

View File

@ -1800,7 +1800,6 @@ class NameValue(Sequence):
bacpypes_debugging(NameValue)
>>>>>>> stage
class DeviceAddress(Sequence):
sequenceElements = \
[ Element('networkNumber', Unsigned)
@ -2625,8 +2624,8 @@ class PropertyReference(Sequence):
class Scale(Choice):
choiceElements = \
[ Element('floatScale', Real)
, Element('integerScale', Integer)
[ Element('floatScale', Real, 0)
, Element('integerScale', Integer, 1)
]
class SecurityKeySet(Sequence):

View File

@ -173,7 +173,7 @@ def run(spin=SPIN, sigterm=stop, sigusr1=print_stack):
if _debug: run._info("keyboard interrupt")
running = False
except Exception, err:
if _debug: run._exception("an error has occurred: %s", err)
run._exception("an error has occurred: %s", err)
running = False
@ -223,7 +223,7 @@ def run_once():
except KeyboardInterrupt:
if _debug: run_once._info("keyboard interrupt")
except Exception, err:
if _debug: run_once._exception("an error has occurred: %s", err)
run_once._exception("an error has occurred: %s", err)
bacpypes_debugging(run_once)

View File

@ -523,8 +523,8 @@ class ActiveCOVSubscriptions(Property):
current_time = TaskManager().get_time()
if _debug: ActiveCOVSubscriptions._debug(" - current_time: %r", current_time)
# start with an empty sequence
cov_subscriptions = ListOf(COVSubscription)()
# start with an empty list
cov_subscriptions = []
# loop through the subscriptions
for cov in obj._app.subscriptions():
@ -553,6 +553,10 @@ class ActiveCOVSubscriptions(Property):
)
if _debug: ActiveCOVSubscriptions._debug(" - recipient_process: %r", recipient_process)
# look for the algorithm already associated with this object
cov_detection = cov.obj_ref._app.cov_detections[cov.obj_ref]
if _debug: ActiveCOVSubscriptions._debug(" - cov_detection: %r", cov_detection)
cov_subscription = COVSubscription(
recipient=recipient_process,
monitoredPropertyReference=ObjectPropertyReference(

View File

@ -18,7 +18,7 @@ if _sys.platform not in _supported_platforms:
# Project Metadata
#
__version__ = '0.17.7'
__version__ = '0.18.0'
__author__ = 'Joel Bender'
__email__ = 'joel@carrickbender.com'

View File

@ -427,7 +427,7 @@ class ApplicationIOController(IOController, Application):
# look up the queue
queue = self.queue_by_address.get(destination_address, None)
if not queue:
queue = SieveQueue(self.request, destination_address)
queue = SieveQueue(self._app_request, destination_address)
self.queue_by_address[destination_address] = queue
if _debug: ApplicationIOController._debug(" - queue: %r", queue)
@ -463,16 +463,27 @@ class ApplicationIOController(IOController, Application):
if _debug: ApplicationIOController._debug(" - queue is empty")
del self.queue_by_address[address]
def request(self, apdu):
if _debug: ApplicationIOController._debug("request %r", apdu)
def _app_request(self, apdu):
if _debug: ApplicationIOController._debug("_app_request %r", apdu)
# send it downstream
# send it downstream, bypass the guard
super(ApplicationIOController, self).request(apdu)
# if this was an unconfirmed request, it's complete, no message
if isinstance(apdu, UnconfirmedRequestPDU):
self._app_complete(apdu.pduDestination, None)
def request(self, apdu):
if _debug: ApplicationIOController._debug("request %r", apdu)
# if this is not unconfirmed request, tell the application to use
# the IOCB interface
if not isinstance(apdu, UnconfirmedRequestPDU):
raise RuntimeError("use IOCB for confirmed requests")
# send it downstream
super(ApplicationIOController, self).request(apdu)
def confirmation(self, apdu):
if _debug: ApplicationIOController._debug("confirmation %r", apdu)

View File

@ -85,7 +85,7 @@ class SSM(OneShotTask, DebugContents):
self.apduTimeout = getattr(sap.localDevice, 'apduTimeout', sap.apduTimeout)
self.segmentationSupported = getattr(sap.localDevice, 'segmentationSupported', sap.segmentationSupported)
self.segmentTimeout = getattr(sap.localDevice, 'segmentTimeout', sap.segmentTimeout)
self.segmentTimeout = getattr(sap.localDevice, 'apduSegmentTimeout', sap.segmentTimeout)
self.maxSegmentsAccepted = getattr(sap.localDevice, 'maxSegmentsAccepted', sap.maxSegmentsAccepted)
self.maxApduLengthAccepted = getattr(sap.localDevice, 'maxApduLengthAccepted', sap.maxApduLengthAccepted)
@ -530,7 +530,11 @@ class ClientSSM(SSM):
self.segmentRetryCount += 1
self.start_timer(self.segmentTimeout)
self.fill_window(self.initialSequenceNumber)
if self.initialSequenceNumber == 0:
self.request(self.get_segment(0))
else:
self.fill_window(self.initialSequenceNumber)
else:
if _debug: ClientSSM._debug(" - abort, no response from the device")

View File

@ -2623,8 +2623,8 @@ class PropertyReference(Sequence):
class Scale(Choice):
choiceElements = \
[ Element('floatScale', Real)
, Element('integerScale', Integer)
[ Element('floatScale', Real, 0)
, Element('integerScale', Integer, 1)
]
class SecurityKeySet(Sequence):

View File

@ -171,7 +171,7 @@ def run(spin=SPIN, sigterm=stop, sigusr1=print_stack):
if _debug: run._info("keyboard interrupt")
running = False
except Exception as err:
if _debug: run._exception("an error has occurred: %s", err)
run._exception("an error has occurred: %s", err)
running = False
@ -220,7 +220,7 @@ def run_once():
except KeyboardInterrupt:
if _debug: run_once._info("keyboard interrupt")
except Exception as err:
if _debug: run_once._exception("an error has occurred: %s", err)
run_once._exception("an error has occurred: %s", err)
#
# deferred

View File

@ -522,8 +522,8 @@ class ActiveCOVSubscriptions(Property):
current_time = TaskManager().get_time()
if _debug: ActiveCOVSubscriptions._debug(" - current_time: %r", current_time)
# start with an empty sequence
cov_subscriptions = ListOf(COVSubscription)()
# start with an empty list
cov_subscriptions = []
# loop through the subscriptions
for cov in obj._app.subscriptions():
@ -552,6 +552,10 @@ class ActiveCOVSubscriptions(Property):
)
if _debug: ActiveCOVSubscriptions._debug(" - recipient_process: %r", recipient_process)
# look for the algorithm already associated with this object
cov_detection = cov.obj_ref._app.cov_detections[cov.obj_ref]
if _debug: ActiveCOVSubscriptions._debug(" - cov_detection: %r", cov_detection)
cov_subscription = COVSubscription(
recipient=recipient_process,
monitoredPropertyReference=ObjectPropertyReference(

View File

@ -18,7 +18,7 @@ if _sys.platform not in _supported_platforms:
# Project Metadata
#
__version__ = '0.17.7'
__version__ = '0.18.0'
__author__ = 'Joel Bender'
__email__ = 'joel@carrickbender.com'

View File

@ -427,7 +427,7 @@ class ApplicationIOController(IOController, Application):
# look up the queue
queue = self.queue_by_address.get(destination_address, None)
if not queue:
queue = SieveQueue(self.request, destination_address)
queue = SieveQueue(self._app_request, destination_address)
self.queue_by_address[destination_address] = queue
if _debug: ApplicationIOController._debug(" - queue: %r", queue)
@ -463,16 +463,27 @@ class ApplicationIOController(IOController, Application):
if _debug: ApplicationIOController._debug(" - queue is empty")
del self.queue_by_address[address]
def request(self, apdu):
if _debug: ApplicationIOController._debug("request %r", apdu)
def _app_request(self, apdu):
if _debug: ApplicationIOController._debug("_app_request %r", apdu)
# send it downstream
# send it downstream, bypass the guard
super(ApplicationIOController, self).request(apdu)
# if this was an unconfirmed request, it's complete, no message
if isinstance(apdu, UnconfirmedRequestPDU):
self._app_complete(apdu.pduDestination, None)
def request(self, apdu):
if _debug: ApplicationIOController._debug("request %r", apdu)
# if this is not unconfirmed request, tell the application to use
# the IOCB interface
if not isinstance(apdu, UnconfirmedRequestPDU):
raise RuntimeError("use IOCB for confirmed requests")
# send it downstream
super(ApplicationIOController, self).request(apdu)
def confirmation(self, apdu):
if _debug: ApplicationIOController._debug("confirmation %r", apdu)

View File

@ -85,7 +85,7 @@ class SSM(OneShotTask, DebugContents):
self.apduTimeout = getattr(sap.localDevice, 'apduTimeout', sap.apduTimeout)
self.segmentationSupported = getattr(sap.localDevice, 'segmentationSupported', sap.segmentationSupported)
self.segmentTimeout = getattr(sap.localDevice, 'segmentTimeout', sap.segmentTimeout)
self.segmentTimeout = getattr(sap.localDevice, 'apduSegmentTimeout', sap.segmentTimeout)
self.maxSegmentsAccepted = getattr(sap.localDevice, 'maxSegmentsAccepted', sap.maxSegmentsAccepted)
self.maxApduLengthAccepted = getattr(sap.localDevice, 'maxApduLengthAccepted', sap.maxApduLengthAccepted)
@ -530,7 +530,11 @@ class ClientSSM(SSM):
self.segmentRetryCount += 1
self.start_timer(self.segmentTimeout)
self.fill_window(self.initialSequenceNumber)
if self.initialSequenceNumber == 0:
self.request(self.get_segment(0))
else:
self.fill_window(self.initialSequenceNumber)
else:
if _debug: ClientSSM._debug(" - abort, no response from the device")

View File

@ -2623,8 +2623,8 @@ class PropertyReference(Sequence):
class Scale(Choice):
choiceElements = \
[ Element('floatScale', Real)
, Element('integerScale', Integer)
[ Element('floatScale', Real, 0)
, Element('integerScale', Integer, 1)
]
class SecurityKeySet(Sequence):

View File

@ -171,7 +171,7 @@ def run(spin=SPIN, sigterm=stop, sigusr1=print_stack):
if _debug: run._info("keyboard interrupt")
running = False
except Exception as err:
if _debug: run._exception("an error has occurred: %s", err)
run._exception("an error has occurred: %s", err)
running = False
@ -220,7 +220,7 @@ def run_once():
except KeyboardInterrupt:
if _debug: run_once._info("keyboard interrupt")
except Exception as err:
if _debug: run_once._exception("an error has occurred: %s", err)
run_once._exception("an error has occurred: %s", err)
#
# deferred

View File

@ -764,9 +764,9 @@ class AccessDoorObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -817,9 +817,9 @@ class AccessPointObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -886,9 +886,9 @@ class AccessZoneObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -925,9 +925,9 @@ class AccumulatorObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -946,9 +946,9 @@ class AlertEnrollmentObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
]
@ -980,9 +980,9 @@ class AnalogInputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1018,9 +1018,9 @@ class AnalogOutputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1055,9 +1055,9 @@ class AnalogValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1108,9 +1108,9 @@ class BinaryInputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1148,9 +1148,9 @@ class BinaryOutputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1186,9 +1186,9 @@ class BinaryValueObject(Object):
, OptionalProperty('eventEnable',EventTransitionBits)
, OptionalProperty('ackedTransitions',EventTransitionBits)
, OptionalProperty('notifyType',NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1215,9 +1215,9 @@ class BitStringValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1254,9 +1254,9 @@ class ChannelObject(Object):
, OptionalProperty('eventState', EventState)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('reliabilityEvaluationInhibit', Boolean)
]
@ -1280,9 +1280,9 @@ class CharacterStringValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1319,9 +1319,9 @@ class CredentialDataInputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('reliabilityEvaluationInhibit', Boolean)
]
@ -1455,9 +1455,9 @@ class EventEnrollmentObject(Object):
, ReadableProperty('eventEnable', EventTransitionBits)
, ReadableProperty('ackedTransitions', EventTransitionBits)
, ReadableProperty('notificationClass', Unsigned)
, ReadableProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, ReadableProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1506,9 +1506,9 @@ class EventLogObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1552,9 +1552,9 @@ class GlobalGroupObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1596,9 +1596,9 @@ class IntegerValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1633,9 +1633,9 @@ class LargeAnalogValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1669,9 +1669,9 @@ class LifeSafetyPointObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1709,9 +1709,9 @@ class LifeSafetyZoneObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1782,9 +1782,9 @@ class LoadControlObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1830,9 +1830,9 @@ class LoopObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1861,9 +1861,9 @@ class MultiStateInputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1893,9 +1893,9 @@ class MultiStateOutputObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1925,9 +1925,9 @@ class MultiStateValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -1953,7 +1953,6 @@ class NetworkPortObject(Object):
, ReadableProperty('apduLength', Unsigned) #388
, ReadableProperty('linkSpeed', Real) #420
, OptionalProperty('linkSpeeds', ArrayOf(Real)) #421
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp)) #130
, OptionalProperty('linkSpeedAutonegotiate', Boolean) #422
, OptionalProperty('networkInterfaceName', CharacterString) #424
, OptionalProperty('bacnetIPMode', IPMode) #408
@ -1999,9 +1998,9 @@ class NetworkPortObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits) #35
, OptionalProperty('ackedTransitions', EventTransitionBits) #0
, OptionalProperty('notifyType', NotifyType) #72
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3)) #130
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3)) #351
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3)) #352
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventState', EventState) #36
, ReadableProperty('reliabilityEvaluationInhibit', Boolean) #357
]
@ -2087,9 +2086,9 @@ class PositiveIntegerValueObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -2118,9 +2117,9 @@ class ProgramObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('reliabilityEvaluationInhibit', Boolean)
]
@ -2154,9 +2153,9 @@ class PulseConverterObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -2184,9 +2183,9 @@ class ScheduleObject(Object):
, ReadableProperty('eventState', EventState)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('reliabilityEvaluationInhibit', Boolean)
]
@ -2263,9 +2262,9 @@ class TrendLogObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)
@ -2300,9 +2299,9 @@ class TrendLogMultipleObject(Object):
, OptionalProperty('eventEnable', EventTransitionBits)
, OptionalProperty('ackedTransitions', EventTransitionBits)
, OptionalProperty('notifyType', NotifyType)
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString))
, OptionalProperty('eventTimeStamps', ArrayOf(TimeStamp, 3))
, OptionalProperty('eventMessageTexts', ArrayOf(CharacterString, 3))
, OptionalProperty('eventMessageTextsConfig', ArrayOf(CharacterString, 3))
, OptionalProperty('eventDetectionEnable', Boolean)
, OptionalProperty('eventAlgorithmInhibitRef', ObjectPropertyReference)
, OptionalProperty('eventAlgorithmInhibit', Boolean)

View File

@ -522,8 +522,8 @@ class ActiveCOVSubscriptions(Property):
current_time = TaskManager().get_time()
if _debug: ActiveCOVSubscriptions._debug(" - current_time: %r", current_time)
# start with an empty sequence
cov_subscriptions = ListOf(COVSubscription)()
# start with an empty list
cov_subscriptions = []
# loop through the subscriptions
for cov in obj._app.subscriptions():
@ -552,6 +552,10 @@ class ActiveCOVSubscriptions(Property):
)
if _debug: ActiveCOVSubscriptions._debug(" - recipient_process: %r", recipient_process)
# look for the algorithm already associated with this object
cov_detection = cov.obj_ref._app.cov_detections[cov.obj_ref]
if _debug: ActiveCOVSubscriptions._debug(" - cov_detection: %r", cov_detection)
cov_subscription = COVSubscription(
recipient=recipient_process,
monitoredPropertyReference=ObjectPropertyReference(

View File

@ -4,17 +4,23 @@
HTTPServer
"""
import os
import threading
import json
import zlib
from collections import OrderedDict
from urlparse import urlparse, parse_qs
import SocketServer
import SimpleHTTPServer
try:
from urlparse import urlparse, parse_qs
from SocketServer import ThreadingMixIn, TCPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
except ImportError:
from urllib.parse import urlparse, parse_qs
from socketserver import ThreadingMixIn, TCPServer
from http.server import SimpleHTTPRequestHandler
from bacpypes.debugging import class_debugging, ModuleLogger
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import ConfigArgumentParser
from bacpypes.core import run, deferred
@ -33,73 +39,86 @@ from bacpypes.local.device import LocalDeviceObject
_debug = 0
_log = ModuleLogger(globals())
# settings
HOST = os.getenv("HOST", "")
PORT = int(os.getenv("PORT", 8080))
# reference a simple application
this_application = None
server = None
# favorite icon
favicon = zlib.decompress(
'x\x9c\xb5\x93\xcdN\xdb@\x14\x85\x07\x95\x07\xc8\x8amYv\xc9#\xe4\x11x\x04\x96}'
'\x8c\x88\x1dl\xa0\x9b\xb6A\xa2)\x0bVTB\xa9"\xa5?*I\x16\xad"\x84d\x84DE\x93'
'\x14;v\xc01M\xe2$\x988\xb1l\x9d\xde;v\\\x03\x89TU\xea\xb5N\xe4\xb9\x9a\xef'
'\x1c\xcfO\x84X\xa0\'\x95\x12\xf4\xbb,\x9e/\n\xb1$\x84xF\xa2\x16u\xc2>WzQ\xfc'
'\xf7\xca\xad\xafo\x91T\xd2\x1ai\xe5\x1fx[\xf9\xf4\x01\xc57\xbb\xd8\xdf\xd8'
'\x00\x8d\x11\xf9\x95\x12\xda\x9a\xc3\xae\xe5_\xbdDpk\x03\xc3\xaeT\xd0\xb3\xd0'
'>?\x83Z\xfd\x86Z\xa5\x84\x1fG_\xa4\xe7\x1c^\xa9W\xbfJ\xfe\xb4\xf0\x0e^\xdb'
'\x88}0 \xafA\x0f\xa3+c&O\xbd\xf4\xc1\xf6\xb6d\x9d\xc6\x05\xdcVSz\xb0x\x1c\x10'
'\x0fo\x02\xc7\xd0\xe7\xf1%\xe5\xf3\xc78\xdb\xf9Y\x93\x1eI\x1f\xf8>\xfa\xb5'
'\x8bG<\x8dW\x0f^\x84\xd9\xee\xb5~\x8f\xe1w\xaf{\x83\x80\xb2\xbd\xe1\x10\x83'
'\x88\'\xa5\x12\xbcZ?9\x8e\xb3%\xd3\xeb`\xd4\xd2\xffdS\xb9\x96\x89!}W!\xfb\x9a'
'\xf9t\xc4f\x8aos\x92\x9dtn\xe0\xe8Z\xcc\xc8=\xec\xf7d6\x97\xa3]\xc2Q\x1b(\xec'
'd\x99_\x8dx\xd4\x15%\xce\x96\xf9\xbf\xacP\xd1:\xfc\xf1\x18\xbe\xeb\xe2\xaey'
'\x89;]\xc5\xf1\xfb<\xf3\x99\xe9\x99\xefon\xa2\xdb6\xe5\x1c\xbb^\x8b}FV\x1b'
'\x9es+\xb3\xbd\x81M\xeb\xd1\xe0^5\xf1\xbd|\xc4\xfca\xf2\xde\xf0w\x9cW\xabr.'
'\xe7\xd9\x8dFx\x0e\xa6){\x93\x8e\x85\xf1\xb5\x81\x89\xd9\x82\xa1\x9c\xc8;\xf9'
'\xe0\x0cV\xb8W\xdc\xdb\x83\xa9i\xb1O@g\xa6T*\xd3=O\xeaP\xcc(^\x17\xfb\xe4\xb3'
'Y\xc9\xb1\x17{N\xf7\xfbo\x8b\xf7\x97\x94\xe3;\xcd\xff)\xd2\xf2\xacy\xa0\x9b'
'\xd4g=\x11B\x8bT\x8e\x94Y\x08%\x12\xe2q\x99\xd4\x7f*\x84O\xfa\r\xb5\x916R'
b"x\x9c\xb5\x93\xcdN\xdb@\x14\x85\x07\x95\x07\xc8\x8amYv\xc9#\xe4\x11x\x04\x96}"
b'\x8c\x88\x1dl\xa0\x9b\xb6A\xa2)\x0bVTB\xa9"\xa5?*I\x16\xad"\x84d\x84DE\x93'
b"\x14;v\xc01M\xe2$\x988\xb1l\x9d\xde;v\\\x03\x89TU\xea\xb5N\xe4\xb9\x9a\xef"
b"\x1c\xcfO\x84X\xa0'\x95\x12\xf4\xbb,\x9e/\n\xb1$\x84xF\xa2\x16u\xc2>WzQ\xfc"
b"\xf7\xca\xad\xafo\x91T\xd2\x1ai\xe5\x1fx[\xf9\xf4\x01\xc57\xbb\xd8\xdf\xd8"
b"\x00\x8d\x11\xf9\x95\x12\xda\x9a\xc3\xae\xe5_\xbdDpk\x03\xc3\xaeT\xd0\xb3\xd0"
b">?\x83Z\xfd\x86Z\xa5\x84\x1fG_\xa4\xe7\x1c^\xa9W\xbfJ\xfe\xb4\xf0\x0e^\xdb"
b"\x88}0 \xafA\x0f\xa3+c&O\xbd\xf4\xc1\xf6\xb6d\x9d\xc6\x05\xdcVSz\xb0x\x1c\x10"
b"\x0fo\x02\xc7\xd0\xe7\xf1%\xe5\xf3\xc78\xdb\xf9Y\x93\x1eI\x1f\xf8>\xfa\xb5"
b"\x8bG<\x8dW\x0f^\x84\xd9\xee\xb5~\x8f\xe1w\xaf{\x83\x80\xb2\xbd\xe1\x10\x83"
b"\x88'\xa5\x12\xbcZ?9\x8e\xb3%\xd3\xeb`\xd4\xd2\xffdS\xb9\x96\x89!}W!\xfb\x9a"
b"\xf9t\xc4f\x8aos\x92\x9dtn\xe0\xe8Z\xcc\xc8=\xec\xf7d6\x97\xa3]\xc2Q\x1b(\xec"
b"d\x99_\x8dx\xd4\x15%\xce\x96\xf9\xbf\xacP\xd1:\xfc\xf1\x18\xbe\xeb\xe2\xaey"
b"\x89;]\xc5\xf1\xfb<\xf3\x99\xe9\x99\xefon\xa2\xdb6\xe5\x1c\xbb^\x8b}FV\x1b"
b"\x9es+\xb3\xbd\x81M\xeb\xd1\xe0^5\xf1\xbd|\xc4\xfca\xf2\xde\xf0w\x9cW\xabr."
b"\xe7\xd9\x8dFx\x0e\xa6){\x93\x8e\x85\xf1\xb5\x81\x89\xd9\x82\xa1\x9c\xc8;\xf9"
b"\xe0\x0cV\xb8W\xdc\xdb\x83\xa9i\xb1O@g\xa6T*\xd3=O\xeaP\xcc(^\x17\xfb\xe4\xb3"
b"Y\xc9\xb1\x17{N\xf7\xfbo\x8b\xf7\x97\x94\xe3;\xcd\xff)\xd2\xf2\xacy\xa0\x9b"
b"\xd4g=\x11B\x8bT\x8e\x94Y\x08%\x12\xe2q\x99\xd4\x7f*\x84O\xfa\r\xb5\x916R"
)
#
# ThreadedHTTPRequestHandler
#
@class_debugging
class ThreadedHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
@bacpypes_debugging
class ThreadedHTTPRequestHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if _debug: ThreadedHTTPRequestHandler._debug("do_GET")
if _debug:
ThreadedHTTPRequestHandler._debug("do_GET")
global favicon
# get the thread
cur_thread = threading.current_thread()
if _debug: ThreadedHTTPRequestHandler._debug(" - cur_thread: %r", cur_thread)
if _debug:
ThreadedHTTPRequestHandler._debug(" - cur_thread: %r", cur_thread)
# parse query data and params to find out what was passed
parsed_params = urlparse(self.path)
if _debug: ThreadedHTTPRequestHandler._debug(" - parsed_params: %r", parsed_params)
if _debug:
ThreadedHTTPRequestHandler._debug(" - parsed_params: %r", parsed_params)
parsed_query = parse_qs(parsed_params.query)
if _debug: ThreadedHTTPRequestHandler._debug(" - parsed_query: %r", parsed_query)
if _debug:
ThreadedHTTPRequestHandler._debug(" - parsed_query: %r", parsed_query)
# find the pieces
args = parsed_params.path.split('/')
if _debug: ThreadedHTTPRequestHandler._debug(" - args: %r", args)
args = parsed_params.path.split("/")
if _debug:
ThreadedHTTPRequestHandler._debug(" - args: %r", args)
if (args[1] == 'read'):
if args[1] == "read":
self.do_read(args[2:])
elif (args[1] == 'whois'):
elif args[1] == "whois":
self.do_whois(args[2:])
if args[1] == 'favicon.ico':
elif args[1] == "favicon.ico":
self.send_response(200)
self.send_header("Content-type", 'image/x-icon')
self.send_header("Content-type", "image/x-icon")
self.send_header("Content-Length", len(favicon))
self.end_headers()
self.wfile.write(favicon)
else:
return "'read' or 'whois' expected"
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"'read' or 'whois' expected")
def do_read(self, args):
if _debug: ThreadedHTTPRequestHandler._debug("do_read %r", args)
if _debug:
ThreadedHTTPRequestHandler._debug("do_read %r", args)
try:
addr, obj_id = args[:2]
@ -123,19 +142,20 @@ class ThreadedHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# build a request
request = ReadPropertyRequest(
objectIdentifier=obj_id,
propertyIdentifier=prop_id,
)
objectIdentifier=obj_id, propertyIdentifier=prop_id
)
request.pduDestination = Address(addr)
# look for an optional array index
if len(args) == 5:
request.propertyArrayIndex = int(args[4])
if _debug: ThreadedHTTPRequestHandler._debug(" - request: %r", request)
if _debug:
ThreadedHTTPRequestHandler._debug(" - request: %r", request)
# make an IOCB
iocb = IOCB(request)
if _debug: ThreadedHTTPRequestHandler._debug(" - iocb: %r", iocb)
if _debug:
ThreadedHTTPRequestHandler._debug(" - iocb: %r", iocb)
# give it to the application
deferred(this_application.request_io, iocb)
@ -145,20 +165,29 @@ class ThreadedHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# filter out errors and aborts
if iocb.ioError:
if _debug: ThreadedHTTPRequestHandler._debug(" - error: %r", iocb.ioError)
result = { "error": str(iocb.ioError) }
if _debug:
ThreadedHTTPRequestHandler._debug(" - error: %r", iocb.ioError)
result = {"error": str(iocb.ioError)}
else:
if _debug: ThreadedHTTPRequestHandler._debug(" - response: %r", iocb.ioResponse)
if _debug:
ThreadedHTTPRequestHandler._debug(
" - response: %r", iocb.ioResponse
)
apdu = iocb.ioResponse
# find the datatype
datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier)
if _debug: ThreadedHTTPRequestHandler._debug(" - datatype: %r", datatype)
datatype = get_datatype(
apdu.objectIdentifier[0], apdu.propertyIdentifier
)
if _debug:
ThreadedHTTPRequestHandler._debug(" - datatype: %r", datatype)
if not datatype:
raise TypeError("unknown datatype")
# special case for array parts, others are managed by cast_out
if issubclass(datatype, Array) and (apdu.propertyArrayIndex is not None):
if issubclass(datatype, Array) and (
apdu.propertyArrayIndex is not None
):
if apdu.propertyArrayIndex == 0:
datatype = Unsigned
else:
@ -167,21 +196,26 @@ class ThreadedHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# convert the value to a dict if possible
value = apdu.propertyValue.cast_out(datatype)
if hasattr(value, 'dict_contents'):
if hasattr(value, "dict_contents"):
value = value.dict_contents(as_class=OrderedDict)
if _debug: ThreadedHTTPRequestHandler._debug(" - value: %r", value)
if _debug:
ThreadedHTTPRequestHandler._debug(" - value: %r", value)
result = { "value": value }
result = {"value": value}
except Exception as err:
ThreadedHTTPRequestHandler._exception("exception: %r", err)
result = { "exception": str(err) }
result = {"exception": str(err)}
# encode the results as JSON, convert to bytes
result_bytes = json.dumps(result).encode("utf-8")
# write the result
json.dump(result, self.wfile)
self.wfile.write(result_bytes)
def do_whois(self, args):
if _debug: ThreadedHTTPRequestHandler._debug("do_whois %r", args)
if _debug:
ThreadedHTTPRequestHandler._debug("do_whois %r", args)
try:
# build a request
@ -195,11 +229,13 @@ class ThreadedHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
if len(args) == 2:
request.deviceInstanceRangeLowLimit = int(args[0])
request.deviceInstanceRangeHighLimit = int(args[1])
if _debug: ThreadedHTTPRequestHandler._debug(" - request: %r", request)
if _debug:
ThreadedHTTPRequestHandler._debug(" - request: %r", request)
# make an IOCB
iocb = IOCB(request)
if _debug: ThreadedHTTPRequestHandler._debug(" - iocb: %r", iocb)
if _debug:
ThreadedHTTPRequestHandler._debug(" - iocb: %r", iocb)
# give it to the application
this_application.request_io(iocb)
@ -209,14 +245,19 @@ class ThreadedHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
except Exception as err:
ThreadedHTTPRequestHandler._exception("exception: %r", err)
result = { "exception": str(err) }
result = {"exception": str(err)}
# encode the results as JSON, convert to bytes
result_bytes = json.dumps(result).encode("utf-8")
# write the result
json.dump(result, self.wfile)
self.wfile.write(result_bytes)
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
class ThreadedTCPServer(ThreadingMixIn, TCPServer):
pass
#
# __main__
#
@ -225,37 +266,41 @@ try:
# parse the command line arguments
parser = ConfigArgumentParser(description=__doc__)
# add an option to override the port in the config file
parser.add_argument('--port', type=int,
help="override the port in the config file to PORT",
default=9000,
)
# add an option for the server host
parser.add_argument("--host", type=str, help="server host", default=HOST)
# add an option for the server port
parser.add_argument("--port", type=int, help="server port", default=PORT)
args = parser.parse_args()
if _debug: _log.debug("initialization")
if _debug: _log.debug(" - args: %r", args)
if _debug:
_log.debug("initialization")
if _debug:
_log.debug(" - args: %r", args)
# make a device object
this_device = LocalDeviceObject(ini=args.ini)
if _debug: _log.debug(" - this_device: %r", this_device)
if _debug:
_log.debug(" - this_device: %r", this_device)
# make a simple application
this_application = BIPSimpleApplication(this_device, args.ini.address)
# local host, special port
HOST, PORT = "", int(args.port)
server = ThreadedTCPServer((HOST, PORT), ThreadedHTTPRequestHandler)
if _debug: _log.debug(" - server: %r", server)
server = ThreadedTCPServer((args.host, args.port), ThreadedHTTPRequestHandler)
if _debug:
_log.debug(" - server: %r", server)
# Start a thread with the server -- that thread will then start a thread for each request
server_thread = threading.Thread(target=server.serve_forever)
if _debug: _log.debug(" - server_thread: %r", server_thread)
if _debug:
_log.debug(" - server_thread: %r", server_thread)
# exit the server thread when the main thread terminates
server_thread.daemon = True
server_thread.start()
if _debug: _log.debug("running")
if _debug:
_log.debug("running")
run()
@ -266,4 +311,5 @@ finally:
if server:
server.shutdown()
if _debug: _log.debug("finally")
if _debug:
_log.debug("finally")

View File

@ -135,6 +135,9 @@ def main():
global this_application
ConsoleLogHandler('bacpypes.consolelogging')
# add logging early to debug argument parsers
# ConsoleLogHandler('bacpypes.consolelogging')
# parse the command line arguments
args = ConfigArgumentParser(description=__doc__).parse_args()

View File

@ -12,7 +12,7 @@ from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import ConfigArgumentParser
from bacpypes.consolecmd import ConsoleCmd
from bacpypes.core import run, enable_sleeping
from bacpypes.core import run, deferred, enable_sleeping
from bacpypes.iocb import IOCB
from bacpypes.pdu import Address, GlobalBroadcast

329
samples/WriteLightingCommand.py Executable file
View File

@ -0,0 +1,329 @@
#!/usr/bin/env python
"""
This application presents a 'console' prompt to the user asking for commands.
"""
import sys
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import ConfigArgumentParser
from bacpypes.consolecmd import ConsoleCmd
from bacpypes.core import run, deferred, enable_sleeping
from bacpypes.iocb import IOCB
from bacpypes.pdu import Address
from bacpypes.object import get_datatype
from bacpypes.apdu import (
SimpleAckPDU,
ReadPropertyRequest,
ReadPropertyACK,
WritePropertyRequest,
)
from bacpypes.primitivedata import Unsigned, ObjectIdentifier
from bacpypes.constructeddata import Array, Any
from bacpypes.basetypes import LightingCommand
from bacpypes.app import BIPSimpleApplication
from bacpypes.local.device import LocalDeviceObject
# some debugging
_debug = 0
_log = ModuleLogger(globals())
# globals
this_application = None
#
# WriteLightingConsoleCmd
#
@bacpypes_debugging
class WriteLightingConsoleCmd(ConsoleCmd):
def do_read(self, args):
"""read <addr> <objid> <prop> [ <indx> ]"""
args = args.split()
if _debug:
WriteLightingConsoleCmd._debug("do_read %r", args)
try:
addr, obj_id, prop_id = args[:3]
obj_id = ObjectIdentifier(obj_id).value
datatype = get_datatype(obj_id[0], prop_id)
if not datatype:
raise ValueError("invalid property for object type")
# build a request
request = ReadPropertyRequest(
objectIdentifier=obj_id, propertyIdentifier=prop_id
)
request.pduDestination = Address(addr)
if len(args) == 4:
request.propertyArrayIndex = int(args[3])
if _debug:
WriteLightingConsoleCmd._debug(" - request: %r", request)
# make an IOCB
iocb = IOCB(request)
if _debug:
WriteLightingConsoleCmd._debug(" - iocb: %r", iocb)
# give it to the application
deferred(this_application.request_io, iocb)
# wait for it to complete
iocb.wait()
# do something for success
if iocb.ioResponse:
apdu = iocb.ioResponse
# should be an ack
if not isinstance(apdu, ReadPropertyACK):
if _debug:
WriteLightingConsoleCmd._debug(" - not an ack")
return
# find the datatype
datatype = get_datatype(
apdu.objectIdentifier[0], apdu.propertyIdentifier
)
if _debug:
WriteLightingConsoleCmd._debug(" - datatype: %r", datatype)
if not datatype:
raise TypeError("unknown datatype")
# special case for array parts, others are managed by cast_out
if issubclass(datatype, Array) and (
apdu.propertyArrayIndex is not None
):
if apdu.propertyArrayIndex == 0:
value = apdu.propertyValue.cast_out(Unsigned)
else:
value = apdu.propertyValue.cast_out(datatype.subtype)
else:
value = apdu.propertyValue.cast_out(datatype)
if _debug:
WriteLightingConsoleCmd._debug(" - value: %r", value)
sys.stdout.write(str(value) + "\n")
if hasattr(value, "debug_contents"):
value.debug_contents(file=sys.stdout)
sys.stdout.flush()
# do something for error/reject/abort
if iocb.ioError:
sys.stdout.write(str(iocb.ioError) + "\n")
except Exception as error:
WriteLightingConsoleCmd._exception("exception: %r", error)
def do_write(self, args):
"""write <addr> <objid> <prop> <operation> [ ... ]"""
args = args.split()
if _debug:
WriteLightingConsoleCmd._debug("do_write %r", args)
try:
addr = args.pop(0)
obj_id = ObjectIdentifier(args.pop(0)).value
prop_id = args.pop(0)
if obj_id[0] != "lightingOutput":
raise ValueError("lightingOutput")
if prop_id != "lightingCommand":
raise ValueError("lightingCommand")
if not args:
raise ValueError("operation required")
value = LightingCommand()
value.operation = operation = args.pop(0)
if operation == "fadeTo":
if not args:
raise ValueError("target level required")
value.targetLevel = float(args.pop(0))
if args:
value.priority = int(args.pop(0))
if args:
value.fadeTime = int(args.pop(0))
elif operation == "rampTo":
if not args:
raise ValueError("target level required")
value.targetLevel = float(args.pop(0))
if args:
value.priority = int(args.pop(0))
if args:
value.rampRate = float(args.pop(0))
elif operation == "stepUp":
if args:
value.priority = int(args.pop(0))
if args:
value.stepIncrement = float(args.pop(0))
elif operation == "stepDown":
if args:
value.priority = int(args.pop(0))
if args:
value.stepIncrement = float(args.pop(0))
elif operation == "stepOn":
if args:
value.priority = int(args.pop(0))
if args:
value.stepIncrement = float(args.pop(0))
elif operation == "stepOff":
if args:
value.priority = int(args.pop(0))
if args:
value.stepIncrement = float(args.pop(0))
elif operation == "warn":
if args:
value.priority = int(args.pop(0))
elif operation == "warnOff":
if args:
value.priority = int(args.pop(0))
elif operation == "warnRelinquish":
if args:
value.priority = int(args.pop(0))
elif operation == "stop":
if args:
value.priority = int(args.pop(0))
else:
raise ValueError("invalid operation")
if (value.targetLevel is not None) and not (
0.0 <= value.targetLevel <= 100.0
):
raise ValueError("invalid target level (0.0..100.0)")
if (value.rampRate is not None) and not (0.0 <= value.rampRate <= 100.0):
raise ValueError("invalid ramp rate (0.0..100.0)")
if (value.stepIncrement is not None) and not (
0.1 <= value.stepIncrement <= 100.0
):
raise ValueError("invalid step increment (0.1..100.0)")
if (value.fadeTime is not None) and not (100 <= value.fadeTime <= 86400000):
raise ValueError("invalid fade time (100..86400000)")
if (value.priority is not None) and not (1 <= value.priority <= 16):
raise ValueError("invalid priority (1..16)")
if _debug:
WriteLightingConsoleCmd._debug(" - value: %r", value)
# build a request
request = WritePropertyRequest(
objectIdentifier=obj_id, propertyIdentifier=prop_id
)
request.pduDestination = Address(addr)
# save the value
request.propertyValue = Any()
try:
request.propertyValue.cast_in(value)
except Exception as error:
WriteLightingConsoleCmd._exception(
"WriteProperty cast error: %r", error
)
if _debug:
WriteLightingConsoleCmd._debug(" - request: %r", request)
# make an IOCB
iocb = IOCB(request)
if _debug:
WriteLightingConsoleCmd._debug(" - iocb: %r", iocb)
# give it to the application
deferred(this_application.request_io, iocb)
# wait for it to complete
iocb.wait()
# do something for success
if iocb.ioResponse:
# should be an ack
if not isinstance(iocb.ioResponse, SimpleAckPDU):
if _debug:
WriteLightingConsoleCmd._debug(" - not an ack")
return
sys.stdout.write("ack\n")
# do something for error/reject/abort
if iocb.ioError:
sys.stdout.write(str(iocb.ioError) + "\n")
except Exception as error:
WriteLightingConsoleCmd._exception("exception: %r", error)
def do_rtn(self, args):
"""rtn <addr> <net> ... """
args = args.split()
if _debug:
WriteLightingConsoleCmd._debug("do_rtn %r", args)
# provide the address and a list of network numbers
router_address = Address(args[0])
network_list = [int(arg) for arg in args[1:]]
# pass along to the service access point
this_application.nsap.update_router_references(
None, router_address, network_list
)
#
# __main__
#
def main():
global this_application
# parse the command line arguments
args = ConfigArgumentParser(description=__doc__).parse_args()
if _debug:
_log.debug("initialization")
if _debug:
_log.debug(" - args: %r", args)
# make a device object
this_device = LocalDeviceObject(ini=args.ini)
if _debug:
_log.debug(" - this_device: %r", this_device)
# make a simple application
this_application = BIPSimpleApplication(this_device, args.ini.address)
# make a console
this_console = WriteLightingConsoleCmd()
if _debug:
_log.debug(" - this_console: %r", this_console)
# enable sleeping will help with threads
enable_sleeping()
_log.debug("running")
run()
_log.debug("fini")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,29 @@
{
"bacpypes": {
"debug": ["__main__"],
"color": true
},
"local-device": {
"objectName": "Betelgeuse-47808",
"address": "wlp2s0:47809",
"objectIdentifier": 599,
"maxApduLengthAccepted": 1024,
"segmentationSupported": "segmentedBoth",
"maxSegmentsAccepted": 1024,
"vendorIdentifier": 15,
"foreignBBMD": "128.253.109.254",
"foreignTTL": 30
},
"redis": {
"host": "enterprise"
},
"redis-stream": "read-prop-stream",
"point-list": [
{
"key": "random1",
"address": "wlp2s0:47808",
"objectIdentifier": "analogValue:1",
"propertyIdentifier": "presentValue"
}
]
}

194
sandbox/read_property_redis.py Executable file
View File

@ -0,0 +1,194 @@
#!/usr/bin/env python
"""
Read some BACnet point values, save them as key/value JSON blobs in Redis,
and publish them to stream.
"""
import json
import redis
from time import time as _time
from collections import deque
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.consolelogging import JSONArgumentParser
from bacpypes.core import run, stop, deferred
from bacpypes.iocb import IOCB
from bacpypes.pdu import Address
from bacpypes.object import get_datatype
from bacpypes.apdu import ReadPropertyRequest
from bacpypes.primitivedata import Unsigned, ObjectIdentifier
from bacpypes.constructeddata import Array
from bacpypes.app import BIPSimpleApplication
from bacpypes.local.device import LocalDeviceObject
# some debugging
_debug = 0
_log = ModuleLogger(globals())
# globals
this_application = None
redis_connection = None
redis_stream = None
@bacpypes_debugging
class ReadPointListApplication(BIPSimpleApplication):
def __init__(self, point_list, *args):
if _debug:
ReadPointListApplication._debug("__init__ %r, %r", point_list, args)
BIPSimpleApplication.__init__(self, *args)
# turn the point list into a queue
self.point_queue = deque(point_list)
def next_request(self):
if _debug:
ReadPointListApplication._debug("next_request")
# check to see if we're done
if not self.point_queue:
if _debug:
ReadPointListApplication._debug(" - done")
stop()
return
# get the next request
point_info = self.point_queue.popleft()
if _debug:
ReadPointListApplication._debug(" - point_info: %r", point_info)
# build a request
request = ReadPropertyRequest(
destination=Address(point_info["address"]),
objectIdentifier=ObjectIdentifier(point_info["objectIdentifier"]).value,
propertyIdentifier=point_info.get("propertyIdentifier", "presentValue"),
)
if _debug:
ReadPointListApplication._debug(" - request: %r", request)
# make an IOCB
iocb = IOCB(request)
iocb.point_info = point_info
# set a callback for the response
iocb.add_callback(self.complete_request)
if _debug:
ReadPointListApplication._debug(" - iocb: %r", iocb)
# send the request
this_application.request_io(iocb)
def complete_request(self, iocb):
if _debug:
ReadPointListApplication._debug("complete_request %r", iocb)
global redis_connection, redis_stream
# point information has the key
point_info = iocb.point_info
if _debug:
ReadPointListApplication._debug(" - point_info: %r", point_info)
if iocb.ioResponse:
apdu = iocb.ioResponse
# find the datatype
datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier)
if _debug:
ReadPointListApplication._debug(" - datatype: %r", datatype)
if not datatype:
raise TypeError("unknown datatype")
# special case for array parts, others are managed by cast_out
if issubclass(datatype, Array) and (apdu.propertyArrayIndex is not None):
if apdu.propertyArrayIndex == 0:
value = apdu.propertyValue.cast_out(Unsigned)
else:
value = apdu.propertyValue.cast_out(datatype.subtype)
else:
value = apdu.propertyValue.cast_out(datatype)
if _debug:
ReadPointListApplication._debug(" - value: %r", value)
# create a blob for the data
point_data = {"timestamp": _time(), "value": value}
if iocb.ioError:
if _debug:
ReadPointListApplication._debug(" - error: %r", iocb.ioError)
# create a blob for the data
point_data = {"timestamp": _time(), "error": iocb.ioError}
# save the content as a JSON
redis_connection.set(point_info["key"], json.dumps(point_data))
# update the point info to add the key, save it in the stream
point_data["key"] = point_info["key"]
redis_connection.xadd(redis_stream, point_data)
# fire off another request
deferred(self.next_request)
def main():
global this_application, redis_connection, redis_stream
# parse the command line arguments
parser = JSONArgumentParser(description=__doc__)
if _debug:
_log.debug("initialization")
args = parser.parse_args()
if _debug:
_log.debug(" - args: %r", args)
# settings for connecting to the redis server
redis_settings = args.json["redis"]
if _debug:
_log.debug(" - redis_settings: %r", redis_settings)
# addtional settings for this application
redis_stream = args.json["redis-stream"]
if _debug:
_log.debug(" - redis_stream: %r", redis_stream)
# connect to Redis
redis_connection = redis.Redis(**redis_settings)
if _debug:
_log.debug(" - redis_connection: %r", redis_connection)
# make a device object
local_device = args.json["local-device"]
this_device = LocalDeviceObject(**local_device)
if _debug:
_log.debug(" - this_device: %r", this_device)
# get the point list
point_list = args.json["point-list"]
if _debug:
_log.debug(" - point_list: %r", point_list)
# make a simple application
this_application = ReadPointListApplication(
point_list, this_device, local_device.address
)
# fire off a request when the core has a chance
deferred(this_application.next_request)
_log.debug("running")
run()
_log.debug("fini")
if __name__ == "__main__":
main()

View File

@ -20,6 +20,7 @@ source_folder = {
(3, 5): 'py34',
(3, 6): 'py34',
(3, 7): 'py34',
(3, 8): 'py34',
}.get(version_info, None)
if not source_folder:
raise EnvironmentError("unsupported version of Python")

View File

@ -1,4 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# placeholder
"""
Test Choice
-----------
"""
import unittest
from bacpypes.basetypes import Scale
from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.primitivedata import Tag, TagList
# some debugging
_debug = 0
_log = ModuleLogger(globals())
@bacpypes_debugging
class TestScaleChoice(unittest.TestCase):
def test_scale_choice(self):
if _debug: TestScaleChoice._debug("test_scale_choice")
taglist = TagList([Tag(1, 1, 1, bytearray(b'\x00'))])
scale = Scale()
scale.decode(taglist)
self.assertDictEqual(scale.dict_contents(), {'integerScale': 0})

View File

@ -8,6 +8,7 @@ from bacpypes.debugging import bacpypes_debugging, ModuleLogger
from bacpypes.capability import Capability
from bacpypes.comm import Client, bind
from bacpypes.iocb import IOCB
from bacpypes.pdu import Address, LocalBroadcast
from bacpypes.npdu import NPDU
from bacpypes.apdu import apdu_types, APDU, SimpleAckPDU, RejectPDU, AbortPDU
@ -292,8 +293,9 @@ class ApplicationStateMachine(ApplicationIOController, StateMachine):
def send(self, apdu):
if _debug: ApplicationStateMachine._debug("send(%s) %r", self.name, apdu)
# send the apdu down the stack
self.request(apdu)
# build an IOCB to wrap the request
iocb = IOCB(apdu)
self.request_io(iocb)
def indication(self, apdu):
if _debug: ApplicationStateMachine._debug("indication(%s) %r", self.name, apdu)