Skip to content

Commit

Permalink
LocalDeviceObject shuffling, automatic protocolServicesSupported
Browse files Browse the repository at this point in the history
  • Loading branch information
JoelBender committed Feb 24, 2018
1 parent b700b09 commit c25b086
Show file tree
Hide file tree
Showing 50 changed files with 61 additions and 537 deletions.
2 changes: 2 additions & 0 deletions py27/bacpypes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@

from . import app
from . import appservice

from . import local
from . import service

#
Expand Down
122 changes: 1 addition & 121 deletions py27/bacpypes/service/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,136 +4,16 @@
from ..capability import Capability

from ..pdu import GlobalBroadcast
from ..primitivedata import Date, Time, ObjectIdentifier
from ..constructeddata import ArrayOf

from ..apdu import WhoIsRequest, IAmRequest, IHaveRequest, SimpleAckPDU, Error
from ..apdu import WhoIsRequest, IAmRequest, IHaveRequest, SimpleAckPDU
from ..errors import ExecutionError, InconsistentParameters, \
MissingRequiredParameter, ParameterOutOfRange
from ..object import register_object_type, registered_object_types, \
Property, DeviceObject
from ..task import FunctionTask

from .object import CurrentPropertyListMixIn

# some debugging
_debug = 0
_log = ModuleLogger(globals())

#
# CurrentDateProperty
#

class CurrentDateProperty(Property):

def __init__(self, identifier):
Property.__init__(self, identifier, Date, default=(), optional=True, mutable=False)

def ReadProperty(self, obj, arrayIndex=None):
# access an array
if arrayIndex is not None:
raise TypeError("{0} is unsubscriptable".format(self.identifier))

# get the value
now = Date()
now.now()
return now.value

def WriteProperty(self, obj, value, arrayIndex=None, priority=None, direct=False):
raise ExecutionError(errorClass='property', errorCode='writeAccessDenied')

#
# CurrentTimeProperty
#

class CurrentTimeProperty(Property):

def __init__(self, identifier):
Property.__init__(self, identifier, Time, default=(), optional=True, mutable=False)

def ReadProperty(self, obj, arrayIndex=None):
# access an array
if arrayIndex is not None:
raise TypeError("{0} is unsubscriptable".format(self.identifier))

# get the value
now = Time()
now.now()
return now.value

def WriteProperty(self, obj, value, arrayIndex=None, priority=None, direct=False):
raise ExecutionError(errorClass='property', errorCode='writeAccessDenied')

#
# LocalDeviceObject
#

@bacpypes_debugging
class LocalDeviceObject(CurrentPropertyListMixIn, DeviceObject):

properties = \
[ CurrentTimeProperty('localTime')
, CurrentDateProperty('localDate')
]

defaultProperties = \
{ 'maxApduLengthAccepted': 1024
, 'segmentationSupported': 'segmentedBoth'
, 'maxSegmentsAccepted': 16
, 'apduSegmentTimeout': 5000
, 'apduTimeout': 3000
, 'numberOfApduRetries': 3
}

def __init__(self, **kwargs):
if _debug: LocalDeviceObject._debug("__init__ %r", kwargs)

# fill in default property values not in kwargs
for attr, value in LocalDeviceObject.defaultProperties.items():
if attr not in kwargs:
kwargs[attr] = value

for key, value in kwargs.items():
if key.startswith("_"):
setattr(self, key, value)
del kwargs[key]

# check for registration
if self.__class__ not in registered_object_types.values():
if 'vendorIdentifier' not in kwargs:
raise RuntimeError("vendorIdentifier required to auto-register the LocalDeviceObject class")
register_object_type(self.__class__, vendor_id=kwargs['vendorIdentifier'])

# check for properties this class implements
if 'localDate' in kwargs:
raise RuntimeError("localDate is provided by LocalDeviceObject and cannot be overridden")
if 'localTime' in kwargs:
raise RuntimeError("localTime is provided by LocalDeviceObject and cannot be overridden")

# the object identifier is required for the object list
if 'objectIdentifier' not in kwargs:
raise RuntimeError("objectIdentifier is required")

# coerce the object identifier
object_identifier = kwargs['objectIdentifier']
if isinstance(object_identifier, (int, long)):
object_identifier = ('device', object_identifier)

