Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving the USB plug & play function (serial-starter) #129

Closed
mpvader opened this issue Mar 15, 2017 · 56 comments
Closed

Improving the USB plug & play function (serial-starter) #129

mpvader opened this issue Mar 15, 2017 · 56 comments
Assignees

Comments

@mpvader
Copy link
Contributor

mpvader commented Mar 15, 2017

Venus supports multiple different serial protocols. The devices using those protocols can be connected to real UARTs and also via USB. There is a driver, not a kernel-driver, just a binary executable, for each different protocol, which bridges between the tty and D-Bus.

The plug & play implementation we have today is the famous serial-starter. In essence it just iterates through all possible drivers, starting them one by one against all available serial-ports: a driver will exit when it does not detect a device, and also exits when it looses the connection. This is a simple but rather crude and CPU intensive solution (by design :-)). Which is now getting in our way: by using so much CPU it limits the amount of devices that can be connected.

Note that the dbus-redflow entry in serial starter can be ignored: it is obsolete.

Dedicated ports

The CCGX and the Beaglebone-based product (named Venus GX) have a few dedicated ports: 2 x VE.Direct, and 1 x MKx (MK2/MK3/VE.Bus). Today, those VE.Direct ports are handled by serial-starter, and the MKx port is not:

  • those dedicated vedirect ports should be solved in a different way. Either letting daemontools restart the service continuously, or, more elegant and saving a bit of CPU: adapting the vedirect-interface binary to have an option to keep retrying, instead of exiting when it does not find a connected device.
  • the dedicated mk2 port is handled fine now. But for the raspberrypis it would be nice if USB connected MKx-es are also detected properly. Note that mk2-dbus already has a commandline flag to let it either keep retrying or exit, see the -e flag in the manual

USB ports

With above, the dedicated ports are out of the way, and what needs to solved then are the USB connected devices/protocols. The idea is to let udev do the work, and use the USB identifiers to filter out the two hard-identifiable, and also most used-, protocols:

  • mk3-usb device
  • vedirect-usb device (only the properly programmed variant)

any available tty ports that don't fall in above category should then be iterated over again. With three drivers: vedirect-interface, dbus-cgwacs and gps-dbus.

Also, instead of redoing the detection at every boot, it should be cached: if a certain product was connected to tty-such-and-so last time, big change that in the next boot it has remained the same. Obviously some more handling is necessary when introducing caching: devices can be disconnected while the Venus-device is switched off, or swapped, or ...

Note that the udev version in Jethro already has an advantage over the one in Danny. It lists tty's by id and by path:

root@beaglebone:/dev/serial# ls
by-id    by-path
root@beaglebone:/dev/serial# ls -al ./by-id 
drwxr-xr-x    2 root     root            60 Mar 14 07:54 .
drwxr-xr-x    4 root     root            80 Mar 14 07:54 ..
lrwxrwxrwx    1 root     root            13 Mar 14 07:54 usb-FTDI_USB-RS485_Cable_FTX14VBA-if00-port0 -> ../../ttyUSB0
root@beaglebone:/dev/serial# ls -al ./by-path
drwxr-xr-x    2 root     root            60 Mar 14 07:54 .
drwxr-xr-x    4 root     root            80 Mar 14 07:54 ..
lrwxrwxrwx    1 root     root            13 Mar 14 07:54 platform-musb-hdrc.1.auto-usb-0:1.3:1.0-port0 -> ../../ttyUSB0

There are five possible types of devices connected to USB:

1) mk2-dbus (aka vecan-dbus aka vebus_interface)

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/vecan-mk2_2.49.bb

The USB-serial converter is produced/programmed by us, and a special identifier is programmed into it. See below.

2) vedirect-interface

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/vedirect-interface_3.15.bb

The USB-serial converter is produced/programmed by us, and a special identifier is programmed into it. See below. Note that

3) dbus-cgwacs: Carlo Gavazzi energy meters on a RS485 bus

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/dbus-cgwacs_1.8.0.bb

The USB-RS485 interfaces are sold to customer by Victron, so we have some control over them. But they are not programmed with a special identifier. There are three options:

  • First version of USB-RS485 cable (purchased from FTDI)
  • Second version of USB-RS485 cable (purchased somewhere in China)
  • USB-Zigbee interface

4) gps-dbus: nmea0183 gps

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/gps-dbus_1.02.bb
https://www.victronenergy.com/live/ccgx:start#connecting_a_usb_gps

These are off-the-shelf devices, which cannot easily be recognized by their USB identifiers.

5) dbus-redflow: Redflow batteries, connected via RS485

https://github.com/victronenergy/dbus-redflow

The same type of USB-RS485 converters are used as for item 3, the dbus-cgwacs Energy Meters.

USB identifiers

1) lsusb -v on a mk3-usb

