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

simplify the error handling and update the API

This commit is contained in:
Joel Bender 2016-08-27 18:51:25 -04:00
parent 40a9a7892d
commit 2b00378904
2 changed files with 82 additions and 116 deletions

View File

@ -29,6 +29,7 @@ __email__ = 'joel@carrickbender.com'
from . import comm
from . import task
from . import singleton
from . import capability
#
# Link Layer Modules

View File

@ -24,6 +24,8 @@ class LocalRecordAccessFileObject(FileObject):
if 'fileAccessMethod' in kwargs:
if kwargs['fileAccessMethod'] != 'recordAccess':
raise ValueError("inconsistent file access method")
else:
kwargs['fileAccessMethod'] = 'recordAccess'
FileObject.__init__(self,
fileAccessMethod='recordAccess',
@ -34,13 +36,13 @@ class LocalRecordAccessFileObject(FileObject):
""" Return the number of records. """
raise NotImplementedError("__len__")
def read_file(self, start_record, record_count):
def read_record(self, start_record, record_count):
""" Read a number of records starting at a specific record. """
raise NotImplementedError("read_file")
raise NotImplementedError("read_record")
def write_file(self, start_record, record_count, record_data):
def write_record(self, start_record, record_count, record_data):
""" Write a number of records, starting at a specific record. """
raise NotImplementedError("write_file")
raise NotImplementedError("write_record")
#
# Local Stream Access File Object Type
@ -59,9 +61,10 @@ class LocalStreamAccessFileObject(FileObject):
if 'fileAccessMethod' in kwargs:
if kwargs['fileAccessMethod'] != 'streamAccess':
raise ValueError("inconsistent file access method")
else:
kwargs['fileAccessMethod'] = 'streamAccess'
FileObject.__init__(self,
fileAccessMethod='streamAccess',
**kwargs
)
@ -69,62 +72,55 @@ class LocalStreamAccessFileObject(FileObject):
""" Return the number of octets in the file. """
raise NotImplementedError("write_file")
def read_file(self, start_position, octet_count):
def read_stream(self, start_position, octet_count):
""" Read a chunk of data out of the file. """
raise NotImplementedError("write_file")
raise NotImplementedError("read_stream")
def write_file(self, start_position, data):
def write_stream(self, start_position, data):
""" Write a number of octets, starting at a specific offset. """
raise NotImplementedError("write_file")
raise NotImplementedError("write_stream")
#
# File Application Mixin
#
@bacpypes_debugging
class FileApplicationMixin(object):
class FileServices(Capability):
def __init__(self, *args, **kwargs):
if _debug: FileApplicationMixin._debug("__init__")
super(FileApplicationMixin, self).__init__(*args, **kwargs)
def __init__(self):
if _debug: FileServices._debug("__init__")
Capability.__init__(self)
def do_AtomicReadFileRequest(self, apdu):
"""Return one of our records."""
if _debug: FileApplicationMixin._debug("do_AtomicReadFileRequest %r", apdu)
if _debug: FileServices._debug("do_AtomicReadFileRequest %r", apdu)
if (apdu.fileIdentifier[0] != 'file'):
resp = Error(errorClass='services', errorCode='inconsistentObjectType', context=apdu)
if _debug: FileApplicationMixin._debug(" - error resp: %r", resp)
self.response(resp)
return
raise ExecutionError('services', 'inconsistentObjectType')
# get the object
obj = self.get_object_id(apdu.fileIdentifier)
if _debug: FileApplicationMixin._debug(" - object: %r", obj)
if _debug: FileServices._debug(" - object: %r", obj)
if not obj:
resp = Error(errorClass='object', errorCode='unknownObject', context=apdu)
elif apdu.accessMethod.recordAccess:
raise ExecutionError('object', 'unknownObject')
if apdu.accessMethod.recordAccess:
# check against the object
if obj.fileAccessMethod != 'recordAccess':
resp = Error(errorClass='services',
errorCode='invalidFileAccessMethod',
context=apdu
)
raise ExecutionError('services', 'invalidFileAccessMethod')
### verify start is valid - double check this (empty files?)
elif (apdu.accessMethod.recordAccess.fileStartRecord < 0) or \
if (apdu.accessMethod.recordAccess.fileStartRecord < 0) or \
(apdu.accessMethod.recordAccess.fileStartRecord >= len(obj)):
resp = Error(errorClass='services',
errorCode='invalidFileStartPosition',
context=apdu
)
else:
raise ExecutionError('services', 'invalidFileStartPosition')
# pass along to the object
end_of_file, record_data = obj.ReadFile(
end_of_file, record_data = obj.read_record(
apdu.accessMethod.recordAccess.fileStartRecord,
apdu.accessMethod.recordAccess.requestedRecordCount,
)
if _debug: FileApplicationMixin._debug(" - record_data: %r", record_data)
if _debug: FileServices._debug(" - record_data: %r", record_data)
# this is an ack
resp = AtomicReadFileACK(context=apdu,
@ -141,24 +137,19 @@ class FileApplicationMixin(object):
elif apdu.accessMethod.streamAccess:
# check against the object
if obj.fileAccessMethod != 'streamAccess':
resp = Error(errorClass='services',
errorCode='invalidFileAccessMethod',
context=apdu
)
raise ExecutionError('services', 'invalidFileAccessMethod')
### verify start is valid - double check this (empty files?)
elif (apdu.accessMethod.streamAccess.fileStartPosition < 0) or \
if (apdu.accessMethod.streamAccess.fileStartPosition < 0) or \
(apdu.accessMethod.streamAccess.fileStartPosition >= len(obj)):
resp = Error(errorClass='services',
errorCode='invalidFileStartPosition',
context=apdu
)
else:
raise ExecutionError('services', 'invalidFileStartPosition')
# pass along to the object
end_of_file, record_data = obj.ReadFile(
end_of_file, record_data = obj.read_stream(
apdu.accessMethod.streamAccess.fileStartPosition,
apdu.accessMethod.streamAccess.requestedOctetCount,
)
if _debug: FileApplicationMixin._debug(" - record_data: %r", record_data)
if _debug: FileServices._debug(" - record_data: %r", record_data)
# this is an ack
resp = AtomicReadFileACK(context=apdu,
@ -171,55 +162,41 @@ class FileApplicationMixin(object):
),
)
if _debug: FileApplicationMixin._debug(" - resp: %r", resp)
if _debug: FileServices._debug(" - resp: %r", resp)
# return the result
self.response(resp)
def do_AtomicWriteFileRequest(self, apdu):
"""Return one of our records."""
if _debug: FileApplicationMixin._debug("do_AtomicWriteFileRequest %r", apdu)
if _debug: FileServices._debug("do_AtomicWriteFileRequest %r", apdu)
if (apdu.fileIdentifier[0] != 'file'):
resp = Error(errorClass='services', errorCode='inconsistentObjectType', context=apdu)
if _debug: FileApplicationMixin._debug(" - error resp: %r", resp)
self.response(resp)
return
raise ExecutionError('services', 'inconsistentObjectType')
# get the object
obj = self.get_object_id(apdu.fileIdentifier)
if _debug: FileApplicationMixin._debug(" - object: %r", obj)
if _debug: FileServices._debug(" - object: %r", obj)
if not obj:
resp = Error(errorClass='object', errorCode='unknownObject', context=apdu)
elif apdu.accessMethod.recordAccess:
raise ExecutionError('object', 'unknownObject')
if apdu.accessMethod.recordAccess:
# check against the object
if obj.fileAccessMethod != 'recordAccess':
resp = Error(errorClass='services',
errorCode='invalidFileAccessMethod',
context=apdu
)
if _debug: FileApplicationMixin._debug(" - error resp: %r", resp)
self.response(resp)
return
raise ExecutionError('services', 'invalidFileAccessMethod')
# check for read-only
if obj.readOnly:
resp = Error(errorClass='services',
errorCode='fileAccessDenied',
context=apdu
)
if _debug: FileApplicationMixin._debug(" - error resp: %r", resp)
self.response(resp)
return
raise ExecutionError('services', 'fileAccessDenied')
# pass along to the object
start_record = obj.WriteFile(
start_record = obj.write_record(
apdu.accessMethod.recordAccess.fileStartRecord,
apdu.accessMethod.recordAccess.recordCount,
apdu.accessMethod.recordAccess.fileRecordData,
)
if _debug: FileApplicationMixin._debug(" - start_record: %r", start_record)
if _debug: FileServices._debug(" - start_record: %r", start_record)
# this is an ack
resp = AtomicWriteFileACK(context=apdu,
@ -229,37 +206,25 @@ class FileApplicationMixin(object):
elif apdu.accessMethod.streamAccess:
# check against the object
if obj.fileAccessMethod != 'streamAccess':
resp = Error(errorClass='services',
errorCode='invalidFileAccessMethod',
context=apdu
)
if _debug: FileApplicationMixin._debug(" - error resp: %r", resp)
self.response(resp)
return
raise ExecutionError('services', 'invalidFileAccessMethod')
# check for read-only
if obj.readOnly:
resp = Error(errorClass='services',
errorCode='fileAccessDenied',
context=apdu
)
if _debug: FileApplicationMixin._debug(" - error resp: %r", resp)
self.response(resp)
return
raise ExecutionError('services', 'fileAccessDenied')
# pass along to the object
start_position = obj.WriteFile(
start_position = obj.write_stream(
apdu.accessMethod.streamAccess.fileStartPosition,
apdu.accessMethod.streamAccess.fileData,
)
if _debug: FileApplicationMixin._debug(" - start_position: %r", start_position)
if _debug: FileServices._debug(" - start_position: %r", start_position)
# this is an ack
resp = AtomicWriteFileACK(context=apdu,
fileStartPosition=start_position,
)
if _debug: FileApplicationMixin._debug(" - resp: %r", resp)
if _debug: FileServices._debug(" - resp: %r", resp)
# return the result
self.response(resp)