Package: nut-server
Version: 2.7.4-13
Severity: normal
Tags: patch

Short version:

  1. UPSONIC IRT-3K 2U speaks a variant of Q1 which omits final \r.
  2. nut 2.4 doesn't check for final \r, so it Just Works.
  3. nut 2.7 checks for final \r, cannot talk to my UPS.
  4. I fixed #3 but it's not very good.


Boring detailed version follows.

I have an "UPSONIC IRT-3K 2U" UPS.
Until September 2022, I was talking to it over USB using nut 2.4, using the 
megatec_usb driver.
This worked fine.

    root@omega:~# dpkg-query -W nut
    nut     2.4.3-1ubuntu3.2

    root@omega:~# grep -v ^# /etc/nut/ups.conf
    [upset]
    driver = megatec_usb
    port = unused

    root@omega:~# xzgrep -hF 'omega upslog [upset]: OL '  
/srv/log/syslog-20220824.xz  | tail -n1
    2022-08-24T06:45:44.154096+10:00 omega upslog [upset]: OL 87.3% charge, 
50.0% load, 18.0°C, 50.0Hz 228.0V in, 240.0V out

I upgraded the nut server to Debian 11 / nut 2.7, using the blazer_usb driver.
There, I got errors from the F\r and I\r queries:

    cyber@light:~$ sudo /lib/nut/blazer_usb -a upset -DDD
    ...
    1.169169     send: F
    1.313636     received 21 (35)
    1.313660     read: #240.0 014 72.00 50.0
    1.313668     blazer_rating: short reply
    1.313675     Rating read 3 failed
    1.313688     Rating information unavailable
    ...
    1.753885     send: I
    1.976101     received 38 (35)
    1.976125     read: #UPSONIC         IRT-3K 2U  MP001155
    1.976133     blazer_vendor: short reply
    1.976139     Vendor information read 3 failed
    1.976146     Vendor information unavailable

Using driver=nutdrv_qx, the Q1\r query also fails in the same way (short reply).

I think this is happening because, for some reason, UPSONIC omits the trailing 
\r from its responses.
I think:

    1. megatec_usb.c in nut 2.4 (omega) did not length-check anything, so all 3 
queries worked.
    2. blazer_usb.c in nut 2.7 (light) length-checks I and F but not Q1, so 
only Q1 works (thus also breaking charge percentage &c).
    3. nutdrv_qx in nut 2.7 (light) length-checks all 3 queries, so all 3 
queries fail.

I have forked the nutdrv_qx_megatec.c to a nutdrv_qx_upsonic.c and simply 
dropped the number of bytes to read by 1.
This is now working perfectly:

    cyber@light:~$ sudo ./nutdrv_qx_cyber -a upset -DDD -x protocol=upsonic -x 
subdriver=krauler -x vendorid=FFFF -x productid=0000
    Network UPS Tools - Generic Q* USB/Serial driver 0.28 (2.7.4)
    USB communication driver 0.33
       0.000000     debug level is '3'
       0.000744     upsdrv_initups...
       0.341199     Checking device (1D6B/0003) (006/001)
       0.372926     - VendorID: 1d6b
       0.372937     - ProductID: 0003
       0.372942     - Manufacturer: unknown
       0.372945     - Product: unknown
       0.372949     - Serial Number: unknown
       0.372952     - Bus: 006
       0.372955     - Device release number: 0510
       0.372959     Trying to match device
       0.372966     Device does not match - skipping
       0.372983     Checking device (1D6B/0002) (005/001)
       0.373132     - VendorID: 1d6b
       0.373153     - ProductID: 0002
       0.373162     - Manufacturer: unknown
       0.373168     - Product: unknown
       0.373175     - Serial Number: unknown
       0.373180     - Bus: 005
       0.373186     - Device release number: 0510
       0.373192     Trying to match device
       0.373201     Device does not match - skipping
       0.373217     Checking device (8087/0024) (003/002)
       0.442033     - VendorID: 8087
       0.442055     - ProductID: 0024
       0.442062     - Manufacturer: unknown
       0.442068     - Product: unknown
       0.442074     - Serial Number: unknown
       0.442079     - Bus: 003
       0.442085     - Device release number: 0000
       0.442094     Trying to match device
       0.442104     Device does not match - skipping
       0.442119     Checking device (1D6B/0002) (003/001)
       0.442157     - VendorID: 1d6b
       0.442167     - ProductID: 0002
       0.442176     - Manufacturer: unknown
       0.442182     - Product: unknown
       0.442189     - Serial Number: unknown
       0.442195     - Bus: 003
       0.442202     - Device release number: 0510
       0.442210     Trying to match device
       0.442218     Device does not match - skipping
       0.442230     Checking device (1D6B/0003) (004/001)
       0.468898     - VendorID: 1d6b
       0.468920     - ProductID: 0003
       0.468928     - Manufacturer: unknown
       0.468934     - Product: unknown
       0.468940     - Serial Number: unknown
       0.468946     - Bus: 004
       0.468954     - Device release number: 0510
       0.468962     Trying to match device
       0.468971     Device does not match - skipping
       0.468986     Checking device (1D6B/0002) (002/001)
       0.469174     - VendorID: 1d6b
       0.469195     - ProductID: 0002
       0.469203     - Manufacturer: unknown
       0.469209     - Product: unknown
       0.469214     - Serial Number: unknown
       0.469220     - Bus: 002
       0.469229     - Device release number: 0510
       0.469236     Trying to match device
       0.469245     Device does not match - skipping
       0.469261     Checking device (FFFF/0000) (001/018)
       0.478493     - VendorID: ffff
       0.478516     - ProductID: 0000
       0.478524     - Manufacturer:
       0.478530     - Product: 010937
       0.478536     - Serial Number:
       0.478542     - Bus: 001
       0.478551     - Device release number: 0937
       0.478559     Trying to match device
       0.478595     Device matches
       0.478626     nut_usb_set_altinterface: skipped 