Bus 001 Device 009: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) 
Device Descriptor: 
 bLength                18 
 bDescriptorType         1 
 bcdUSB               2.00 
 bDeviceClass            0 (Defined at Interface level) 
 bDeviceSubClass         0  
 bDeviceProtocol         0  
 bMaxPacketSize0         8 
 idVendor           0x0403 Future Technology Devices International, Ltd 
 idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO) 
 bcdDevice           10.00 
 iManufacturer           1 FTDI 
 iProduct                2 MK3-USB Interface 
 iSerial                 3 HQ1639PKSJU 
 bNumConfigurations      1 
 Configuration Descriptor: 
   bLength                 9 
   bDescriptorType         2 
   wTotalLength           32 
   bNumInterfaces          1 
   bConfigurationValue     1 
   iConfiguration          0  
   bmAttributes         0x80 
     (Bus Powered) 
   MaxPower               90mA 
   Interface Descriptor: 
     bLength                 9 
     bDescriptorType         4 
     bInterfaceNumber        0 
     bAlternateSetting       0 
     bNumEndpoints           2 
     bInterfaceClass       255 Vendor Specific Class 
     bInterfaceSubClass    255 Vendor Specific Subclass 
     bInterfaceProtocol    255 Vendor Specific Protocol 
     iInterface              2 MK3-USB Interface 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x81  EP 1 IN 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x02  EP 2 OUT 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
Device Status:     0x0000 
 (Bus Powered)

2) lsusb -v on a properly programmed VE.Direct USB cable

Bus 001 Device 008: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) 
Device Descriptor: 
 bLength                18 
 bDescriptorType         1 
 bcdUSB               2.00 
 bDeviceClass            0 (Defined at Interface level) 
 bDeviceSubClass         0  
 bDeviceProtocol         0  
 bMaxPacketSize0         8 
 idVendor           0x0403 Future Technology Devices International, Ltd 
 idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO) 
 bcdDevice           10.00 
 iManufacturer           1 VictronEnergy BV 
 iProduct                2 VE Direct cable 
 iSerial                 3 VEYVK9XT 
 bNumConfigurations      1 
 Configuration Descriptor: 
   bLength                 9 
   bDescriptorType         2 
   wTotalLength           32 
   bNumInterfaces          1 
   bConfigurationValue     1 
   iConfiguration          0  
   bmAttributes         0x80 
     (Bus Powered) 
   MaxPower               90mA 
   Interface Descriptor: 
     bLength                 9 
     bDescriptorType         4 
     bInterfaceNumber        0 
     bAlternateSetting       0 
     bNumEndpoints           2 
     bInterfaceClass       255 Vendor Specific Class 
     bInterfaceSubClass    255 Vendor Specific Subclass 
     bInterfaceProtocol    255 Vendor Specific Protocol 
     iInterface              2 VE Direct cable 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x81  EP 1 IN 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x02  EP 2 OUT 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
Device Status:     0x0000 
 (Bus Powered)

3) lsusb -v on a not properly programmed VE.Direct USB cable.

During some time (months/years) we made a mistake in programming the usb-serial converter chips: the data was written to the chip, but not a proper checksum. Note that the returned info still differs from an original ftdi chip that has a proper checksum. Still the idea is to not try to detect this. It adds complexity, and the caching feature will eliminate the extra cpu usage anyway.

Bus 001 Device 010: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) 
Device Descriptor: 
 bLength                18 
 bDescriptorType         1 
 bcdUSB               2.00 
 bDeviceClass            0 (Defined at Interface level) 
 bDeviceSubClass         0  
 bDeviceProtocol         0  
 bMaxPacketSize0         8 
 idVendor           0x0403 Future Technology Devices International, Ltd 
 idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO) 
 bcdDevice           10.00 
 iManufacturer           1 FTDI 
 iProduct                2 FT232EX 
 iSerial                 0  
 bNumConfigurations      1 
 Configuration Descriptor: 
   bLength                 9 
   bDescriptorType         2 
   wTotalLength           32 
   bNumInterfaces          1 
   bConfigurationValue     1 
   iConfiguration          0  
   bmAttributes         0x80 
     (Bus Powered) 
   MaxPower               98mA 
   Interface Descriptor: 
     bLength                 9 
     bDescriptorType         4 
     bInterfaceNumber        0 
     bAlternateSetting       0 
     bNumEndpoints           2 
     bInterfaceClass       255 Vendor Specific Class 
     bInterfaceSubClass    255 Vendor Specific Subclass 
     bInterfaceProtocol    255 Vendor Specific Protocol 
     iInterface              2 FT232EX 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x81  EP 1 IN 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x02  EP 2 OUT 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
Device Status:     0x0000 
 (Bus Powered)
@mpvader
Copy link
Contributor Author

mpvader commented Mar 15, 2017

@jhofstee: pls review above before I assign it to someone. thanks.

@oldwindmill
Copy link

Above, you mention a manual for vebus
Note that mk2-dbus already has a commandline flag to let it either keep retrying or exit, see the -e flag in the manual

But the link to manual returns 404, and Mk2-dbus - h does not show this option.

@mpvader
Copy link
Contributor Author

mpvader commented Mar 16, 2017

@oldwindmill: it might be a compile option to enable that commandline flag. What platform / origin of the binary are you using? The repsonsible developer is on holiday. Perhaps @izak is able to figure this out in the meantime.

@izak
Copy link
Collaborator

izak commented Mar 16, 2017

This is the udev I use for the mk2 and mk3. It simply matches the ID_MODEL part advertised by the device and creates a symlink.

