nut
nut copied to clipboard
Proper solution for UPSes without unique serials
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?
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.
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.
Software can't help and wish for hardware to do things. Sounds like the best solution is to update to libusb1.
Note that port names are not guaranteed persistent (at least not on all OSes) and can change as you reboot, plug things, etc.
The libusb1 support was added over time and merged last year, but I don't think the notion of ignoring usb drivers' port parameter went away - PRs welcome!
As a twist on the situation, consider that you bought a defective product - their protocol provides for a serial number but does not provide one uniquely per device. It is important for your use case. Do nag them, do post requests to fix the firmware!
On Fri, Aug 12, 2022, 20:54 melyux @.***> wrote:
Software can't help and wish for hardware to do things. Sounds like the best solution is to update to libusb1.
— Reply to this email directly, view it on GitHub https://github.com/networkupstools/nut/issues/1273#issuecomment-1213423060, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAMPTFA3D5FL4K3G6JIRIU3VY2MYFANCNFSM5NDHQH5Q . You are receiving this because you are subscribed to this thread.Message ID: @.***>
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.
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
@ntwerdochlib : Cheers, I believe similar work was done in master branch, see PR #1770
@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.
@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.
FYI: I'll be mostly offline till mid-May. Good luck on your quest!
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?
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
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?
Hi, just recently a PR has landed to add
busport
settings (also tonut-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.
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
Ok, so just for making a note - on the hub whose topology libusb reports for us, the busport
values did differ here. Thanks!
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.
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"
@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 :)