usb_set_altinterface(udev, 0)
       0.478643     Skipping protocol Voltronic 0.06
       0.478653     Skipping protocol Voltronic-QS 0.07
       0.478661     Skipping protocol Voltronic-QS-Hex 0.10
       0.478667     Skipping protocol Mustek 0.07
       0.478675     Skipping protocol Megatec/old 0.07
       0.478683     Skipping protocol BestUPS 0.06
       0.478691     Skipping protocol Mecer 0.07
       0.478699     Skipping protocol Megatec 0.06
       0.478710     send: Q1
       0.739486     received 46 (40)
       0.739520     read: (231.0 120.0 240.0 055 49.9 2.29 19.0 00000001
       0.739546     send: I
       1.215002     received 38 (35)
       1.215035     read: #UPSONIC         IRT-3K 2U  MP001155
       1.215050     Using protocol: Upsonic 0.06
       1.215070     upsdrv_initinfo...
       1.215084     send: Q1
       1.473383     received 46 (40)
       1.473417     read: (231.0 120.0 240.0 055 49.9 2.29 19.0 00000001
       1.473489     send: F
       1.611858     received 21 (35)
       1.611888     read: #240.0 014 72.00 50.0
       1.611923     send: I
       1.831257     received 38 (35)
       1.831290     read: #UPSONIC         IRT-3K 2U  MP001155
       1.831334     No values for battery high/low voltages
       1.831353     Using 'guesstimation' (low: 62.400000, high: 78.000000)!
       1.831365     Battery runtime will not be calculated (runtimecal not set)
       1.831377     upsdrv_updateinfo...
       1.831385     Quick update...
       1.831397     send: Q1
       2.089478     received 46 (40)
       2.089513     read: (231.0 120.0 240.0 056 49.9 2.29 19.0 00000001
       2.089600     dstate_init: sock /run/nut/nutdrv_qx_cyber-upset open on fd 
5
       2.089626     upsdrv_updateinfo...
       2.089633     Quick update...
       2.089641     send: Q1
       2.351475     received 46 (40)
       2.351509     read: (231.0 120.0 240.0 056 49.9 2.29 19.0 00000001
       4.091419     upsdrv_updateinfo...
       4.091442     Quick update...
       4.091453     send: Q1
       4.344459     received 46 (40)
       4.344494     read: (231.0 120.0 240.0 055 49.9 2.29 19.0 00000001
       6.093230     upsdrv_updateinfo...
       6.093265     Quick update...
       6.093276     send: Q1
       6.349442     received 46 (40)
       6.349477     read: (231.0 120.0 240.0 056 49.9 2.29 19.0 00000001
       8.095031     upsdrv_updateinfo...
       8.095057     Quick update...
       8.095068     send: Q1
       8.354674     received 46 (40)
       8.354709     read: (231.0 120.0 240.0 055 49.9 2.29 19.0 00000001
      10.096835     upsdrv_updateinfo...
      10.096868     Quick update...

And it's working when hooked up to regular units:

    cyber@light:~$ sudo grep -v ^# /etc/nut/ups.conf
    [upset]
    driver = nutdrv_qx_cyber
    port = auto

    cyber@light:~$ sudo systemctl status nut-server nut-monitor nut-driver 
upslog@upset
    ● nut-server.service - Network UPS Tools - power devices information server
         Loaded: loaded (/lib/systemd/system/nut-server.service; enabled; 
vendor preset: enabled)
         Active: active (running) since Tue 2022-09-13 09:47:23 AEST; 14min ago
        Process: 894474 ExecStart=/sbin/upsd (code=exited, status=0/SUCCESS)
       Main PID: 894475 (upsd)
          Tasks: 1 (limit: 4651)
         Memory: 708.0K
            CPU: 167ms
         CGroup: /system.slice/nut-server.service
                 └─894475 /lib/nut/upsd

    Sep 13 09:47:23 light upsd[894474]: Connected to UPS [upset]: 
nutdrv_qx_cyber-upset
    Sep 13 09:47:23 light upsd[894475]: Startup successful
    Sep 13 09:47:23 light systemd[1]: Started Network UPS Tools - power devices 
information server.
    Sep 13 09:47:23 light upsd[894475]: User monmaster@127.0.0.1 logged into 
UPS [upset]
    Sep 13 09:47:24 light upsd[894475]: User monslave@203.7.155.125 logged into 
UPS [upset]
    Sep 13 09:47:24 light upsd[894475]: User monslave@203.7.155.13 logged into 
UPS [upset]
    Sep 13 09:47:27 light upsd[894475]: User monslave@203.7.155.115 logged into 
UPS [upset]
    Sep 13 09:47:27 light upsd[894475]: User monslave@203.7.155.2 logged into 
UPS [upset]
    Sep 13 09:47:27 light upsd[894475]: User monslave@203.7.155.156 logged into 
UPS [upset]
    Sep 13 09:47:28 light upsd[894475]: User monslave@203.7.155.188 logged into 
UPS [upset]

    ● nut-monitor.service - Network UPS Tools - power device monitor and 
shutdown controller
         Loaded: loaded (/lib/systemd/system/nut-monitor.service; enabled; 
vendor preset: enabled)
        Drop-In: /etc/systemd/system/nut-monitor.service.d
                 └─override.conf
         Active: active (running) since Tue 2022-09-13 09:47:23 AEST; 14min ago
        Process: 894476 ExecStart=/sbin/upsmon (code=exited, status=0/SUCCESS)
       Main PID: 894478 (upsmon)
          Tasks: 2 (limit: 4651)
         Memory: 920.0K
            CPU: 33ms
         CGroup: /system.slice/nut-monitor.service
                 ├─894478 /lib/nut/upsmon
                 └─894479 /lib/nut/upsmon

    Sep 13 09:47:23 light systemd[1]: Starting Network UPS Tools - power device 
monitor and shutdown controller...
    Sep 13 09:47:23 light upsmon[894476]: kill: No such process
    Sep 13 09:47:23 light upsmon[894476]: UPS: upset@localhost (master) (power 
value 1)
    Sep 13 09:47:23 light upsmon[894476]: Using power down flag file 
/etc/killpower
    Sep 13 09:47:23 light upsmon[894478]: Startup successful
    Sep 13 09:47:23 light systemd[1]: Started Network UPS Tools - power device 
monitor and shutdown controller.
    Sep 13 09:47:23 light upsmon[894479]: Init SSL without certificate database

    ● nut-driver.service - Network UPS Tools - power device driver controller
         Loaded: loaded (/lib/systemd/system/nut-driver.service; static)
         Active: active (running) since Tue 2022-09-13 09:47:23 AEST; 14min ago
        Process: 894431 ExecStart=/sbin/upsdrvctl start (code=exited, 
status=0/SUCCESS)
       Main PID: 894473 (nutdrv_qx_cyber)
          Tasks: 1 (limit: 4651)
         Memory: 1.0M
            CPU: 97ms
         CGroup: /system.slice/nut-driver.service
                 └─894473 /lib/nut/nutdrv_qx_cyber -a upset

    Sep 13 09:47:19 light systemd[1]: Starting Network UPS Tools - power device 
driver controller...
    Sep 13 09:47:22 light upsdrvctl[894432]: Using protocol: Upsonic 0.06
    Sep 13 09:47:23 light upsdrvctl[894432]: No values for battery high/low 
voltages
    Sep 13 09:47:23 light upsdrvctl[894432]: Using 'guesstimation' (low: 
62.400000, high: 78.000000)!
    Sep 13 09:47:23 light upsdrvctl[894432]: Battery runtime will not be 
calculated (runtimecal not set)
    Sep 13 09:47:23 light upsdrvctl[894431]: Network UPS Tools - UPS driver 
controller 2.7.4
    Sep 13 09:47:23 light nutdrv_qx_cyber[894473]: Startup successful
    Sep 13 09:47:23 light systemd[1]: Started Network UPS Tools - power device 
driver controller.

    ● upslog@upset.service
         Loaded: loaded (/etc/systemd/system/upslog@.service; enabled; vendor 
preset: enabled)
         Active: active (running) since Tue 2022-09-13 09:47:23 AEST; 14min ago
       Main PID: 894477 (upslog)
          Tasks: 1 (limit: 4651)
         Memory: 624.0K
            CPU: 26ms
         CGroup: /system.slice/system-upslog.slice/upslog@upset.service
                 └─894477 upslog -s upset -l - -f %VAR ups.status% %VAR 
battery.charge%%% charge, %VAR ups.load%%% load, %VAR ups.temperature%°C, %VAR 
input.frequency%Hz %VAR input.voltage%V in, %VAR output.voltage%V out

    Sep 13 09:56:53 light upslog/upset[894477]: OL 100% charge, 56% load, 
20.0°C, 50.0Hz 228.0V in, 240.0V out
    Sep 13 09:57:23 light upslog/upset[894477]: OL 100% charge, 56% load, 
20.0°C, 50.0Hz 228.0V in, 240.0V out
    Sep 13 09:57:53 light upslog/upset[894477]: OL 100% charge, 55% load, 
20.0°C, 50.0Hz 228.0V in, 240.0V out
    Sep 13 09:58:23 light upslog/upset[894477]: OL 100% charge, 55% load, 
20.0°C, 50.0Hz 228.0V in, 240.0V out
    Sep 13 09:58:53 light upslog/upset[894477]: OL 100% charge, 55% load, 
20.0°C, 50.0Hz 228.0V in, 240.0V out
    Sep 13 09:59:23 light upslog/upset[894477]: OL 100% charge, 55% load, 
20.0°C, 50.0Hz 229.0V in, 240.0V out
    Sep 13 09:59:53 light upslog/upset[894477]: OL 100% charge, 55% load, 
20.0°C, 50.0Hz 229.0V in, 240.0V out
    Sep 13 10:00:23 light upslog/upset[894477]: OL 100% charge, 56% load, 
20.0°C, 49.9Hz 229.0V in, 240.0V out
    Sep 13 10:00:53 light upslog/upset[894477]: OL 100% charge, 56% load, 
20.0°C, 50.0Hz 230.0V in, 240.0V out
    Sep 13 10:01:23 light upslog/upset[894477]: OL 100% charge, 56% load, 
20.0°C, 49.9Hz 229.0V in, 240.0V out

I don't know the "right" way to fix this.
It seems reasonable for nut to check for buffer underruns.

I've attached the quick-and-dirty patch against
https://salsa.debian.org/debian/nut
which is working for me.


PS: I tried to get the UPS to send \r bytes by doing a firmware upgade, but
    my UPS doesn't appear to support firmware updates.

PS: I tried to get the UPS to send \r bytes by switching from it's USB port to 
its serial port,
    then using a USB-serial adapter, then using driver=nutdrv_qx 
port=/dev/ttyUSB0, but
    even after "sudo chown -h nut: /dev/ttyUSB0", I got weird I/O errors.
    Using a different model USB-serial adapter cable didn't help.
    Using "sudo screen /dev/ttyUSB0" saw the same I/O errors.

    UPSonic doesn't have a manual for a IRT-3K product anymore, but
    their "ESART" products seem to use the DB-9 port very oddly --
    with e.g. a dedicated pin for ON-BATTERY state.

    
https://www.upsonic.com.au/wp-content/uploads/2022/03/Upsonic-ESART-1kVA-to-3kVA-User-Manual-210322.pdf#page=25
    
https://www.upsonic.com.au/wp-content/uploads/2022/03/Upsonic-CSCT-Tower-Series-UPS-Upsonic-CSCRT-Rack-Tower-UPS-User-Manual-1000VA-to-3000VA-doc.rev-240322.pdf#page=27

    Possibly unpatched nut can talk to my UPS over DB9, but
    right now I don't know how.


-- System Information:
Debian Release: 11.5
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 
'proposed-updates'), (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 5.18.0-0.bpo.1-amd64 (SMP w/8 CPU threads; PREEMPT)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_WARN, TAINT_OOT_MODULE, 
TAINT_UNSIGNED_MODULE
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
>From f15beb7a3c523e832e4cf63e27eafd9d1ef71a91 Mon Sep 17 00:00:00 2001
From: Laurent Bigonville <bi...@debian.org>
Date: Sun, 10 Jul 2022 09:23:10 +0200
Subject: [PATCH 1/2] debian/watch: Update the URL and add support for RC
 releases

---
 debian/watch | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/debian/watch b/debian/watch
index e228e43..0308379 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,2 +1,3 @@
-version=3
-https://networkupstools.org/download.html .*/nut-(.*)\.tar\.(?:gz|bz2|xz)
+version=4
+opts="uversionmangle=s/-rc/~rc/" \
+https://networkupstools.org/source/(?:([\d\.]+))/@PACKAGE@@ANY_VERSION@@ARCHIVE_EXT@
-- 
2.34.1

>From b7e417a410f0cf0557d0bb31a63807cbe139c5f5 Mon Sep 17 00:00:00 2001
From: "Trent W. Buck" <trentb...@gmail.com>
Date: Tue, 13 Sep 2022 08:00:57 +1000
Subject: [PATCH 2/2] fix upsonic irt-3000 2u

---
 debian/changelog                      |   6 +
 debian/patches/nut-upsonic-hack.patch | 262 ++++++++++++++++++++++++++
 debian/patches/series                 |   3 +
 3 files changed, 271 insertions(+)
 create mode 100644 debian/patches/nut-upsonic-hack.patch

diff --git a/debian/changelog b/debian/changelog
index c235416..811dd8a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+nut (2.7.4-13cyber2) UNRELEASED; urgency=medium
+
+  * fix upsonic irt-3000 2u
+
+ -- Trent W. Buck <trentb...@gmail.com>  Tue, 13 Sep 2022 08:19:40 +1000
+
 nut (2.7.4-13) unstable; urgency=medium
 
   [ Arnaud Quette ]
diff --git a/debian/patches/nut-upsonic-hack.patch 
b/debian/patches/nut-upsonic-hack.patch
new file mode 100644
index 0000000..601b19a
--- /dev/null
+++ b/debian/patches/nut-upsonic-hack.patch
@@ -0,0 +1,262 @@
+Description: <short summary of the patch>
+ TODO: Put a short summary on the line above and replace this paragraph
+ with a longer explanation of this change. Complete the meta-information
+ with other relevant fields (see below for details). To make it easier, the
+ information below has been extracted from the changelog. Adjust it or drop
+ it.
+ .
+ nut (2.8.0-2cyber1) UNRELEASED; urgency=medium
+ .
+   * Kludge the length checking for UPSONIC IRT-3K 2U.
+Author: Trent W. Buck <trentb...@gmail.com>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: https://bugs.debian.org/<bugnumber>
+Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: 2022-09-12
+
+--- a/drivers/Makefile.am
++++ b/drivers/Makefile.am
+@@ -242,7 +242,7 @@ nutdrv_qx_SOURCES += libusb.c usb-common.c
+ nutdrv_qx_LDADD += $(LIBUSB_LIBS)
+ endif
+ NUTDRV_QX_SUBDRIVERS = nutdrv_qx_bestups.c nutdrv_qx_blazer-common.c  \
+- nutdrv_qx_mecer.c nutdrv_qx_megatec.c nutdrv_qx_megatec-old.c        \
++ nutdrv_qx_mecer.c nutdrv_qx_megatec.c nutdrv_qx_upsonic.c 
nutdrv_qx_megatec-old.c    \
+  nutdrv_qx_mustek.c nutdrv_qx_q1.c nutdrv_qx_voltronic.c      \
+  nutdrv_qx_voltronic-qs.c nutdrv_qx_voltronic-qs-hex.c nutdrv_qx_zinto.c
+ nutdrv_qx_SOURCES += $(NUTDRV_QX_SUBDRIVERS)
+@@ -263,7 +263,7 @@ dist_noinst_HEADERS = apc-mib.h apc-hid.h baytech-mib.h 
bcmxcp.h   \
+  upshandler.h usb-common.h usbhid-ups.h powercom-hid.h compaq-mib.h 
idowell-hid.h \
+  apcsmart.h apcsmart_tabs.h apcsmart-old.h apcupsd-ups.h cyberpower-mib.h 
riello.h openups-hid.h \
+  delta_ups-mib.h nutdrv_qx.h nutdrv_qx_bestups.h nutdrv_qx_blazer-common.h 
nutdrv_qx_mecer.h  \
+- nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h 
nutdrv_qx_q1.h        \
++ nutdrv_qx_megatec.h nutdrv_qx_upsonic.h nutdrv_qx_megatec-old.h 
nutdrv_qx_mustek.h nutdrv_qx_q1.h    \
+  nutdrv_qx_voltronic.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h 
nutdrv_qx_zinto.h \
+  xppc-mib.h huawei-mib.h eaton-ats-mib.h apc-ats-mib.h
+ 
+--- /dev/null
++++ nut-2.8.0/drivers/nutdrv_qx_upsonic.c
+@@ -0,0 +1,162 @@
++/* nutdrv_qx_upsonic.c - Subdriver for Upsonic protocol based UPSes
++ *
++ *  --- Exactly the same as megatec, except no \r at the end of responses to 
I/F/Q1 queries.
++ *      This avoids this problem:
++ *
++ *          1.169169     send: F
++ *          1.313636     received 21 (35)
++ *          1.313660     read: #240.0 014 72.00 50.0
++ *          1.313668     blazer_rating: short reply
++ *          1.313675     Rating read 3 failed
++ *          1.313688     Rating information unavailable
++ *          ...
++ *          1.753885     send: I
++ *          1.976101     received 38 (35)
++ *          1.976125     read: #UPSONIC         IRT-3K 2U  MP001155
++ *          1.976133     blazer_vendor: short reply
++ *          1.976139     Vendor information read 3 failed
++ *          1.976146     Vendor information unavailable
++ *
++ *      I strongly suspect:
++ *
++ *          1. megatec_usb in nut 2.4 did not length-check anything, so all 3 
queries worked.
++ *          2. blazer_usb in nut 2.7 length-checks I and F but not Q1, so 
only Q1 works (thus also breaking charge percentage &c).
++ *          3. nutdrv_qx in nut 2.7 length-checks all 3 queries, so all 3 
queries fail.
++ *
++ *
++ * Copyright (C)
++ *   2013 Daniele Pezzini <hyo...@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#include "main.h"
++#include "nutdrv_qx.h"
++#include "nutdrv_qx_blazer-common.h"
++
++#include "nutdrv_qx_upsonic.h"
++
++#define UPSONIC_VERSION "Upsonic 0.06"
++
++/* qx2nut lookup table */
++static item_t upsonic_qx2nut[] = {
++
++      /*
++       * > [Q1\r]
++       * < [(226.0 195.0 226.0 014 49.0 27.5 30.0 00001000\r]
++       *    01234567890123456789012345678901234567890123456
++       *    0         1         2         3         4
++       */
++
++      { "input.voltage",              0,      NULL,   "Q1\r", "",     46,     
'(',    "",     1,      5,      "%.1f", 0,      NULL,   NULL,   NULL },
++      { "input.voltage.fault",        0,      NULL,   "Q1\r", "",     46,     
'(',    "",     7,      11,     "%.1f", 0,      NULL,   NULL,   NULL },
++      { "output.voltage",             0,      NULL,   "Q1\r", "",     46,     
'(',    "",     13,     17,     "%.1f", 0,      NULL,   NULL,   NULL },
++      { "ups.load",                   0,      NULL,   "Q1\r", "",     46,     
'(',    "",     19,     21,     "%.0f", 0,      NULL,   NULL,   NULL },
++      { "input.frequency",            0,      NULL,   "Q1\r", "",     46,     
'(',    "",     23,     26,     "%.1f", 0,      NULL,   NULL,   NULL },
++      { "battery.voltage",            0,      NULL,   "Q1\r", "",     46,     
'(',    "",     28,     31,     "%.2f", 0,      NULL,   NULL,   NULL },
++      { "ups.temperature",            0,      NULL,   "Q1\r", "",     46,     
'(',    "",     33,     36,     "%.1f", 0,      NULL,   NULL,   NULL },
++      /* Status bits */
++      { "ups.status",                 0,      NULL,   "Q1\r", "",     46,     
'(',    "",     38,     38,     NULL,   QX_FLAG_QUICK_POLL,     NULL,   NULL,   
blazer_process_status_bits },   /* Utility Fail (Immediate) */
++      { "ups.status",                 0,      NULL,   "Q1\r", "",     46,     
'(',    "",     39,     39,     NULL,   QX_FLAG_QUICK_POLL,     NULL,   NULL,   
blazer_process_status_bits },   /* Battery Low */
++      { "ups.status",                 0,      NULL,   "Q1\r", "",     46,     
'(',    "",     40,     40,     NULL,   QX_FLAG_QUICK_POLL,     NULL,   NULL,   
blazer_process_status_bits },   /* Bypass/Boost or Buck Active */
++      { "ups.alarm",                  0,      NULL,   "Q1\r", "",     46,     
'(',    "",     41,     41,     NULL,   0,                      NULL,   NULL,   
blazer_process_status_bits },   /* UPS Failed */
++      { "ups.type",                   0,      NULL,   "Q1\r", "",     46,     
'(',    "",     42,     42,     "%s",   QX_FLAG_STATIC,         NULL,   NULL,   
blazer_process_status_bits },   /* UPS Type */
++      { "ups.status",                 0,      NULL,   "Q1\r", "",     46,     
'(',    "",     43,     43,     NULL,   QX_FLAG_QUICK_POLL,     NULL,   NULL,   
blazer_process_status_bits },   /* Test in Progress */
++      { "ups.status",                 0,      NULL,   "Q1\r", "",     46,     
'(',    "",     44,     44,     NULL,   QX_FLAG_QUICK_POLL,     NULL,   NULL,   
blazer_process_status_bits },   /* Shutdown Active */
++      { "ups.beeper.status",          0,      NULL,   "Q1\r", "",     46,     
'(',    "",     45,     45,     "%s",   0,                      NULL,   NULL,   
blazer_process_status_bits },   /* Beeper status */
++
++      /*
++       * > [F\r]
++       * < [#220.0 000 024.0 50.0\r]
++       *    0123456789012345678901
++       *    0         1         2
++       */
++
++      { "input.voltage.nominal",      0,      NULL,   "F\r",  "",     21,     
'#',    "",     1,      5,      "%.0f", QX_FLAG_STATIC, NULL,   NULL,   NULL },
++      { "input.current.nominal",      0,      NULL,   "F\r",  "",     21,     
'#',    "",     7,      9,      "%.1f", QX_FLAG_STATIC, NULL,   NULL,   NULL },
++      { "battery.voltage.nominal",    0,      NULL,   "F\r",  "",     21,     
'#',    "",     11,     15,     "%.1f", QX_FLAG_STATIC, NULL,   NULL,   NULL },
++      { "input.frequency.nominal",    0,      NULL,   "F\r",  "",     21,     
'#',    "",     17,     20,     "%.0f", QX_FLAG_STATIC, NULL,   NULL,   NULL },
++
++      /*
++       * > [I\r]
++       * < [#-------------   ------     VT12046Q  \r]
++       *    012345678901234567890123456789012345678
++       *    0         1         2         3
++       */
++
++      { "device.mfr",                 0,      NULL,   "I\r",  "",     38,     
'#',    "",     1,      15,     "%s",   QX_FLAG_STATIC | QX_FLAG_TRIM,  NULL,   
NULL,   NULL },
++      { "device.model",               0,      NULL,   "I\r",  "",     38,     
'#',    "",     17,     26,     "%s",   QX_FLAG_STATIC | QX_FLAG_TRIM,  NULL,   
NULL,   NULL },
++      { "ups.firmware",               0,      NULL,   "I\r",  "",     38,     
'#',    "",     28,     37,     "%s",   QX_FLAG_STATIC | QX_FLAG_TRIM,  NULL,   
NULL,   NULL },
++
++      /* Instant commands */
++      { "beeper.toggle",              0,      NULL,   "Q\r",          "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++      { "load.off",                   0,      NULL,   "S00R0000\r",   "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++      { "load.on",                    0,      NULL,   "C\r",          "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++      { "shutdown.return",            0,      NULL,   "S%s\r",        "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
blazer_process_command },
++      { "shutdown.stayoff",           0,      NULL,   "S%sR0000\r",   "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
blazer_process_command },
++      { "shutdown.stop",              0,      NULL,   "C\r",          "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++      { "test.battery.start",         0,      NULL,   "T%02d\r",      "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
blazer_process_command },
++      { "test.battery.start.deep",    0,      NULL,   "TL\r",         "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++      { "test.battery.start.quick",   0,      NULL,   "T\r",          "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++      { "test.battery.stop",          0,      NULL,   "CT\r",         "",     
0,      0,      "",     0,      0,      NULL,   QX_FLAG_CMD,    NULL,   NULL,   
NULL },
++
++      /* Server-side settable vars */
++      { "ups.delay.start",            ST_FLAG_RW,     blazer_r_ondelay,       
NULL,   "",     0,      0,      "",     0,      0,      DEFAULT_ONDELAY,        
QX_FLAG_ABSENT | QX_FLAG_SETVAR | QX_FLAG_RANGE,        NULL,   NULL,   
blazer_process_setvar },
++      { "ups.delay.shutdown",         ST_FLAG_RW,     blazer_r_offdelay,      
NULL,   "",     0,      0,      "",     0,      0,      DEFAULT_OFFDELAY,       
QX_FLAG_ABSENT | QX_FLAG_SETVAR | QX_FLAG_RANGE,        NULL,   NULL,   
blazer_process_setvar },
++
++      /* End of structure. */
++      { NULL,                         0,      NULL,   NULL,           "",     
0,      0,      "",     0,      0,      NULL,   0,      NULL,   NULL,   NULL }
++};
++
++/* Testing table */
++#ifdef TESTING
++static testing_t      upsonic_testing[] = {
++      { "Q1\r",       "(215.0 195.0 230.0 014 49.0 22.7 30.0 00000000",       
-1 },
++      { "F\r",        "#230.0 000 024.0 50.0",        -1 },
++      { "I\r",        "#NOT_A_LIVE_UPS  TESTING    TESTING   ",       -1 },
++      { "Q\r",        "",     -1 },
++      { "S03\r",      "",     -1 },
++      { "C\r",        "",     -1 },
++      { "S02R0005\r", "",     -1 },
++      { "S.5R0000\r", "",     -1 },
++      { "T04\r",      "",     -1 },
++      { "TL\r",       "",     -1 },
++      { "T\r",        "",     -1 },
++      { "CT\r",       "",     -1 },
++      { NULL }
++};
++#endif        /* TESTING */
++
++/* Subdriver-specific initups */
++static void   upsonic_initups(void)
++{
++      blazer_initups(upsonic_qx2nut);
++}
++
++/* Subdriver interface */
++subdriver_t   upsonic_subdriver = {
++      UPSONIC_VERSION,
++      blazer_claim,
++      upsonic_qx2nut,
++      upsonic_initups,
++      NULL,
++      blazer_makevartable,
++      "ACK",
++      NULL,
++#ifdef TESTING
++      upsonic_testing,
++#endif        /* TESTING */
++};
+--- /dev/null
++++ nut-2.8.0/drivers/nutdrv_qx_upsonic.h
+@@ -0,0 +1,29 @@
++/* nutdrv_qx_upsonic.h - Subdriver for Upsonic protocol based UPSes
++ *
++ * Copyright (C)
++ *   2013 Daniele Pezzini <hyo...@gmail.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++#ifndef NUTDRV_QX_UPSONIC_H
++#define NUTDRV_QX_UPSONIC_H
++
++#include "nutdrv_qx.h"
++
++extern subdriver_t    upsonic_subdriver;
++
++#endif /* NUTDRV_QX_UPSONICH_H */
+--- a/drivers/nutdrv_qx.c
++++ b/drivers/nutdrv_qx.c
+@@ -83,6 +83,7 @@
+       &bestups_subdriver,
+       &mecer_subdriver,
+       &megatec_subdriver,
++      &upsonic_subdriver,
+       &zinto_subdriver,
+       /* Fallback Q1 subdriver */
+       &q1_subdriver,
+--- a/drivers/nutdrv_qx.c
++++ b/drivers/nutdrv_qx.c
+@@ -65,6 +65,7 @@
+ #include "nutdrv_qx_bestups.h"
+ #include "nutdrv_qx_mecer.h"
+ #include "nutdrv_qx_megatec.h"
++#include "nutdrv_qx_upsonic.h"
+ #include "nutdrv_qx_megatec-old.h"
+ #include "nutdrv_qx_mustek.h"
+ #include "nutdrv_qx_q1.h"
diff --git a/debian/patches/series b/debian/patches/series
index 50dc917..fc8139f 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -11,3 +11,6 @@
 0011-use-pkgconfig-module.patch
 0012-add-AEG-PROTECT-NAS-support.patch
 0013-fix-doc-build.patch
+
+# twb
+nut-upsonic-hack.patch
\ No newline at end of file
-- 
2.34.1

Reply via email to