# the object list is provided
if 'objectList' in kwargs:
raise RuntimeError("objectList is provided by LocalDeviceObject and cannot be overridden")
kwargs['objectList'] = ArrayOf(ObjectIdentifier)([object_identifier])

# check for a minimum value
if kwargs['maxApduLengthAccepted'] < 50:
raise ValueError("invalid max APDU length accepted")

# dump the updated attributes
if _debug: LocalDeviceObject._debug(" - updated kwargs: %r", kwargs)

# proceed as usual
super(LocalDeviceObject, self).__init__(**kwargs)

#
# Who-Is I-Am Services
#
Expand Down
55 changes: 2 additions & 53 deletions py27/bacpypes/service/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
from ..primitivedata import Atomic, Null, Unsigned
from ..constructeddata import Any, Array, ArrayOf

from ..apdu import Error, \
from ..apdu import \
SimpleAckPDU, ReadPropertyACK, ReadPropertyMultipleACK, \
ReadAccessResult, ReadAccessResultElement, ReadAccessResultElementChoice
from ..errors import ExecutionError
from ..object import Property, Object, PropertyError
from ..object import PropertyError

# some debugging
_debug = 0
Expand All @@ -20,57 +20,6 @@
# handy reference
ArrayOfPropertyIdentifier = ArrayOf(PropertyIdentifier)

#
# CurrentPropertyList
#

@bacpypes_debugging
class CurrentPropertyList(Property):

def __init__(self):
if _debug: CurrentPropertyList._debug("__init__")
Property.__init__(self, 'propertyList', ArrayOfPropertyIdentifier, default=None, optional=True, mutable=False)

def ReadProperty(self, obj, arrayIndex=None):
if _debug: CurrentPropertyList._debug("ReadProperty %r %r", obj, arrayIndex)

# make a list of the properties that have values
property_list = [k for k, v in obj._values.items()
if v is not None
and k not in ('objectName', 'objectType', 'objectIdentifier', 'propertyList')
]
if _debug: CurrentPropertyList._debug(" - property_list: %r", property_list)

# sort the list so it's stable
property_list.sort()

# asking for the whole thing
if arrayIndex is None:
return ArrayOfPropertyIdentifier(property_list)

# asking for the length
if arrayIndex == 0:
return len(property_list)

# asking for an index
if arrayIndex > len(property_list):
raise ExecutionError(errorClass='property', errorCode='invalidArrayIndex')
return property_list[arrayIndex - 1]

def WriteProperty(self, obj, value, arrayIndex=None, priority=None, direct=False):
raise ExecutionError(errorClass='property', errorCode='writeAccessDenied')

#
# CurrentPropertyListMixIn
#

@bacpypes_debugging
class CurrentPropertyListMixIn(Object):

properties = [
CurrentPropertyList(),
]

#
# ReadProperty and WriteProperty Services
#
Expand Down
9 changes: 1 addition & 8 deletions samples/AccumulatorObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from bacpypes.object import AccumulatorObject

from bacpypes.app import BIPSimpleApplication
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject
from bacpypes.service.object import ReadWritePropertyMultipleServices

# some debugging
Expand Down Expand Up @@ -84,13 +84,6 @@ def main():
# add the additional service
this_application.add_capability(ReadWritePropertyMultipleServices)

# get the services supported
services_supported = this_application.get_services_supported()
if _debug: _log.debug(" - services_supported: %r", services_supported)

# let the device object know
this_device.protocolServicesSupported = services_supported.value

