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

Proper solution for UPSes without unique serials #1273

Closed
melyux opened this issue Jan 29, 2022 · 19 comments
Closed

Proper solution for UPSes without unique serials #1273

melyux opened this issue Jan 29, 2022 · 19 comments
Labels
CyberPower (CPS) service/daemon start/stop General subject for starting and stopping NUT daemons (drivers, server, monitor); also BG/FG/Debug USB USB-duplicate-devices Track bugs and issues about monitoring several devices that seem identical to NUT or libusb
Milestone

Comments

@melyux
Copy link

melyux commented Jan 29, 2022

I've been struggling to get NUT working with two CyberPower UPSes that have no serials. As such, the ups.conf has no way to tell them apart now that usbhid-ups ignores the port = setting. I only discovered this silent ignoring of my nice differentiated symlinks when I did a lsof and found both driver instances accessing (and failing) the same UPS.

The usual solution to USB devices that are not uniquely distinguishable is to use udev rules to distinguish them in some way using their physical ports and setting a symlink to a specific port (e.g. /dev/ups_1, /dev/ups_2, etc.), which is the solution many use to great success in other cases. However, NUT seems to almost go out of its way to prevent this since the port setting is ignored. As such, I can only connect to one UPS per machine. If I try more, the two running drivers end up trying to connect to the same UPS and nothing works.

The master branch now allows setting the device = setting, but this isn't good enough since device number changes after reboots. A good solution would be if NUT can use something that's settable by udev, like the device name or the device symlink (aka "port"), since udev has the power to distinguish devices permanently. There have been many, many people over the years who have had this problem. Is there any way out of this?

@jimklimov jimklimov added CyberPower (CPS) service/daemon start/stop General subject for starting and stopping NUT daemons (drivers, server, monitor); also BG/FG/Debug USB labels Feb 10, 2022
@ntwerdochlib
Copy link

ntwerdochlib commented Apr 8, 2022

I too have run head on into this wall... I am trying to monitor 2 Tripplite Smart3000RM2U UPSs, but what I have found is that the driver, tripplite_usb in my case, bails out the second instance with the message "Duplicate driver instance detected! Terminating other driver!"

If there is not already a plan to address this somehow, I would offer to step up and look into it.

@clepple
Copy link
Member

clepple commented Aug 12, 2022

However, NUT seems to almost go out of its way to prevent this since the port setting is ignored.

NUT was written before libusb1, so there was no way to open a device in libusb0.1 by its port name.

A better solution would be for UPS vendors to provide unique serial numbers accessible over USB.

@melyux
Copy link
Author

melyux commented Aug 12, 2022

Software can't help and wish for hardware to do things. Sounds like the best solution is to update to libusb1.

@jimklimov
Copy link
Member

jimklimov commented Aug 12, 2022 via email

@jimklimov jimklimov added the USB-duplicate-devices Track bugs and issues about monitoring several devices that seem identical to NUT or libusb label Jan 2, 2023
@skl111
Copy link

skl111 commented Apr 24, 2023

Screenshot 2023-04-23 234831
I am experiencing this same issue setting up a 3d Printer farm where I use 1 UPS per printer.

I did some skulking around and I discovered this from lsusb -t

If support was added to nut to specify the Bus, Port, Port, Port until you get to the port the device is on, that would eliminate the need for the serial #.
2 of my cyberpower ups units are on Bus 4, Port, Port 1, Ports 3,1. which is a 4 port hub with only 2 connected and since I am not moving them around, their ports do not change. even after reboot.

@ntwerdochlib
Copy link

I am running a local modification that addresses this issue by allowing the code to skip devices that are already detected. I am running 2 Tripplite UPSs that do not have have serial numbers available in the USB query. I would have to check to see if I pushed these changes to a branch on github

@jimklimov
Copy link
Member

@ntwerdochlib : Cheers, I believe similar work was done in master branch, see PR #1770

@jimklimov
Copy link
Member

jimklimov commented Apr 24, 2023

@skl111 : I can't vouch for how precisely would libusb allow to specify the paths. I think it has a way to identify a "bus" and a "device" on that bus (or "port" in some documentation, with minute differences not seen in parctice on several platforms where discussion went that deep).

Either way, it does not specify a tree but two values which I believe to logically map to an USB hub (as bus) and either its physical port (should be stable) or some logical identifier it assigned to an attached device (which potentially can change due to re-plugs of stuff). Or so I thought. In the tree view above, all device numbers happen to be unique (some devices have more than one interface), but the Bus is only reported for a root hub - which has a branch of further hubs each with its port numbers starting from 1. So the bus+device ID matching as implemented in NUT now(*) should suffice.

