bacpypes icon indicating copy to clipboard operation
bacpypes copied to clipboard

How to stop the task loop -run() inside the method its been used

Open snehabati opened this issue 4 years ago • 5 comments

Hi Joel,

I am using core.run() function inside my cov subscription method, once my sunscription lifetime is over I just dont want to be hanging in there hence I want to stop the task loop , basically how to stop the run() menthod using any other method. Ctrl-C works now but I want to wrap this in a robot framework hence would need some method to stop the run(). Can you please help. My program looks like below. def cov_subscription(device_ip_addr,device_port,client_ip_addr,client_port,object_name,obj_instance): global this_application

# make a device object
this_device = LocalDeviceObject(
    objectName='Device',
    objectIdentifier=int(599),
    maxApduLengthAccepted=int(1024),
    segmentationSupported='segmentedBoth',
    vendorIdentifier=int(15),
    )

device_ip = device_ip_addr + ':' + device_port
client_ip = client_ip_addr + ':' + client_port
# make a simple application
this_application = SubscribeCOVApplication(this_device, client_ip)

# make a subscription context
context = SubscriptionContext(Address(device_ip), (object_name, obj_instance), False, 10)

# send the subscription when the stack is ready
deferred(this_application.send_subscription, context)

run()

snehabati avatar Sep 01 '20 14:09 snehabati

Hi Joel, I tried run_once() as well that did not execute it even once just came out of the program. While the subscription is active in this program how can we send unsubscription at some point of time? Do we have to write another application for it?

snehabati avatar Sep 02 '20 07:09 snehabati

Technically, your instance should remain on the network as long as it runs. It is a BACnet device that will interact with other devices on the BACnet network.

You should not have to start/stop the application constantly as it goes against the way BACnet works.

That said, to terminate BAC0 for example I :

from bacpypes.core import stop
# Freeing socket
try:
    self.this_application.mux.directPort.handle_close()
except:
    self.this_application.mux.broadcastPort.handle_close()

# Then I call stop
stop()

Plus all other tasks that should be stopped inside the app itself.

ChristianTremblay avatar Sep 02 '20 15:09 ChristianTremblay

ok thanks Christian for the explanation and example. As the run() never ends anytime I am not able to continue execution of my next statements in the code, there has to be some condition till when the run() will continue to execute else the stop() after a run() never works as run() has no ending in my case.

snehabati avatar Sep 02 '20 16:09 snehabati

In my case, run is using its own thread.

And I defer all traffic there. This way I keep everything clear.

Le mer. 2 sept. 2020 à 12:57, Sneha Bati [email protected] a écrit :

ok thanks Christian for the explanation and example. As the run() never ends anytime I am not able to continue execution of my next statements in the code, there has to be some condition till when the run() will continue to execute else the stop() after a run() never works as run() has no ending in my case.

— You are receiving this because you commented.

Reply to this email directly, view it on GitHub https://github.com/JoelBender/bacpypes/issues/355#issuecomment-685867111, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABQUXB3ERWB3I6U4O5LZASDSDZ2PTANCNFSM4QRYMRMQ .

ChristianTremblay avatar Sep 02 '20 17:09 ChristianTremblay

BACpypes uses IO Control Blocks (iocb module) to coordinate requests and responses, letting the application layer know when a particular request has been satisfied (in the case of a confirmed request it is when some kind of acknowledgement or error is returned, in the case of unconfirmed requests it is after the request has been sent). Check out the ControllerAndIOCB.py sample application in the tutorial directory.

There are two ways the IOCB tells the application, (1) by a callback function or (2) by event flags.

The callback can be used to chain functionality together so when one request is completed the callback can look at the results and decide what to do next. The DiscoverToDo.py sample application does this by wrapping this design pattern in a ToDoItem, supervised by a ToDoList. So a request goes out to read the object list property of the device object, then when it returns new to-do items are created to read information about each object. All this happens in a single thread.

The event flag is used like @ChristianTremblay is doing, keeping the BACpypes run() function in its own thread. The main thread creates the IOCB and "passes" it to the "core" thread and then waits for the event flag. When the IOCB has completed the event flag is set, so at that point the IOCB contains the response (or abort or error). BACpypes is not thread friendly, there are ways of reaching into objects and mucking with data structures used by the code, and it doesn't check for which thread is calling different APIs.

JoelBender avatar Sep 03 '20 03:09 JoelBender