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:
parent
1a9f06fd51
commit
a8f29e915a
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user