(*) Note: there were fixes to "device" matching on the master branch this year, no official release since then yet => see #1763 and related PRs for details. On most OSes you would need a custom NUT build for now, https://github.com/networkupstools/nut/wiki/Building-NUT-for-in%E2%80%90place-upgrades-or-non%E2%80%90disruptive-tests can help with that.

@skl111
Copy link

skl111 commented Apr 28, 2023

@jimklimov thanks for the reply, lsusb uses libusb so that pr probably is accurate.
I will have to take some time to compile a build for rocky 8 and debian 9 to see how well it works until and official release.

@jimklimov
Copy link
Member

FYI: I'll be mostly offline till mid-May. Good luck on your quest!

@skl111
Copy link

skl111 commented Sep 12, 2023

I finally got around to getting this working on debian 11 and maybe I am missing something, but this does not solve the issue as it references the device # and if that device gets removed manually or by the device itself before nut can grab it, then that # increments and its no longer valid for the config. The device being CyberPower USB connected UPS's in particular.

CyberPower Device shows connected

/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    ID 1d6b:0002 Linux Foundation 2.0 root hub
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M
        ID 05e3:0610 Genesys Logic, Inc. Hub
        |__ Port 1: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics
        |__ Port 2: Dev 4, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics
            |__ Port 1: Dev 6, If 0, Class=Human Interface Device, Driver=usbfs, 1.5M
                ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
            |__ Port 2: Dev 63, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
                ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
        |__ Port 3: Dev 5, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics

after the 2nd ups disconnected and reconnected.

/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    ID 1d6b:0002 Linux Foundation 2.0 root hub
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M
        ID 05e3:0610 Genesys Logic, Inc. Hub
        |__ Port 1: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics
        |__ Port 2: Dev 4, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics
            |__ Port 1: Dev 6, If 0, Class=Human Interface Device, Driver=usbfs, 1.5M
                ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
            |__ Port 2: Dev 66, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
                ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
        |__ Port 3: Dev 5, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics

I saw this option
allow_duplicates
but based on the manual it looks like it will ignore all 7 regex options, and it works for 2 Cyberpower UPS'es when I have it added to the 2nd UPS and that stopped it from disconnecting like it did above before I added it.
If I add another CyberPower UPS, then it could get them both mixed up?

@skl111
Copy link

skl111 commented Sep 18, 2023

And update to this based on testing.
allow_duplicates looks like it obeys the bus & dev rule, as I had the dev's at ports 6 & 7 and then when I rebooted a few times the timing was off by enough difference that nut didn't catch them when they were at 6 & 7 and they kept disconnecting and reconnecting at higher numbers.

I updated the udev rule for that series via a post in a gentoo forum about this issue to include

RUN+="/sbin/upsdrvctl stop ; /sbin/upsdrvctl start"

so it looks like

ATTR{idVendor}=="0764", ATTR{idProduct}=="0501", MODE="664", GROUP="nut", RUN+="/sbin/upsdrvctl stop ; /sbin/upsdrvctl start"

After a few reboots so far they are staying at dev 6 & 7.

I think having nut-scanner scan the ports and when it finds CyberPower UPS's, to add the usb hub port # instead of the dev # so it starts trying to attach to the UPS on that port, would bypass the need for a udev rule change.

And of course include a warning about these finicky CyberPower UPSs'

:; lsusb -tv output
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
    ID 1d6b:0002 Linux Foundation 2.0 root hub
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/3p, 480M
        ID 05e3:0610 Genesys Logic, Inc. Hub
        |__ Port 1: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics
        |__ Port 2: Dev 4, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics
            |__ Port 1: Dev 6, If 0, Class=Human Interface Device, Driver=usbfs, 1.5M
                ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
            |__ Port 2: Dev 7, If 0, Class=Human Interface Device, Driver=usbfs, 1.5M
                ID 0764:0501 Cyber Power System, Inc. CP1500 AVR UPS
        |__ Port 3: Dev 5, If 0, Class=Hub, Driver=hub/4p, 480M
            ID 214b:7250 Huasheng Electronics

UPS.conf

[Ender3Pro1UPS]
        driver = "usbhid-ups"
        port = "auto"
        desc = "Ender 3 Pro 1 UPS"
        pollonly = "enabled"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "003"
        device = "006"
        ###NOTMATCHED-YET###bcdDevice = "0001"
        allow_duplicates