diff --git a/recipes-ve/vecan-mk2/mkx.rules b/recipes-ve/vecan-mk2/mkx.rules
new file mode 100644
index 0000000..9608970
--- /dev/null
+++ b/recipes-ve/vecan-mk2/mkx.rules
@@ -0,0 +1,5 @@
+# MK2 USB
+SUBSYSTEM=="tty", ENV{ID_MODEL}=="MK2USB_COM_Interface", MODE="0660", GROUP="dialout", SYMLINK+="ttyMK2"
+
+# MK3 USB
+SUBSYSTEM=="tty", ENV{ID_MODEL}=="MK3-USB_Interface", MODE="0660", GROUP="dialout", SYMLINK+="ttyMK3"

There is another change (in meta-victronenergy-private) to make serial-starter skip the mk2/mk3, which will also be useful here. If you want, I can also look at the rs485 (cgwacs) one, I own that piece of hardware :-)

@izak
Copy link
Collaborator

izak commented Mar 16, 2017

The changes I made, for the Rapsberry Pi, is in the internal repo, on the WIP-rpi3 branch. The relevant changes are:

b31e98 - small improvement on the way sed is used
ae74e1 - Skip mk2/mk3 devices in serial-starter.
892e55 - Add udev rule for mk2/3

Somewhere in the past -- I think I deleted that code -- I had a solution that would skip a device IF a symlink to it existed already. The idea is that serial-starter would look for some kind of indication that the device was already handled. That is a more generic solution that would automatically ignore any device handled by udev, as long as udev created a symlink as part of the job. The trouble with that solution is that there is a race condition: It is possible that serial-starter notices the new tty device before udev manages to create the symlink.

Unfortunately device creation cannot be overriden, nor can devices be renamed in udev, so a device node will always appear directly in /dev where serial-starter will find it. A possible solution is to put symlinks to all recognised usb-serial devices in a known place, and the unrecognised ones in another known place, and let serial-starter do the serial dance only for those who reach the latter.

I'm just think out loud of course.

@mpvader
Copy link
Contributor Author

mpvader commented Mar 17, 2017

@izak: you wrote:

If you want, I can also look at the rs485 (cgwacs) one, I own that piece of hardware :-)

I left that out of the list of recognizable devices (mk3-usb & vedirect-usb) on purpose. The reason not to autodetect the cgwacs/rs485 is that its too complicated to justify:

  • those USB-rs485 cables we sell are standard rs232 / rs485 cables (so no custom victron id anywhere)
  • we already have three different ones (old, new & zigbee)
  • the suppliers we buy them from might change those usb ids at any time

So, same as GPS, they'll need to be detected in the old style. But by adding a cache, it only hurts on the first boot.

@izak
Copy link
Collaborator

izak commented Mar 19, 2017

I assume the cache can be invalidated in some manner, probably by throwing it all away when an inconsistency is detected? Then it only hurts when you move/add devices.

@mpvader
Copy link
Contributor Author

mpvader commented Apr 20, 2017

@mansr: fyi I've added the Redflow to the list, now that it is not (yet) obsolete anymore.

@mansr
Copy link
Collaborator

mansr commented Apr 24, 2017

I've pushed an overhauled serial-starter script to branch mans/serial-starter. I have tested it with a VE Direct USB cable and a very old GPS receiver connected to a generic usb-serial adapter. I'm not sure what to do with mk2/mk3 devices since the script currently does not handle these at all.

@izak
Copy link
Collaborator

izak commented Apr 24, 2017

With @mpvader 's permission, I'd like to request that serial-starter detect the mk2/3 and explicitly skip it, do nothing.

My solution on the raspberry pi is to add a udev configuration stub that detects the mk3 and symlinks it to a known location, where the vecan-mk2 process finds it. As long as serial-starter leaves it alone it works perfectly. It also works because you will (or should) only ever have one mk3 device.

The alternative is to duplicate the vecan-mk2 service, stop the original (which auto-starts), then start the copy you made. This is perhaps more in the spirit of making a definite distinction between built-in hardware and usb hardware.

I'm commenting here specifically because this is one of the final blockers for a full Raspberry Pi version. Don't have a preference and will go with what you guys decide, just making some suggestions :-)

@mansr
Copy link
Collaborator

mansr commented Apr 24, 2017

Skipping those devices in serial-starter should be easy enough.

@mpvader
Copy link
Contributor Author

mpvader commented Apr 25, 2017

Is there a good reason to manage the fixed VE.Direct tty ports with the serial starter and at the same time not managing the fixed VE.Bus tty port through it?

Note that, as discussed with @mansr, the plan is to add a command line option to the VE.Direct driver, telling it to never give up. Two services with that flag in their run file can then be installed for the dedicated VE.Direct ports.

Either created by serial-starter, or perhaps more clean, in another way. Leaving serial starter to manage only the USB ports.

@mansr
Copy link
Collaborator

mansr commented Apr 25, 2017

There's certainly a case for managing all devices and services of the same type in the same place. A machine-specific config file could tell serial-starter what to do with built-in ports (fixed function, auto-probe, or ignore) while for USB devices this decision would be based on the product string.