# make a random input object
accumulator = AccumulatorObject(
objectIdentifier=('accumulator', 1),
Expand Down
3 changes: 2 additions & 1 deletion samples/BBMD2VLANRouter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@

from bacpypes.app import Application
from bacpypes.appservice import StateMachineAccessPoint, ApplicationServiceAccessPoint
from bacpypes.service.device import LocalDeviceObject, WhoIsIAmServices
from bacpypes.local.device import LocalDeviceObject
from bacpypes.service.device import WhoIsIAmServices
from bacpypes.service.object import ReadWritePropertyServices

from bacpypes.primitivedata import Real
Expand Down
9 changes: 1 addition & 8 deletions samples/COVClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
SimpleAckPDU, RejectPDU, AbortPDU

from bacpypes.app import BIPSimpleApplication
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 0
Expand Down Expand Up @@ -228,13 +228,6 @@ def main():
# make a simple application
this_application = SubscribeCOVApplication(this_device, args.ini.address)

# get the services supported
services_supported = this_application.get_services_supported()
if _debug: _log.debug(" - services_supported: %r", services_supported)

# let the device object know
this_device.protocolServicesSupported = services_supported.value

# make a console
this_console = SubscribeCOVConsoleCmd()
if _debug: _log.debug(" - this_console: %r", this_console)
Expand Down
2 changes: 1 addition & 1 deletion samples/COVServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from bacpypes.app import BIPSimpleApplication
from bacpypes.object import AnalogValueObject, BinaryValueObject
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject
from bacpypes.service.cov import ChangeOfValueServices

# some debugging
Expand Down
4 changes: 2 additions & 2 deletions samples/CommandableMixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
TimeValueObject, TimePatternValueObject, ChannelObject

from bacpypes.app import BIPSimpleApplication
from bacpypes.service.object import CurrentPropertyListMixIn
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.object import CurrentPropertyListMixIn
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 0
Expand Down
9 changes: 1 addition & 8 deletions samples/DeviceCommunicationControl.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from bacpypes.apdu import DeviceCommunicationControlRequest

from bacpypes.app import BIPSimpleApplication
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 0
Expand Down Expand Up @@ -134,13 +134,6 @@ def main():
# make a simple application
this_application = BIPSimpleApplication(this_device, args.ini.address)

# get the services supported
services_supported = this_application.get_services_supported()
if _debug: _log.debug(" - services_supported: %r", services_supported)

# let the device object know
this_device.protocolServicesSupported = services_supported.value

# make a console
this_console = DCCConsoleCmd()
if _debug: _log.debug(" - this_console: %r", this_console)
Expand Down
9 changes: 1 addition & 8 deletions samples/DeviceDiscovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from bacpypes.errors import DecodingError

from bacpypes.app import BIPSimpleApplication
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 1
Expand Down Expand Up @@ -211,13 +211,6 @@ def main():
# make a simple application
this_application = DiscoveryApplication(this_device, args.ini.address)

# get the services supported
services_supported = this_application.get_services_supported()
if _debug: _log.debug(" - services_supported: %r", services_supported)

# let the device object know
this_device.protocolServicesSupported = services_supported.value

# make a console
this_console = DiscoveryConsoleCmd()
if _debug: _log.debug(" - this_console: %r", this_console)
Expand Down
9 changes: 1 addition & 8 deletions samples/DeviceDiscoveryForeign.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from bacpypes.errors import DecodingError

from bacpypes.app import BIPForeignApplication
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 1
Expand Down Expand Up @@ -215,13 +215,6 @@ def main():
int(args.ini.foreignttl),
)

# get the services supported
services_supported = this_application.get_services_supported()
if _debug: _log.debug(" - services_supported: %r", services_supported)

# let the device object know
this_device.protocolServicesSupported = services_supported.value

# make a console
this_console = DiscoveryConsoleCmd()
if _debug: _log.debug(" - this_console: %r", this_console)
Expand Down
9 changes: 1 addition & 8 deletions samples/HTTPServer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from bacpypes.app import BIPSimpleApplication
from bacpypes.object import get_object_class, get_datatype
from bacpypes.service.device import LocalDeviceObject
from bacpypes.local.device import LocalDeviceObject

# some debugging
_debug = 0
Expand Down Expand Up @@ -190,13 +190,6 @@ class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
# make a simple application
this_application = BIPSimpleApplication(this_device, args.ini.address)

# get the services supported
services_supported = this_application.get_services_supported()
if _debug: _log.debug(" - services_supported: %r", services_supported)

# let the device object know
this_device.protocolServicesSupported = services_supported.value

# local host, special port
HOST, PORT = "", int(args.port)
server = ThreadedTCPServer((HOST, PORT), ThreadedHTTPRequestHandler)
Expand Down
Loading

0 comments on commit c25b086

Please sign in to comment.