[Ender3Pro2UPS]
        driver = "usbhid-ups"
        port = "auto"
        desc = "Ender 3 Pro 2 UPS"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "003"
        device = "07"
        ###NOTMATCHED-YET###bcdDevice = "0001"
        allow_duplicates

@jimklimov
Copy link
Member

jimklimov commented Sep 18, 2023

Hi, just recently a PR #2054 has landed to add busport settings (also to nut-scanner discoveries) - I wonder if on your system the two UPSes would show that same bus and port (as HW topology), with possibly differing logical device numbers?

@skl111
Copy link

skl111 commented Sep 18, 2023

Hi, just recently a PR has landed to add busport settings (also to nut-scanner discoveries) - I wonder if on your system the two UPSes would show that same bus and port (as HW topology), with possibly differing logical device numbers?

Thats exactly what it does, it increments the dev numbers if it doesn't get attached to, physically the same ports.

@skl111
Copy link

skl111 commented Sep 19, 2023

I updated the local source and remvoed the udev rule modification as well as the device # and it looks to be working, I will monitor and update it if I do or do see any issues with it.

  • ups.conf
[Ender3Pro1UPS]
        driver = "usbhid-ups"
        port = "auto"
        desc = "Ender 3 Pro 1 UPS"
        pollonly = "enabled"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "003"
#rem device = "006"
        busport = "001"
        ###NOTMATCHED-YET###bcdDevice = "0001"
        allow_duplicates

[Ender3Pro2UPS]
        driver = "usbhid-ups"
        port = "auto"
        desc = "Ender 3 Pro 2 UPS"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "003"
#rem device = "007"
        busport = "002"
        ###NOTMATCHED-YET###bcdDevice = "0001"
        allow_duplicates

@jimklimov
Copy link
Member

Ok, so just for making a note - on the hub whose topology libusb reports for us, the busport values did differ here. Thanks!

@skl111
Copy link

skl111 commented Sep 19, 2023

Ok, so just for making a note - on the hub whose topology libusb reports for us, the busport values did differ here. Thanks!

Here is the nutscanner output and I am attaching a screenshot of the lsusb -tv output.
lsusb -tv 2023-09-19 040443

Scanning USB bus.
[nutdev1]
        driver = "usbhid-ups"
        port = "auto"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "003"
        device = "007"
        busport = "002"
        ###NOTMATCHED-YET###bcdDevice = "0001"
[nutdev2]
        driver = "usbhid-ups"
        port = "auto"
        vendorid = "0764"
        productid = "0501"
        product = "ST Series"
        vendor = "CPS"
        bus = "003"
        device = "006"
        busport = "001"
        ###NOTMATCHED-YET###bcdDevice = "0001"

@jimklimov
Copy link
Member

jimklimov commented Sep 30, 2023

@skl111 : Also, looking at your earlier comment:

I saw this option allow_duplicates but based on the manual it looks like it will ignore all 7 regex options

By code, I believe it should honour the regex options (if set), and just not abort the driver initialization if it has a hit but the discovered libusb device is busy - move on and find another hit. If documentation was not sufficiently clear about this, feel free to post a PR with a better understandable rephrasing - beauty is in the eyes of the beholder, I've re-read docs/man/nut_usb_addvars.txt and it seemed okay :)

@jimklimov jimklimov modified the milestones: 2.8.1, 2.8.2 Oct 31, 2023
@jimklimov jimklimov modified the milestones: 2.8.2, 2.8.3 Apr 6, 2024
@jimklimov
Copy link
Member

As of NUT v2.8.2 with PR #2221 in place, it was decided that OS enumeration dependent values are too flaky for generated and written config files to rely on.

Currently nut-scanner would not promote these into configuration by default, but would print them as comments (so end-users may choose to skip or use these values):

:; ./tools/nut-scanner/nut-scanner -U
Scanning USB bus.
[nutdev-usb1]
        driver = "usbhid-ups"
        port = "auto"
        vendorid = "0463"
        productid = "FFFF"
        product = "Ellipse ECO"
        serial = "000000000"
        vendor = "EATON"
        # bus = "003"
        # device = "005"
        # busport = "002"

# WARNING: all-same character "serial" with 9 copies of '0' (0x30) reported in some devices: nutdev-usb1

More copies of the -U argument would print these values not-commented away(-UU "unlocks" bus and busport lines, -UUU also "unlocks" the device line).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CyberPower (CPS) service/daemon start/stop General subject for starting and stopping NUT daemons (drivers, server, monitor); also BG/FG/Debug USB USB-duplicate-devices Track bugs and issues about monitoring several devices that seem identical to NUT or libusb
Projects
None yet
Development

No branches or pull requests

5 participants