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

separate the upstream traffic into responses and errors by PDU type, minor documentation

This commit is contained in:
Joel Bender 2016-08-30 15:03:18 -04:00
parent 1a9f06fd51
commit a8f29e915a

View File

@ -22,7 +22,9 @@ from .bvllservice import BIPSimple, BIPForeign, AnnexJCodec, UDPMultiplexer
from .object import Property, DeviceObject, \ from .object import Property, DeviceObject, \
registered_object_types, register_object_type registered_object_types, register_object_type
from .apdu import ConfirmedRequestPDU, Error from .apdu import UnconfirmedRequestPDU, ConfirmedRequestPDU, \
SimpleAckPDU, ComplexAckPDU, ErrorPDU, RejectPDU, AbortPDU, Error
from .errors import ExecutionError, UnrecognizedService, AbortException, RejectException from .errors import ExecutionError, UnrecognizedService, AbortException, RejectException
# for computing protocol services supported # for computing protocol services supported
@ -191,15 +193,24 @@ class DeviceInfoCache:
class ApplicationController(IOQController): class ApplicationController(IOQController):
def __init__(self, request_fn, address): def __init__(self, request_fn, address):
"""Initialize an application controller. To process requests it only
needs the function to call that sends an APDU down the stack, the address
parameter is to help with debugging."""
if _debug: ApplicationController._debug("__init__ %r %r", request_fn, address) if _debug: ApplicationController._debug("__init__ %r %r", request_fn, address)
IOQController.__init__(self, name=str(address)) IOQController.__init__(self, str(address))
# save a reference to the request function # save a reference to the request function
self.request_fn = request_fn self.request_fn = request_fn
self.address = address
def process_io(self, iocb): def process_io(self, iocb):
"""Called to start processing a request. This is called immediately
when the controller is idle, otherwise this is called for the next IOCB
when the current request has been satisfied."""
if _debug: ApplicationController._debug("process_io %r", iocb) if _debug: ApplicationController._debug("process_io %r", iocb)
"""Called by a client to start processing a request."""
# this is now an active request
self.active_io(iocb)
# send the request # send the request
self.request_fn(iocb.args[0]) self.request_fn(iocb.args[0])
@ -344,10 +355,20 @@ class Application(ApplicationServiceElement, Collector):
#----- #-----
def request(self, apdu): def request(self, apdu):
"""Intercept downstream requests and filter them. For unconfirmed
services the APDU is passed down the stack and None is returned. For
confirmed services an IOCB is built with the request and queued to
be sent by an application controller.
"""
if _debug: Application._debug("request %r", apdu) if _debug: Application._debug("request %r", apdu)
# the parent class request function
request_fn = super(Application, self).request
if _debug: Application._debug(" - request_fn: %r", request_fn)
if isinstance(apdu, UnconfirmedRequestPDU): if isinstance(apdu, UnconfirmedRequestPDU):
iocb = None iocb = None
request_fn(apdu)
elif isinstance(apdu, ConfirmedRequestPDU): elif isinstance(apdu, ConfirmedRequestPDU):
iocb = IOCB(apdu) iocb = IOCB(apdu)
@ -358,12 +379,12 @@ class Application(ApplicationServiceElement, Collector):
if not controller: if not controller:
if _debug: Application._debug(" - new controller") if _debug: Application._debug(" - new controller")
controller = ApplicationController( controller = ApplicationController(
super(Application, self).request, request_fn, apdu.pduDestination,
apdu.pduDestination,
) )
# keep track of the controller # keep track of the controller
self.controllers[apdu.pduDestination] = controller self.controllers[apdu.pduDestination] = controller
if _debug: Application._debug(" - controller: %r", controller)
# request this apdu # request this apdu
controller.request_io(iocb) controller.request_io(iocb)
@ -372,16 +393,25 @@ class Application(ApplicationServiceElement, Collector):
return iocb return iocb
def confirmation(self, apdu): def confirmation(self, apdu):
"""Upstream confirmations are from confirmed services that this
application has generated. The service will be the active IOCB
of the application controller."""
if _debug: Application._debug("confirmation %r", apdu) if _debug: Application._debug("confirmation %r", apdu)
# get the queue for this destination # get the queue for this destination
controller = self.controllers.get(apdu.pduSource, None) controller = self.controllers.get(apdu.pduSource, None)
if _debug: Application._debug(" - controller: %r", controller)
if not controller: if not controller:
if _debug: Application._debug(" - no queue for this source")
return return
# this request is complete # this request is complete
if isinstance(apdu, (SimpleAckPDU, ComplexAckPDU)):
controller.complete_io(controller.active_iocb, apdu) controller.complete_io(controller.active_iocb, apdu)
elif isinstance(apdu, (ErrorPDU, RejectPDU, AbortPDU)):
controller.abort_io(controller.active_iocb, apdu)
else:
raise RuntimeError("unrecognized APDU type")
if _debug: Application._debug(" - controller finished")
# if the queue is empty, forget about the controller # if the queue is empty, forget about the controller
if not controller.ioQueue.queue: if not controller.ioQueue.queue: