rscada / libmbus

Meter-bus library and utility programs
http://www.rscada.se/libmbus
BSD 3-Clause "New" or "Revised" License
224 stars 138 forks source link

Expose file descriptor for select()-style asynchronous polling #86

Open sjlongland opened 8 years ago

sjlongland commented 8 years ago

Hi all,

I've been asked to write a comms driver for M-Bus and looking around, this seems to be the best supported library for doing so. The system we use reports data over AMQP (Advanced Message Queueing Protocol; specifically RabbitMQ). This protocol requires we send heartbeats on a regular basis, otherwise we get booted from the server.

Looking at libmbus, it looks to be a synchronous library. Now, I could whack it into a thread, get it blocking on a queue that I feed with requests, then it passes back replies.

An alternative implementation would be to take the file descriptor, then use epoll or select to wait on the serial port file descriptor/socket for data. Asynchronous frameworks like Tornado and Twisted in Python have good support for this. Then when I get told there's data waiting, I can then call the libmbus functions to do the actual reading.

In the meantime, I'm able to respond to requests without the IO loop blocking.

Has there been any thought into exposing a file descriptor for use with functions like select to enable asynchronous programming?

lategoodbye commented 8 years ago

Hi Stuart,

yes libmbus is a synchronous library in order to hide the complexity and runtime behavior from the user. I think it should be possible to implement a asynchronous interface but it would result in a lot of work and a transfer of runtime handling into the user application. So currently there are no plans for such a implementation.

Regards Stefan

sjlongland commented 8 years ago

Hi Stefan,

Indeed, I wasn't thinking of making libmbus fully asynchronous, but if it could expose the file descriptor (as I understand it, M-Bus isn't so timing-sensitive unlike Modbus/RTU) then the program can do other things while it waits on select, then on that signal, calls the mbus_receive_frame (the existing one) then that would be "good enough".

I've done similar with EDMI energy meters using pyserial and Tornado's logic to tell me that there is data on the serial port, this method works rather well. The same could be done between mbus_send_request_frame and mbus_receive_frame since that looks to be where the majority of the processing is done.

lategoodbye commented 8 years ago

Hi Stuart,

the file descriptor is stored in the mbus_handle so no need to expose it.

Please keep in mind a timecritical / synchronous part is in mbus-tcp.c and mbus-serial.c, too.