@mpvader
Copy link
Contributor Author

mpvader commented Apr 26, 2017

Another question, @mansr did you find out what the purpose of the special treatment of GPS-es is in serial starter?

I ask because I now have a support request on system that doesn't recognize a GPS. I know there is a gps:

root@ccgx:~# stty -F /dev/ttyUSB0 4800
root@ccgx:~# cat /dev/ttyUSB0
$GPGGA,0662.000,5149.5197,N,00547.7166,E,1,08,1.2,7.4,M,47.2,M,,0000*50
$GPGSA,M,3,30,07,05,09,02,13,20,16,,,,,1.9,1.2,1.5*3C
$GPRMC,061625.000,A,5149.5197,N,00547.7166,E,0.00,274.71,260417,,,A*6A
$GPGGA,061626.000,5149.5197,N,00547.7166,E,1,08,1.2,7.4,M,47.2,M,,0000*53
$GPGSA,M,3,30,07,05,09,02,13,20,16,,,,,1.9,1.2,1.5*3C
$GPRMC,061626.000,A,5149.5197,N,00547.7166,E,0.00,274.71,260417,,,A*69

But serial-starter is not trying the gps service:

root@ccgx:~# svstat /service/* | grep USB0
/service/dbus-cgwacs.ttyUSB0: up (pid 19484) 7 seconds, normally down
/service/dbus-redflow.ttyUSB0: down 14 seconds
/service/gps-dbus.ttyUSB0: down 212596 seconds
/service/vedirect-interface.ttyUSB0: down 10 seconds

Fyi, while browsing around I found that /opt/victronenergy/gps-dbus/start-gps.sh, also touches /var/lock/gps.lock.

Above system has these locks:

root@ccgx:~# ls /var/lock
gps.lock      subsys        ttyO0.lock    ttyO2.lock    ttyUSB0.lock

@mpvader
Copy link
Contributor Author

mpvader commented Apr 26, 2017

I have an idea already: could be that the purpose is that there is to only have on gps-dbus service running at a time. See below for what happens in case multiple gps-es are plugged in and multiple services are running.

Plugging in multiple gps-es is not a promoted or normal thing to do.

@martinbosma
Copy link
Collaborator

I've tested here with two gps-es by starting the gps_dbus twice. The second service does not crash, but is connected to the dbus using a temporary name. Both services print out connected to dbus, which is the next line after the temporary dbus service name is changed to com.victronenergy.dbus.

Service 1:

root@ccgx:/opt/victronenergy/gps-dbus# ./gps_dbus -vv --dbus system -s /dev/ttyACM0 -b 4800
000.142 INF.VALUES: connected to dbus
000.156 INF.GPS: GPVTG,,T,,M,,N,,K
000.169 INF.GPS: GPGGA,002959.799,0000.0000,N,00000.0000,E,0,00,,,M,,,,0000
000.187 INF.GPS: GPGSA,A,1,,,,,,,,,,,,,,,
000.189 INF.GPS: GPGSV,1,1,00
000.191 INF.GPS: GPRMC,002959.799,V,0000.0000,N,00000.0000,E,,,060180,,

Service 2:

root@ccgx:/opt/victronenergy/gps-dbus# ./gps_dbus -vv --dbus system -s /dev/ttyUSB0 -b 9600
000.441 INF.VALUES: connected to dbus
000.446 INF.GPS: GPGGA,002956.054,,,,,0,00,,,M,0.0,M,,0000
000.456 INF.GPS: GPGSA,A,1,,,,,,,,,,,,,,,
000.509 INF.GPS: GPGSV,3,1,12,20,00,000,,10,00,000,,25,00,000,,27,00,000,
000.580 INF.GPS: GPGSV,3,2,12,22,00,000,,07,00,000,,21,00,000,,24,00,000,
000.651 INF.GPS: GPGSV,3,3,12,16,00,000,,28,00,000,,26,00,000,,29,00,000,
000.698 INF.GPS: GPRMC,002956.054,V,,,,,,,160406,,,N

@mpvader
Copy link
Contributor Author

mpvader commented Apr 26, 2017

thanks, I've updated my comment above.

@mpvader
Copy link
Contributor Author

mpvader commented Apr 26, 2017

Conclusion: in case a user plugs two gps-es in, which they shouldn't do in the first place, there is no problem in running the gps-dbus service twice:

the second service to start will get an alternative dbus name. The processes using gps data (gui, vrmlogger, modbus tcp etc), will therefore simply not see it.

@mansr
Copy link
Collaborator

mansr commented Apr 26, 2017

Does gps-dbus claim the dbus service name only once it has detected a GPS device? Otherwise there could be a problem. Suppose there is a non-GPS device on ttyUSB0 and a GPS on ttyUSB1. Then the following could happen:

  1. serial-starter speculatively starts gps-dbus on ttyUSB0, claiming the dbus service name.
  2. Before gps-dbus gives up on ttyUSB0, serial-starter starts it for ttyUSB1, which gets a different name.
  3. gps-dbus gives up on ttyUSB0, but the real one is already running on ttyUSB1 with the wrong name.

