mirror of
https://github.com/JoelBender/bacpypes
synced 2025-09-28 22:15:23 +08:00
Merge branch 'patch-6' of https://github.com/tjohnsonhvac/bacpypes into tjohnsonhvac-patch-6
This commit is contained in:
commit
8ebd58727d
|
@ -1730,7 +1730,8 @@ class AccessRule(Sequence):
|
|||
]
|
||||
|
||||
class AccessThreatLevel(Unsigned):
|
||||
pass
|
||||
_low_limit = 0
|
||||
_high_limit = 100
|
||||
|
||||
class AccumulatorRecord(Sequence):
|
||||
sequenceElements = \
|
||||
|
|
|
@ -594,8 +594,10 @@ class Boolean(Atomic):
|
|||
class Unsigned(Atomic):
|
||||
|
||||
_app_tag = Tag.unsignedAppTag
|
||||
_low_limit = 0
|
||||
_high_limit = None
|
||||
|
||||
def __init__(self,arg = None):
|
||||
def __init__(self, arg=None):
|
||||
self.value = 0L
|
||||
|
||||
if arg is None:
|
||||
|
@ -603,14 +605,16 @@ class Unsigned(Atomic):
|
|||
elif isinstance(arg, Tag):
|
||||
self.decode(arg)
|
||||
elif isinstance(arg, int):
|
||||
if (arg < 0):
|
||||
raise ValueError("unsigned integer required")
|
||||
if not self.is_valid(arg):
|
||||
raise ValueError("value out of range")
|
||||
self.value = long(arg)
|
||||
elif isinstance(arg, long):
|
||||
if (arg < 0):
|
||||
raise ValueError("unsigned integer required")
|
||||
if not self.is_valid(arg):
|
||||
raise ValueError("value out of range")
|
||||
self.value = arg
|
||||
elif isinstance(arg, Unsigned):
|
||||
if not self.is_valid(arg.value):
|
||||
raise ValueError("value out of range")
|
||||
self.value = arg.value
|
||||
else:
|
||||
raise TypeError("invalid constructor datatype")
|
||||
|
@ -621,7 +625,7 @@ class Unsigned(Atomic):
|
|||
|
||||
# reduce the value to the smallest number of octets
|
||||
while (len(data) > 1) and (data[0] == '\x00'):
|
||||
data = data[1:]
|
||||
del data[0]
|
||||
|
||||
# encode the tag
|
||||
tag.set_app_data(Tag.unsignedAppTag, data)
|
||||
|
@ -643,10 +647,24 @@ class Unsigned(Atomic):
|
|||
@classmethod
|
||||
def is_valid(cls, arg):
|
||||
"""Return True if arg is valid value for the class."""
|
||||
return isinstance(arg, (int, long)) and (not isinstance(arg, bool)) and (arg >= 0)
|
||||
if not isinstance(arg, (int, long)) or isinstance(arg, bool):
|
||||
return False
|
||||
if (arg < cls._low_limit):
|
||||
return False
|
||||
if (cls._high_limit is not None) and (arg > cls._high_limit):
|
||||
return False
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return "Unsigned(%s)" % (self.value, )
|
||||
return "%s(%s)" % (self.__class__.__name__, self.value)
|
||||
|
||||
class Unsigned8(Unsigned):
|
||||
_low_limit = 0
|
||||
_high_limit = 255
|
||||
|
||||
class Unsigned16(Unsigned):
|
||||
_low_limit = 0
|
||||
_high_limit = 65535
|
||||
|
||||
#
|
||||
# Integer
|
||||
|
|
|
@ -1730,7 +1730,8 @@ class AccessRule(Sequence):
|
|||
]
|
||||
|
||||
class AccessThreatLevel(Unsigned):
|
||||
pass
|
||||
_low_limit = 0
|
||||
_high_limit = 100
|
||||
|
||||
class AccumulatorRecord(Sequence):
|
||||
sequenceElements = \
|
||||
|
|
|
@ -598,8 +598,10 @@ class Boolean(Atomic):
|
|||
class Unsigned(Atomic):
|
||||
|
||||
_app_tag = Tag.unsignedAppTag
|
||||
_low_limit = 0
|
||||
_high_limit = None
|
||||
|
||||
def __init__(self,arg = None):
|
||||
def __init__(self, arg=None):
|
||||
self.value = 0L
|
||||
|
||||
if arg is None:
|
||||
|
@ -607,14 +609,16 @@ class Unsigned(Atomic):
|
|||
elif isinstance(arg, Tag):
|
||||
self.decode(arg)
|
||||
elif isinstance(arg, int):
|
||||
if (arg < 0):
|
||||
raise ValueError("unsigned integer required")
|
||||
if not self.is_valid(arg):
|
||||
raise ValueError("value out of range")
|
||||
self.value = long(arg)
|
||||
elif isinstance(arg, long):
|
||||
if (arg < 0):
|
||||
raise ValueError("unsigned integer required")
|
||||
if not self.is_valid(arg):
|
||||
raise ValueError("value out of range")
|
||||
self.value = arg
|
||||
elif isinstance(arg, Unsigned):
|
||||
if not self.is_valid(arg.value):
|
||||
raise ValueError("value out of range")
|
||||
self.value = arg.value
|
||||
else:
|
||||
raise TypeError("invalid constructor datatype")
|
||||
|
@ -647,10 +651,24 @@ class Unsigned(Atomic):
|
|||
@classmethod
|
||||
def is_valid(cls, arg):
|
||||
"""Return True if arg is valid value for the class."""
|
||||
return isinstance(arg, (int, long)) and (not isinstance(arg, bool)) and (arg >= 0)
|
||||
if not isinstance(arg, (int, long)) or isinstance(arg, bool):
|
||||
return False
|
||||
if (arg < cls._low_limit):
|
||||
return False
|
||||
if (cls._high_limit is not None) and (arg > cls._high_limit):
|
||||
return False
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return "Unsigned(%s)" % (self.value, )
|
||||
return "%s(%s)" % (self.__class__.__name__, self.value)
|
||||
|
||||
class Unsigned8(Unsigned):
|
||||
_low_limit = 0
|
||||
_high_limit = 255
|
||||
|
||||
class Unsigned16(Unsigned):
|
||||
_low_limit = 0
|
||||
_high_limit = 65535
|
||||
|
||||
#
|
||||
# Integer
|
||||
|
|
|
@ -94,6 +94,7 @@ class ObjectTypesSupported(BitString):
|
|||
, 'accessUser':35
|
||||
, 'accessZone':36
|
||||
, 'credentialDataInput':37
|
||||
, 'networkPort':56
|
||||
, 'networkSecurity':38
|
||||
, 'bitstringValue':39
|
||||
, 'characterstringValue':40
|
||||
|
@ -1101,9 +1102,50 @@ class ProgramState(Enumerated):
|
|||
}
|
||||
|
||||
class PropertyIdentifier(Enumerated):
|
||||
# TODO: Sort Alphabetically
|
||||
vendor_range = (512, 4194303)
|
||||
enumerations = \
|
||||
{ 'absenteeLimit':244
|
||||
, 'tags':486
|
||||
, 'profileLocation':91
|
||||
, 'eventDetectionEnabled':353
|
||||
, 'apduLength':388
|
||||
, 'linkSpeed':420
|
||||
, 'linkSpeeds':421
|
||||
, 'linkSpeedAutonegotiate':422
|
||||
, 'networkInterfaceName':424
|
||||
, 'bacnetIPMode':408
|
||||
, 'ipAddress':400
|
||||
, 'bacnetIPUDPPort':412
|
||||
, 'ipSubnetMask':411
|
||||
, 'ipDefaultGateway':401
|
||||
, 'bacnetIPMulticastAddress':409
|
||||
, 'ipDNSServer':406
|
||||
, 'ipDHCPEnable':402
|
||||
, 'ipDHCPLeaseTime':403
|
||||
, 'ipDHCPLeaseTimeRemaining':404
|
||||
, 'ipDHCPServer':405
|
||||
, 'bacnetIPNATTraversal':410
|
||||
, 'bacnetIPGlobalAddress':407
|
||||
, 'bbmdBroadcastDistributionTable':414
|
||||
, 'bbmdAcceptFDRegistrations':413
|
||||
, 'bbmdForeignDeviceTable':415
|
||||
, 'fdBBMDAddress':418
|
||||
, 'fdSubscriptionLifetime':419
|
||||
, 'bacnetIPv6Mode':435
|
||||
, 'ipv6Address':436
|
||||
, 'ipv6PrefixLength':437
|
||||
, 'bacnetIPv6UDPPort':438
|
||||
, 'ipv6DefaultGateway':439
|
||||
, 'bacnetIPv6MulticastAddress':440
|
||||
, 'ipv6DNSServer':441
|
||||
, 'ipv6AutoAddressingEnabled':442
|
||||
, 'ipv6DHCPLeaseTime':443
|
||||
, 'ipv6DHCPLeaseTimeRemaining':444
|
||||
, 'ipv6DHCPServer':445
|
||||
, 'ipv6ZoneIndex':446
|
||||
, 'virtualMACAddressTable':429
|
||||
, 'routingTable':428
|
||||
, 'acceptedModes':175
|
||||
, 'accessAlarmEvents':245
|
||||
, 'accessDoors':246
|
||||
|
@ -1158,8 +1200,10 @@ class PropertyIdentifier(Enumerated):
|
|||
, 'bufferSize':126
|
||||
, 'changeOfStateCount':15
|
||||
, 'changeOfStateTime':16
|
||||
, 'changesPending':416
|
||||
, 'channelNumber':366
|
||||
, 'clientCovIncrement':127
|
||||
, 'command':417
|
||||
, 'configurationFiles':154
|
||||
, 'controlGroups':367
|
||||
, 'controlledVariableReference':19
|
||||
|
@ -1286,6 +1330,7 @@ class PropertyIdentifier(Enumerated):
|
|||
, 'loggingRecord':184
|
||||
, 'loggingType':197
|
||||
, 'lowLimit':59
|
||||
, 'macAddress':423
|
||||
, 'maintenanceRequired':158
|
||||
, 'manipulatedVariableReference':60
|
||||
, 'manualSlaveAddressBinding':170
|
||||
|
@ -1317,6 +1362,9 @@ class PropertyIdentifier(Enumerated):
|
|||
, 'musterPoint':287
|
||||
, 'negativeAccessRules':288
|
||||
, 'networkAccessSecurityPolicies':332
|
||||
, 'networkNumber':425
|
||||
, 'networkNumberQuality':427
|
||||
, 'networkType': 427
|
||||
, 'nodeSubtype':207
|
||||
, 'nodeType':208
|
||||
, 'notificationClass':17
|
||||
|
@ -1365,6 +1413,7 @@ class PropertyIdentifier(Enumerated):
|
|||
, 'propertyList':371
|
||||
, 'proportionalConstant':93
|
||||
, 'proportionalConstantUnits':94
|
||||
, 'protocolLevel':482
|
||||
, 'protocolObjectTypesSupported':96
|
||||
, 'protocolRevision':139
|
||||
, 'protocolServicesSupported':97
|
||||
|
@ -1376,6 +1425,7 @@ class PropertyIdentifier(Enumerated):
|
|||
, 'recipientList':102
|
||||
, 'recordsSinceNotification':140
|
||||
, 'recordCount':141
|
||||
, 'referencePort':483
|
||||
, 'reliability':103
|
||||
, 'reliabilityEvaluationInhibit':357
|
||||
, 'relinquishDefault':104
|
||||
|
@ -1565,11 +1615,107 @@ class WriteStatus(Enumerated):
|
|||
, 'successful':2
|
||||
, 'failed':3
|
||||
}
|
||||
class NetworkType(Enumerated):
|
||||
enumerations = \
|
||||
{ 'ethernet':0
|
||||
, 'arcnet':1
|
||||
, 'mstp':2
|
||||
, 'ptp':3
|
||||
, 'lontalk':4
|
||||
, 'ipv4':5
|
||||
, 'zigbee':6
|
||||
, 'virtual': 7
|
||||
# , 'non-bacnet': 8 Removed in Version 1, Revision 18
|
||||
, 'ipv6':9
|
||||
, 'serial':10
|
||||
}
|
||||
|
||||
class ProtocolLevel(Enumerated):
|
||||
enumerations = \
|
||||
{ 'physical':0
|
||||
, 'protocol':1
|
||||
, 'bacnetApplication':2
|
||||
, 'nonBacnetApplication':3
|
||||
}
|
||||
|
||||
class NetworkNumberQuality(Enumerated):
|
||||
enumerations = \
|
||||
{ 'unknown':0
|
||||
, 'learned':1
|
||||
, 'learnedConfigured':2
|
||||
, 'configured':3
|
||||
}
|
||||
|
||||
class NetworkPortCommand(Enumerated):
|
||||
enumerations = \
|
||||
{ 'idle':0
|
||||
, 'discardChanges':1
|
||||
, 'renewFdDRegistration':2
|
||||
, 'restartSlaveDiscovery':3
|
||||
, 'renewDHCP':4
|
||||
, 'restartAutonegotiation':5
|
||||
, 'disconnect':6
|
||||
, 'restartPort':7
|
||||
}
|
||||
|
||||
class IPMode(Enumerated):
|
||||
enumerations = \
|
||||
{ 'normal':0
|
||||
, 'foreign':1
|
||||
, 'bbmd':2
|
||||
}
|
||||
|
||||
class RouterEntryStatus(Enumerated):
|
||||
# This was defined directly in the RouterEntry Sequence in the standard, but I moved it up here because
|
||||
# I didn't see anywhere else you defined something that way.
|
||||
enumerations = \
|
||||
{ 'available':0
|
||||
, 'busy':1
|
||||
, 'disconnected':2
|
||||
}
|
||||
|
||||
#
|
||||
# Forward Sequences
|
||||
#
|
||||
|
||||
class HostNPort(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('host', HostAddress)
|
||||
, Element('port', Unsigned16)
|
||||
]
|
||||
|
||||
class BDTEntry(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('bbmdAddress', HostNPort)
|
||||
, Element('broadcastMask', OctetString) # shall be present if BACnet/IP, and absent for BACnet/IPv6
|
||||
]
|
||||
|
||||
class FDTEntry(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('bacnetIPAddress', OctetString) # the 6-octet B/IP or 18-octet B/IPv6 address of the registrant
|
||||
, Element('timeToLive', Unsigned16) # time to live in seconds at the time of registration
|
||||
, Element('remainingTimeToLive', Unsigned16) # remaining time to live in seconds, incl. grace period
|
||||
]
|
||||
|
||||
class VMACEntry(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('virtualMACAddress', OctetString) # maximum size 6 octets
|
||||
, Element('nativeMACAddress', OctetString)
|
||||
]
|
||||
|
||||
class RouterEntry(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('networkNumber', Unsigned16)
|
||||
, Element('macAddress', OctetString)
|
||||
, Element('status', RouterEntryStatus) # Defined Above
|
||||
]
|
||||
|
||||
class NameValue(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('name', CharacterString)
|
||||
, Element('value', Atomic) # IS ATOMIC CORRECT HERE? value is limited to primitive datatypes and BACnetDateTime
|
||||
]
|
||||
|
||||
class DeviceAddress(Sequence):
|
||||
sequenceElements = \
|
||||
[ Element('networkNumber', Unsigned)
|
||||
|
@ -1624,6 +1770,13 @@ class ObjectPropertyReference(Sequence):
|
|||
, Element('propertyIdentifier', PropertyIdentifier, 1)
|
||||
, Element('propertyArrayIndex', Unsigned, 2, True)
|
||||
]
|
||||
|
||||
class HostAddress(Choice):
|
||||
choiceElements = \
|
||||
[ Element('none', Null)
|
||||
, Element('ipAddress', OctetString) # 4 octets for B/IP or 16 octets for B/IPv6
|
||||
, Element('name', CharacterString) # Internet host name (see RFC 1123)
|
||||
]
|
||||
|
||||
class ProcessIdSelection(Choice):
|
||||
choiceElements = \
|
||||
|
@ -1730,7 +1883,8 @@ class AccessRule(Sequence):
|
|||
]
|
||||
|
||||
class AccessThreatLevel(Unsigned):
|
||||
pass
|
||||
_low_limit = 0
|
||||
_high_limit = 100
|
||||
|
||||
class AccumulatorRecord(Sequence):
|
||||
sequenceElements = \
|
||||
|
|
|
@ -598,8 +598,10 @@ class Boolean(Atomic):
|
|||
class Unsigned(Atomic):
|
||||
|
||||
_app_tag = Tag.unsignedAppTag
|
||||
_low_limit = 0
|
||||
_high_limit = None
|
||||
|
||||
def __init__(self,arg = None):
|
||||
def __init__(self, arg=None):
|
||||
self.value = 0
|
||||
|
||||
if arg is None:
|
||||
|
@ -607,10 +609,12 @@ class Unsigned(Atomic):
|
|||
elif isinstance(arg, Tag):
|
||||
self.decode(arg)
|
||||
elif isinstance(arg, int):
|
||||
if (arg < 0):
|
||||
raise ValueError("unsigned integer required")
|
||||
if not self.is_valid(arg):
|
||||
raise ValueError("value out of range")
|
||||
self.value = arg
|
||||
elif isinstance(arg, Unsigned):
|
||||
if not self.is_valid(arg.value):
|
||||
raise ValueError("value out of range")
|
||||
self.value = arg.value
|
||||
else:
|
||||
raise TypeError("invalid constructor datatype")
|
||||
|
@ -643,10 +647,24 @@ class Unsigned(Atomic):
|
|||
@classmethod
|
||||
def is_valid(cls, arg):
|
||||
"""Return True if arg is valid value for the class."""
|
||||
return isinstance(arg, int) and (not isinstance(arg, bool)) and (arg >= 0)
|
||||
if not isinstance(arg, int) or isinstance(arg, bool):
|
||||
return False
|
||||
if (arg < cls._low_limit):
|
||||
return False
|
||||
if (cls._high_limit is not None) and (arg > cls._high_limit):
|
||||
return False
|
||||
return True
|
||||
|
||||
def __str__(self):
|
||||
return "Unsigned(%s)" % (self.value, )
|
||||
return "%s(%s)" % (self.__class__.__name__, self.value)
|
||||
|
||||
class Unsigned8(Unsigned):
|
||||
_low_limit = 0
|
||||
_high_limit = 255
|
||||
|
||||
class Unsigned16(Unsigned):
|
||||
_low_limit = 0
|
||||
_high_limit = 65535
|
||||
|
||||
#
|
||||
# Integer
|
||||
|
|
|
@ -12,7 +12,7 @@ import unittest
|
|||
from bacpypes.debugging import bacpypes_debugging, ModuleLogger, xtob
|
||||
|
||||
from bacpypes.errors import InvalidTag
|
||||
from bacpypes.primitivedata import Unsigned, Tag
|
||||
from bacpypes.primitivedata import Unsigned, Unsigned8, Unsigned16, Tag
|
||||
|
||||
# some debugging
|
||||
_debug = 0
|
||||
|
@ -104,6 +104,22 @@ class TestUnsigned(unittest.TestCase):
|
|||
with self.assertRaises(ValueError):
|
||||
Unsigned(-1)
|
||||
|
||||
def test_unsigned8(self):
|
||||
if _debug: TestUnsigned._debug("test_unsigned8")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
Unsigned8(-1)
|
||||
with self.assertRaises(ValueError):
|
||||
Unsigned8(256)
|
||||
|
||||
def test_unsigned16(self):
|
||||
if _debug: TestUnsigned._debug("test_unsigned16")
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
Unsigned16(-1)
|
||||
with self.assertRaises(ValueError):
|
||||
Unsigned16(65536)
|
||||
|
||||
def test_unsigned_tag(self):
|
||||
if _debug: TestUnsigned._debug("test_unsigned_tag")
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user