opensmarthouse / opensmarthouse-core

Eclipse Public License 2.0
7 stars 0 forks source link

Better handling of serial ports with multiple serial implementations #31

Open splatch opened 3 years ago

splatch commented 3 years ago

I am not sure if that's an issue, I would rather qualify it as request for clarification or an input towards discussion.

Currently there is no simple way for system to work with multiple serial port libraries. For example if there is a rxtx (nrjavaserial) implementation combined with ie. javacomm then created serial port connection can be handled by any of these libraries. Binding can't really know by which one as first one registered in system wins. This means that if you stop rxtx, restart binding and start rxtx back your other serial port provider will work. However, after restart situation will flip since rxtx usually starts earlier than other extensions. In quite many bindings so far people worked this around by provisioning of their own serial port handling implementations. This is far from perfect, cause an end user experience is quite awful.

I had a look on how serial handling is made and I believe we could utilize a basic strategy which uses URI scheme (it is partially used) and render multiple options. For example rxtx:/dev/ttyUSB0 and javacomm:/dev/ttyUSB0. End user could simply select a specific serial port implementation. The binding developer could assure specific implementation through additional method SerialPortIdentifier.getProvider which could return a scheme (ie. rxtx) if a specific port implementation is required. This could open a path towards implementation of a reliable serial port handling (see openhab-core issue 2119). I made an attempt to implement that. It seems to work within junit tests without any udev injections. User could then see a completely different category of port which is not bound to system but a specific USB device (based on idVendor, idProduct). I described implementation logic is OH forums: https://community.openhab.org/t/co7io-persistent-serial-port-identifier-provider-for-openhab/124223

cdjackson commented 3 years ago

I guess my question would first be - why do you want multiple serial libraries? Now I could offer an answer - and that might be to split out things like USB, and RFC2217 - currently this is embedded in nrjavaserial, and that library seems to have a few problems and (IMHO) it would be better to split them out. If they were split, then this may be required - or you could use the fact that one URI is a \dev\port\ and the other is a \rfc2217\address. I'm not completely sure why you would need two implementations of USB support?

splatch commented 3 years ago

I believe that RFC2217 is one of reasons why someone could need rxtx + other serial lib. I am aware of ie. ebus binding which requires jserialcomm due to lower latency than for rxtx. I see a risk that someone might run two of such bindings with two distinct requirements. I don't know anyone who faced similar issue, but that's other story. On other hand I understand that making multiple identifiers for the same serial port might be misleading and overwhelming. When system have multiple ports and has multiple serial libs (2 ports * 2 implementations => 4 enumerations) this might quickly turn into unmaintainable pile of options. Sticking to port number seems a rational choice, because at least that part is guaranteed to be consistent by system and uniquely identifiable. Given that vendor id and product id can clash between different devices using same serial chip this could indeed present a reliable path. Only one benefit of device identification based on USB attributes might be a fact that configuration will work when even if dongles are shifted between ports.

From implementation perspective I'd say that USB port number is actually a thing which we currently miss! The UsbSerialDiscovery is currently able to scan Linux sysfs in pursue of /dev/tty* nodes. We'll need to find a way to extract a hub and port number from path such as /sys/devices/pci0000:00/0000:00:14.0/usb3/3-11/3-11:1.0/ttyUSB0. The last chunk before teletype name is a hub and port number. Given that there might be multiple hubs over the path we'd rather need to stick to full identifier (3-11:1.0) rather than port number and interface number itself (1.0).