@mpvader
Copy link
Contributor Author

mpvader commented Apr 26, 2017

Gps: another reason to stop looking for gps-es once one is found could be to save detection time. But, that is only three times a few seconds, and with the new code there will be caching, recognizing vedirect USB ids, etc: also not such a strong argument to keep the gps.lock complexity in place.

@jhofstee: do you know any other reason for the gps.lock?

@martinbosma
Copy link
Collaborator

Does gps-dbus claim the dbus service name only once it has detected a GPS device?

Yes, gps-dbus needs to see valid GPS (NMEA0183) output before it is actually claiming the service name

@mansr
Copy link
Collaborator

mansr commented Apr 26, 2017

OK, in that case is seems like dropping the lock should be safe.

@izak
Copy link
Collaborator

izak commented May 15, 2017

Hi Mans,

I had a quick look at the committed code, I like it. I think there's two small things that jumps out at me:

  1. I think vecan-mk2 needs a DAEMONTOOLS_DOWN line in the recipe, if it will be managed by serial-starter in future.
  2. I'd let create_service and start_service calls take the service as parameter $1, mostly aesthetic and slightly OCD, but perhaps that's a tad cleaner?

Otherwise, +1. I love the way you delete symlinks once handled.

@mansr
Copy link
Collaborator

mansr commented May 16, 2017

I've made a few tweaks and also converted vecan-mk2. There's still a problem with daemontools trying to restart the service if its device is removed.

@mansr
Copy link
Collaborator

mansr commented May 16, 2017

And now that problem is fixed.

@izak
Copy link
Collaborator

izak commented May 17, 2017

Just loaded the 2.07~19 build serial-starter changes on my CCGX. Everything came up and is working, and this was the fastest I've ever seen the grid meter come up! It came up even before the MPPT, usually it was dead last.

There is a vedirect_interface process trying to access /dev/ttyO2 (unused on my ccgx) that restarts in a loop, which I suspect should be started with the "forever" switch. That's the only oddity I see right now.

Will build and test the Rpi version tonight.

@mansr
Copy link
Collaborator

mansr commented May 17, 2017

I've updated the branch with what is hopefully the final version. The vedirect-interface service now disables the timeout for known devices. There are also some other minor fixes and cleanups.

@mansr
Copy link
Collaborator

mansr commented May 17, 2017

Testing with a USB-connected mk3, I noticed a somewhat unrelated problem. If the device is unplugged, the mk2-dbus program doesn't exit but starts printing error messages as fast as possible. This is obviously not good, although in practice it should be uncommon for a device to be unplugged while the system is running.

@izak
Copy link
Collaborator

izak commented May 19, 2017

Feedback on the Raspberry Pi. It works with the master branch, but with the serial-starter changes the serial terminal falls over within seconds after booting. I can't for the life of me think what it might be, but I can debug it tomorrow once I have access to a screen and keyboard again. Hopefully it's something silly.

@izak
Copy link
Collaborator

izak commented May 20, 2017

Somehow the serial device /dev/ttyAMA0 -- the debug port -- is showing up as a serial port that needs to be handled and because no program is associated with that it tries the default two (gps and vedirect) which kills the debug console.

That's probably because because the rules say SUBSYSTEMS=="platform|usb-serial", ie platform is included. That's of course right, you do want to do that, just not on the debug ports.

Simplest solution might be to just skip them, although it feels cleaner to match them in the rules file and avoid creating the symlink in the first place.

I'll test my theory on the beaglebone later, but I'm pretty sure the same is going to happen.

@izak
Copy link
Collaborator

izak commented May 20, 2017

Further to the above, on the CCGX there is no dedicated debug port, and the code handles the exclusion of ttyO0 if vegetty is enabled. On the BBB and the Rpi there is a dedicated debug port that is not used for vedirect, and should always be skipped. On the BBB this is also ttyO0. It seems as if this might have to go into machine-runtime-conf, so you can specify the debug port in the bsp conf file.

@izak
Copy link
Collaborator

izak commented May 20, 2017

Here is a possible solution. It's a "simplest thing that will possibly work" sort of solution that simply ships a slightly modified udev rule per platform. For the Rpi we simply ignore all platform devices, we only have one UART and it is used as debug console. For the Beaglebone, we ignore ttyO0. The beaglebone solution is untested.

https://git.victronenergy.com/ccgx/meta-victronenergy-private/commit/486725c06de0f41c0795901513bce871269ac1db

@mpvader
Copy link
Contributor Author

mpvader commented May 20, 2017

Ok thanks @izak, up to @mansr

@mansr
Copy link
Collaborator

mansr commented May 22, 2017

I see what's going on. The ttyAMA ports are reported under the "amba" subsystem rather than "platform" like most built-in devices. The udev rule matches a "platform" subsystem higher up in the tree while the script only looks at the device itself. I have updated the script to ignore any devices with an unrecognised subsystem which should take care of this with no further changes.

@mansr
Copy link
Collaborator

mansr commented May 22, 2017

an old wish resurfaced: is it possible to temporarily disable a (vedirect) service?

This would require stopping it through daemontools and preventing serial-starter from starting it again. As the scripts look now, the equivalent of this shell command sequence ought to work:

rm -f /dev/serial-starter/$tty		# make serial-starter ignore device
svc -d /service/*.$tty			# stop any running services on $tty
# do stuff
ln -s ../$tty /dev/serial-starter/$tty	# let serial-starter pick up the device as if it had just been added

@izak
Copy link
Collaborator

izak commented May 22, 2017

We'll have to check if that is sufficient for the beaglebone. On the beaglebone I half suspect it will incorrectly attempt to start vedirect and gps on debug port /dev/ttyO0.

@mansr
Copy link
Collaborator

mansr commented May 22, 2017

It works fine on beaglebone. ttyO0 isn't listed in /etc/venus/vedirect_ports so it is ignored just like all the other unused ports.

@izak
Copy link
Collaborator

izak commented May 22, 2017

Okay, so I'll test again on the Rpi, though I don't foresee any trouble. The two most important platforms are covered then.

@izak
Copy link
Collaborator

izak commented May 22, 2017

Tested again. Specific platform was an Rpi3 with official mk3 and vedirect cables. Works as advertised. 👍 from me.

@mansr
Copy link
Collaborator

mansr commented May 25, 2017

A few more improvements today. As requested by @mpvader, the main script now exports information on which ttys might provide each function. There are also scripts to stop/start services per tty as required to perform firmware updates. Additionally, the initial startup is much faster.

@mpvader
Copy link
Contributor Author

mpvader commented Jun 8, 2017

@mansr about stop-tty.sh:

That script adds a delay of 7 seconds. Which I suppose is there since there no quicker yet trivial solution.

The 7 seconds is fine, but when having lots of possible vedirect ttys this becomes rather long. Can this be changed to feed multiple ttys to the stop script, and then do the sleep only once?

So then the call would be stop-tty.sh ttyO2 ttyO4 ttyUSB0 ttyUSB1

@mansr
Copy link
Collaborator

mansr commented Jun 8, 2017

Sure, that should be easy to do. It shouldn't be terribly hard to get rid of the delay completely either. If you're otherwise happy with it, I'll see what I can do.

@mpvader
Copy link
Contributor Author

mpvader commented Jun 8, 2017

If the 7 second delay always works its fine, but besides it being a (only small!) nuisance for the user, we also need to make sure it doesn't create a bug. Either now or in the future. Am I right that when, for example, some new service takes longer than 7 seconds to detect something, this would create a bug?

Its up to you, for me its fine if you spend a few more hours to take it out altogether, especially in case that also makes it more robust.

@mansr
Copy link
Collaborator

mansr commented Jun 8, 2017

The svc -d command should kill a running service whatever state it's in. The sleep is for the case when someone runs stop-tty.sh immediately after serial-starter has created a service and is waiting for daemontools to discover it. There is a smaller race window when the service already exists and the main loop is just about to restart it. Looking at this again, I think a bit more coordination between the scripts is called for. That will both get rid of the delay and make it more robust.

@mansr
Copy link
Collaborator

mansr commented Jun 9, 2017

I have improved the scripts to get rid of the delay and also fix a possible race.

@mpvader
Copy link
Contributor Author

mpvader commented Jun 10, 2017

great. I've added it for inclusion into the next release process.

@mpvader mpvader assigned jhofstee and unassigned mansr Jun 10, 2017
@mpvader
Copy link
Contributor Author

mpvader commented Jun 28, 2017

Was added in Venus v2.08~1

@mpvader mpvader closed this as completed Jun 28, 2017
@mpvader mpvader changed the title Improving the USB plug & play function Improving the USB plug & play function (serial-starter) Dec 27, 2017
@gio49
Copy link

gio49 commented Aug 21, 2021

Venus supporta diversi protocolli seriali. I dispositivi che utilizzano questi protocolli possono essere collegati a UART reali e anche tramite USB. C'è un driver, non un driver del kernel, solo un eseguibile binario, per ogni protocollo diverso, che fa da ponte tra il tty e il D-Bus.

L'implementazione plug & play che abbiamo oggi è il famoso serial-starter . In sostanza, si limita a scorrere tutti i possibili driver, avviandoli uno per uno contro tutte le porte seriali disponibili: un driver uscirà quando non rileva un dispositivo, ed esce anche quando perde la connessione. Questa è una soluzione semplice ma piuttosto rozza e che richiede molta CPU (in base alla progettazione :-)). Il che ora ci ostacola: l'utilizzo di così tanta CPU limita la quantità di dispositivi che possono essere collegati.

Nota che la voce dbus-redflow in serial starter può essere ignorata: è obsoleta .

Porte dedicate

Il CCGX e il prodotto basato su Beaglebone (denominato Venus GX) hanno alcune porte dedicate: 2 x VE.Direct e 1 x MKx (MK2/MK3/VE.Bus). Oggi, quelle porte VE.Direct sono gestite da serial-starter e la porta MKx non è:

  • quelle porte vedirect dedicate dovrebbero essere risolte in modo diverso. O lasciando che daemontools riavvii il servizio continuamente, o, più elegante e risparmiando un po' di CPU: adattando il binario dell'interfaccia vedirect per avere un'opzione per continuare a riprovare, invece di uscire quando non trova un dispositivo connesso.
  • la porta mk2 dedicata è gestita bene ora. Ma per il raspberrypis sarebbe bello se anche gli MKx-es collegati tramite USB venissero rilevati correttamente. Nota che mk2-dbus ha già un flag della riga di comando per consentirgli di continuare a riprovare o di uscire, vedi il flag -e nel manuale

Porte USB

Con quanto sopra, le porte dedicate sono fuori mano e ciò che deve essere risolto sono i dispositivi/protocolli collegati tramite USB. L'idea è di lasciare che udev faccia il lavoro e utilizzare gli identificatori USB per filtrare i due protocolli identificabili e anche più utilizzati:

  • dispositivo mk3-usb
  • dispositivo vedirect-usb (solo la variante opportunamente programmata)

tutte le porte tty disponibili che non rientrano nella categoria precedente dovrebbero quindi essere ripetute. Con tre driver: interfaccia vedirect, dbus-cgwacs e gps-dbus.

Inoltre, invece di ripetere il rilevamento ad ogni avvio, dovrebbe essere memorizzato nella cache: se un determinato prodotto è stato connesso a tty-tal-and-co l'ultima volta, grande cambiamento che nel prossimo avvio è rimasto lo stesso. Ovviamente è necessario un po' più di gestione quando si introduce la memorizzazione nella cache: i dispositivi possono essere disconnessi mentre il dispositivo Venus è spento, o scambiato, o ...

Nota che la versione udev in Jethro ha già un vantaggio su quella in Danny. Elenca i tty per id e per percorso:

root@beaglebone:/dev/serial# ls
by-id    by-path
root@beaglebone:/dev/serial# ls -al ./by-id 
drwxr-xr-x    2 root     root            60 Mar 14 07:54 .
drwxr-xr-x    4 root     root            80 Mar 14 07:54 ..
lrwxrwxrwx    1 root     root            13 Mar 14 07:54 usb-FTDI_USB-RS485_Cable_FTX14VBA-if00-port0 -> ../../ttyUSB0
root@beaglebone:/dev/serial# ls -al ./by-path
drwxr-xr-x    2 root     root            60 Mar 14 07:54 .
drwxr-xr-x    4 root     root            80 Mar 14 07:54 ..
lrwxrwxrwx    1 root     root            13 Mar 14 07:54 platform-musb-hdrc.1.auto-usb-0:1.3:1.0-port0 -> ../../ttyUSB0

Ci sono cinque possibili tipi di dispositivi collegati a USB:

1) mk2-dbus (alias vecan-dbus alias vebus_interface)

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/vecan-mk2_2.49.bb

Il convertitore USB-seriale è prodotto/programmato da noi e in esso è programmato un identificatore speciale. Vedi sotto.

2) interfaccia-vedirect

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/vedirect-interface_3.15.bb

Il convertitore USB-seriale è prodotto/programmato da noi e in esso è programmato un identificatore speciale. Vedi sotto. Notare che

3) dbus-cgwacs: contatori di energia Carlo Gavazzi su bus RS485

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/dbus-cgwacs_1.8.0.bb

Le interfacce USB-RS485 sono vendute al cliente da Victron, quindi abbiamo un certo controllo su di esse. Ma non sono programmati con un identificatore speciale. Ci sono tre opzioni:

  • Prima versione del cavo USB-RS485 (acquistato da FTDI)
  • Seconda versione del cavo USB-RS485 (acquistato da qualche parte in Cina)
  • Interfaccia USB-Zigbee

4) gps-dbus: nmea0183 gps

https://git.victronenergy.com/ccgx/meta-victronenergy-private/blob/master/recipes-ve/gps-dbus_1.02.bb
https://www.victronenergy.com/live/ccgx:start#connecting_a_usb_gps

Questi sono dispositivi standard, che non possono essere facilmente riconosciuti dai loro identificatori USB.

5) dbus-redflow: batterie Redflow, collegate tramite RS485

https://github.com/victronenergy/dbus-redflow

Viene utilizzato lo stesso tipo di convertitori USB-RS485 del punto 3, i contatori di energia dbus-cgwacs.

Identificatori USB

1) lsusb -v su un mk3-usb

Bus 001 Device 009: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) 
Device Descriptor: 
 bLength                18 
 bDescriptorType         1 
 bcdUSB               2.00 
 bDeviceClass            0 (Defined at Interface level) 
 bDeviceSubClass         0  
 bDeviceProtocol         0  
 bMaxPacketSize0         8 
 idVendor           0x0403 Future Technology Devices International, Ltd 
 idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO) 
 bcdDevice           10.00 
 iManufacturer           1 FTDI 
 iProduct                2 MK3-USB Interface 
 iSerial                 3 HQ1639PKSJU 
 bNumConfigurations      1 
 Configuration Descriptor: 
   bLength                 9 
   bDescriptorType         2 
   wTotalLength           32 
   bNumInterfaces          1 
   bConfigurationValue     1 
   iConfiguration          0  
   bmAttributes         0x80 
     (Bus Powered) 
   MaxPower               90mA 
   Interface Descriptor: 
     bLength                 9 
     bDescriptorType         4 
     bInterfaceNumber        0 
     bAlternateSetting       0 
     bNumEndpoints           2 
     bInterfaceClass       255 Vendor Specific Class 
     bInterfaceSubClass    255 Vendor Specific Subclass 
     bInterfaceProtocol    255 Vendor Specific Protocol 
     iInterface              2 MK3-USB Interface 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x81  EP 1 IN 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x02  EP 2 OUT 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
Device Status:     0x0000 
 (Bus Powered)

2) lsusb -v su un cavo USB VE.Direct opportunamente programmato

Bus 001 Device 008: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) 
Device Descriptor: 
 bLength                18 
 bDescriptorType         1 
 bcdUSB               2.00 
 bDeviceClass            0 (Defined at Interface level) 
 bDeviceSubClass         0  
 bDeviceProtocol         0  
 bMaxPacketSize0         8 
 idVendor           0x0403 Future Technology Devices International, Ltd 
 idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO) 
 bcdDevice           10.00 
 iManufacturer           1 VictronEnergy BV 
 iProduct                2 VE Direct cable 
 iSerial                 3 VEYVK9XT 
 bNumConfigurations      1 
 Configuration Descriptor: 
   bLength                 9 
   bDescriptorType         2 
   wTotalLength           32 
   bNumInterfaces          1 
   bConfigurationValue     1 
   iConfiguration          0  
   bmAttributes         0x80 
     (Bus Powered) 
   MaxPower               90mA 
   Interface Descriptor: 
     bLength                 9 
     bDescriptorType         4 
     bInterfaceNumber        0 
     bAlternateSetting       0 
     bNumEndpoints           2 
     bInterfaceClass       255 Vendor Specific Class 
     bInterfaceSubClass    255 Vendor Specific Subclass 
     bInterfaceProtocol    255 Vendor Specific Protocol 
     iInterface              2 VE Direct cable 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x81  EP 1 IN 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x02  EP 2 OUT 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
Device Status:     0x0000 
 (Bus Powered)

3) lsusb -v su un cavo USB VE.Direct non correttamente programmato.

Per qualche tempo (mesi/anni) abbiamo commesso un errore nella programmazione dei chip del convertitore usb-seriale: i dati sono stati scritti sul chip, ma non un vero e proprio checksum. Nota che le informazioni restituite differiscono ancora da un chip ftdi originale che ha un checksum appropriato. L'idea è comunque quella di non provare a rilevarlo. Aggiunge complessità e la funzione di memorizzazione nella cache eliminerà comunque l'utilizzo aggiuntivo della CPU.

Bus 001 Device 010: ID 0403:6015 Future Technology Devices International, Ltd Bridge(I2C/SPI/UART/FIFO) 
Device Descriptor: 
 bLength                18 
 bDescriptorType         1 
 bcdUSB               2.00 
 bDeviceClass            0 (Defined at Interface level) 
 bDeviceSubClass         0  
 bDeviceProtocol         0  
 bMaxPacketSize0         8 
 idVendor           0x0403 Future Technology Devices International, Ltd 
 idProduct          0x6015 Bridge(I2C/SPI/UART/FIFO) 
 bcdDevice           10.00 
 iManufacturer           1 FTDI 
 iProduct                2 FT232EX 
 iSerial                 0  
 bNumConfigurations      1 
 Configuration Descriptor: 
   bLength                 9 
   bDescriptorType         2 
   wTotalLength           32 
   bNumInterfaces          1 
   bConfigurationValue     1 
   iConfiguration          0  
   bmAttributes         0x80 
     (Bus Powered) 
   MaxPower               98mA 
   Interface Descriptor: 
     bLength                 9 
     bDescriptorType         4 
     bInterfaceNumber        0 
     bAlternateSetting       0 
     bNumEndpoints           2 
     bInterfaceClass       255 Vendor Specific Class 
     bInterfaceSubClass    255 Vendor Specific Subclass 
     bInterfaceProtocol    255 Vendor Specific Protocol 
     iInterface              2 FT232EX 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x81  EP 1 IN 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
     Endpoint Descriptor: 
       bLength                 7 
       bDescriptorType         5 
       bEndpointAddress     0x02  EP 2 OUT 
       bmAttributes            2 
         Transfer Type            Bulk 
         Synch Type               None 
         Usage Type               Data 
       wMaxPacketSize     0x0040  1x 64 bytes 
       bInterval               0 
Device Status:     0x0000 
 (Bus Powered)

@gio49
Copy link

gio49 commented Aug 21, 2021

hi, I have a FTDI rs485 cable, I connected it to my victron GX color control but it doesn't work to read the ET112 smart meter, how can I program the EEPROM to make it work?
thanks a lot

@mpvader
Copy link
Contributor Author

mpvader commented Aug 21, 2021

Hi, sorry, but I don’t know by heart; we don’t support that.

what you could try is ask on the Modifications section on https://community.victronenergy.com.

perhaps there someone can help. But don’t be surprised if no one can, and you’re only option is to buy such cable from us.

@mpvader
Copy link
Contributor Author

mpvader commented Aug 21, 2021

(Updated above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants