Skip to content

Commit 093e44b

Browse files
authored
Merge pull request #2938 from dvdesolve/innovart33
Add support (experimental) for Ippon Innova RT 3/3
2 parents ea8cb0e + d2c02ff commit 093e44b

File tree

9 files changed

+307
-11
lines changed

9 files changed

+307
-11
lines changed

NEWS.adoc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ https://github.com/networkupstools/nut/milestone/9
7373
and misfired on some platforms, and the way to print had a theoretical
7474
potential for buffer overflow. [#2915]
7575

76+
- `nutdrv_qx` driver updates:
77+
* Introduced `innovart33` protocol support for Ippon Innova RT 3/3 topology
78+
UPSes. [#2938]
79+
7680
- `usbhid-ups` driver updates:
7781
* The `cps-hid` subdriver's existing mechanism for fixing broken report
7882
descriptors was extended to cover a newly reported case of nominal UPS
@@ -324,7 +328,8 @@ This requirement compromises usability of `make distcheck` on platforms without
324328
* Added Visench C1K (using serial port converter with USB ID `1a86:7523`)
325329
as known supported by `nutdrv_qx` (Megatec protocol) since at least
326330
NUT v2.7.4 release. [#2395]
327-
* Introduced `innovart31` protocol support for Innova RT 3/1 UPSes. [#2712, #2798]
331+
* Introduced `innovart31` protocol support for Ippon Innova RT 3/1 topology
332+
UPSes. [#2712, #2798]
328333
* Introduced `q2` and `q6` protocol support; currently also based/tested
329334
on Innova devices, but other models than RT 3/1. [#2798]
330335
* Introduced a `gtec` subdriver and protocol, tested over USB with a

docs/man/nutdrv_qx.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ If you set stayoff in linkman:ups.conf[5] when FSD arises the UPS will call a *s
8888

8989
*protocol =* 'string'::
9090
Skip autodetection of the protocol to use and only use the one specified.
91-
Supported values: 'bestups', 'gtec', 'hunnox', 'innovart31', 'masterguard', 'mecer', 'megatec', 'megatec/old', 'mustek', 'q1', 'q2', 'q6', 'voltronic', 'voltronic-qs', 'voltronic-qs-hex' and 'zinto'.
91+
Supported values: 'bestups', 'gtec', 'hunnox', 'innovart31', 'innovart33', 'masterguard', 'mecer', 'megatec', 'megatec/old', 'mustek', 'q1', 'q2', 'q6', 'voltronic', 'voltronic-qs', 'voltronic-qs-hex' and 'zinto'.
9292
+
9393
Run the driver program with the `--help` option to see the exact list of
9494
`protocol` values it would currently recognize.
@@ -168,8 +168,8 @@ If not specified, the driver defaults to 10%.
168168
Only used if *runtimecal* is also specified.
169169

170170

171-
BESTUPS, INNOVART31, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, Q2, Q6, VOLTRONIC-QS, VOLTRONIC-QS-HEX, ZINTO PROTOCOLS
172-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
171+
BESTUPS, INNOVART31, INNOVART33, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, Q2, Q6, VOLTRONIC-QS, VOLTRONIC-QS-HEX, ZINTO PROTOCOLS
172+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
173173

174174
*ignoresab*::
175175
Some UPSes incorrectly report the `Shutdown Active' bit as always on, consequently making the driver believe the UPS is nearing a shutdown (and, as a result, ups.status always contains +FSD+... and you know what this means).
@@ -217,8 +217,8 @@ Safeguard against talking to the wrong one of several identical UPSes on the sam
217217
Note that when changing *ups.id* (through linkman:upsrw[8]) the driver will continue to talk to the UPS with the new 'slave address', but won't claim it again on restart until the *slave_addr* parameter is adjusted.
218218

219219

220-
INNOVART31, Q1, Q2, Q6 PROTOCOLS
221-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
220+
INNOVART31, INNOVART33, Q1, Q2, Q6 PROTOCOLS
221+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
222222

223223
*ondelay*::
224224
The acceptable range is +0..599940+ seconds.
@@ -499,8 +499,8 @@ Stop a running battery test.
499499
(Not available on some hardware)
500500

501501

502-
BESTUPS, INNOVART31, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, Q2, Q6, ZINTO PROTOCOLS
503-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
502+
BESTUPS, INNOVART31, INNOVART33, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, Q2, Q6, ZINTO PROTOCOLS
503+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
504504

505505
*test.battery.start* 'value'::
506506
Perform a battery test for the duration of 'value' seconds (truncated to 60 seconds) [+60..5940+].

docs/nutdrv_qx-subdrivers.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,7 @@ For more details, have a look at the currently available subdrivers:
11791179

11801180
- +nutdrv_qx_bestups.+{+c+,+h+}
11811181
- +nutdrv_qx_innovart31.+{+c+,+h+}
1182+
- +nutdrv_qx_innovart33.+{+c+,+h+}
11821183
- +nutdrv_qx_masterguard.+{+c+,+h+}
11831184
- +nutdrv_qx_mecer.+{+c+,+h+}
11841185
- +nutdrv_qx_megatec.+{+c+,+h+}

drivers/Makefile.am

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ nutdrv_qx_LDADD += $(LIBUSB_LIBS)
393393
endif WITH_USB
394394
NUTDRV_QX_SUBDRIVERS = nutdrv_qx_bestups.c nutdrv_qx_blazer-common.c \
395395
nutdrv_qx_innovart31.c \
396+
nutdrv_qx_innovart33.c \
396397
nutdrv_qx_masterguard.c \
397398
nutdrv_qx_mecer.c nutdrv_qx_megatec.c nutdrv_qx_megatec-old.c \
398399
nutdrv_qx_mustek.c nutdrv_qx_q1.c nutdrv_qx_q2.c nutdrv_qx_q6.c nutdrv_qx_voltronic.c \
@@ -418,7 +419,7 @@ dist_noinst_HEADERS = \
418419
upshandler.h usb-common.h usbhid-ups.h powercom-hid.h compaq-mib.h idowell-hid.h \
419420
apcsmart.h apcsmart_tabs.h apcsmart-old.h apcupsd-ups.h cyberpower-mib.h riello.h openups-hid.h \
420421
delta_ups-mib.h nutdrv_qx.h nutdrv_qx_bestups.h nutdrv_qx_blazer-common.h \
421-
nutdrv_qx_gtec.h nutdrv_qx_innovart31.h nutdrv_qx_masterguard.h nutdrv_qx_mecer.h nutdrv_qx_ablerex.h \
422+
nutdrv_qx_gtec.h nutdrv_qx_innovart31.h nutdrv_qx_innovart33.h nutdrv_qx_masterguard.h nutdrv_qx_mecer.h nutdrv_qx_ablerex.h \
422423
nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h nutdrv_qx_q1.h nutdrv_qx_q2.h nutdrv_qx_q6.h nutdrv_qx_hunnox.h \
423424
nutdrv_qx_voltronic.h nutdrv_qx_voltronic-qs.h nutdrv_qx_voltronic-qs-hex.h nutdrv_qx_zinto.h \
424425
upsdrvquery.h \

drivers/nutdrv_qx.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#include "nutdrv_qx_bestups.h"
7373
#include "nutdrv_qx_hunnox.h"
7474
#include "nutdrv_qx_innovart31.h"
75+
#include "nutdrv_qx_innovart33.h"
7576
#include "nutdrv_qx_mecer.h"
7677
#include "nutdrv_qx_megatec.h"
7778
#include "nutdrv_qx_megatec-old.h"
@@ -102,6 +103,7 @@ static subdriver_t *subdriver_list[] = {
102103
&hunnox_subdriver,
103104
&ablerex_subdriver,
104105
&innovart31_subdriver,
106+
&innovart33_subdriver,
105107
&q2_subdriver,
106108
&q6_subdriver,
107109
&gtec_subdriver,

drivers/nutdrv_qx_blazer-common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* nutdrv_qx_blazer-common.c - Common functions/settings for nutdrv_qx_{innovart31,mecer,megatec,megatec-old,mustek,q1,q2,q6,voltronic-qs,zinto}.{c,h}
1+
/* nutdrv_qx_blazer-common.c - Common functions/settings for nutdrv_qx_{innovart31,innovart33,mecer,megatec,megatec-old,mustek,q1,q2,q6,voltronic-qs,zinto}.{c,h}
22
*
33
* Copyright (C)
44
* 2013 Daniele Pezzini <[email protected]>

drivers/nutdrv_qx_blazer-common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* nutdrv_qx_blazer-common.h - Common functions/settings for nutdrv_qx_{innovart31,mecer,megatec,megatec-old,mustek,q1,q2,q6,voltronic-qs,zinto}.{c,h}
1+
/* nutdrv_qx_blazer-common.h - Common functions/settings for nutdrv_qx_{innovart31,innovart33,mecer,megatec,megatec-old,mustek,q1,q2,q6,voltronic-qs,zinto}.{c,h}
22
*
33
* Copyright (C)
44
* 2013 Daniele Pezzini <[email protected]>

drivers/nutdrv_qx_innovart33.c

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
/* nutdrv_qx_innovart33.c - Subdriver for INNOVA RT 3/3 UPSes
2+
*
3+
* Copyright (C)
4+
* 2025 Viktor Drobot <[email protected]>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19+
*
20+
*/
21+
22+
#include "main.h"
23+
#include "nutdrv_qx.h"
24+
#include "nutdrv_qx_blazer-common.h"
25+
26+
#include "nutdrv_qx_innovart33.h"
27+
28+
#define INNOVART33_VERSION "INNOVART33 0.01"
29+
30+
/* Support functions */
31+
static int innovart33_claim(void);
32+
static void innovart33_initups(void);
33+
static void innovart33_initinfo(void);
34+
35+
/* qx2nut lookup table */
36+
static item_t innovart33_qx2nut[] = {
37+
38+
/*
39+
* > [Q6\r]
40+
* < [(227.0 225.6 230.0 50.0 229.9 000.0 000.0 49.9 007 000 000 327.8 000.0 23.0 06932 100 32 00000000 00000000 11\r]
41+
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
42+
* 0 1 2 3 4 5 6 7 8 9 10
43+
*/
44+
45+
/* Common parameters */
46+
{ "input.L1-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 1, 5, "%.1f", 0, NULL, NULL, NULL },
47+
{ "input.L2-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 7, 11, "%.1f", 0, NULL, NULL, NULL },
48+
{ "input.L3-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 13, 17, "%.1f", 0, NULL, NULL, NULL },
49+
{ "input.frequency", 0, NULL, "Q6\r", "", 110, '(', "", 19, 22, "%.1f", 0, NULL, NULL, NULL },
50+
{ "output.L1-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 24, 28, "%.1f", 0, NULL, NULL, NULL },
51+
{ "output.L2-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 30, 34, "%.1f", 0, NULL, NULL, NULL },
52+
{ "output.L3-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 36, 40, "%.1f", 0, NULL, NULL, NULL },
53+
{ "output.frequency", 0, NULL, "Q6\r", "", 110, '(', "", 42, 45, "%.1f", 0, NULL, NULL, NULL },
54+
{ "output.L1.load", 0, NULL, "Q6\r", "", 110, '(', "", 47, 49, "%.0f", 0, NULL, NULL, NULL },
55+
{ "output.L2.load", 0, NULL, "Q6\r", "", 110, '(', "", 51, 53, "%.0f", 0, NULL, NULL, NULL },
56+
{ "output.L3.load", 0, NULL, "Q6\r", "", 110, '(', "", 55, 57, "%.0f", 0, NULL, NULL, NULL },
57+
{ "ups.temperature", 0, NULL, "Q6\r", "", 110, '(', "", 71, 74, "%.1f", 0, NULL, NULL, NULL },
58+
{ "battery.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 59, 63, "%.1f", 0, NULL, NULL, qx_multiply_battvolt },
59+
{ "battery.runtime", 0, NULL, "Q6\r", "", 110, '(', "", 76, 80, "%.0f", 0, NULL, NULL, NULL },
60+
{ "battery.charge", 0, NULL, "Q6\r", "", 110, '(', "", 82, 84, "%.0f", 0, NULL, NULL, NULL },
61+
62+
/*
63+
* > [WA\r]
64+
* < [(001.4 000.0 000.0 001.4 000.0 000.0 001.4 001.4 006.5 000.0 000.0 007 00000000\r]
65+
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
66+
* 0 1 2 3 4 5 6 7
67+
*/
68+
69+
/* Output consumption parameters */
70+
{ "output.L1.realpower", 0, NULL, "WA\r", "", 80, '(', "", 1, 5, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
71+
{ "output.L2.realpower", 0, NULL, "WA\r", "", 80, '(', "", 7, 11, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
72+
{ "output.L3.realpower", 0, NULL, "WA\r", "", 80, '(', "", 13, 17, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
73+
{ "output.L1.power", 0, NULL, "WA\r", "", 80, '(', "", 19, 23, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
74+
{ "output.L2.power", 0, NULL, "WA\r", "", 80, '(', "", 25, 29, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
75+
{ "output.L3.power", 0, NULL, "WA\r", "", 80, '(', "", 31, 35, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
76+
{ "output.L1.current", 0, NULL, "WA\r", "", 80, '(', "", 49, 53, "%.1f", 0, NULL, NULL, NULL },
77+
{ "output.L2.current", 0, NULL, "WA\r", "", 80, '(', "", 55, 59, "%.1f", 0, NULL, NULL, NULL },
78+
{ "output.L3.current", 0, NULL, "WA\r", "", 80, '(', "", 61, 65, "%.1f", 0, NULL, NULL, NULL },
79+
{ "ups.realpower", 0, NULL, "WA\r", "", 80, '(', "", 37, 41, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
80+
{ "ups.power", 0, NULL, "WA\r", "", 80, '(', "", 43, 47, "%.1f", 0, NULL, NULL, qx_multiply_x1000 },
81+
{ "ups.load", 0, NULL, "WA\r", "", 80, '(', "", 67, 69, "%.0f", 0, NULL, NULL, NULL },
82+
83+
/*
84+
* > [BPS\r]
85+
* < [(230.4 000.0 000.0 49.9\r]
86+
* 012345678901234567890123
87+
* 0 1 2
88+
*/
89+
90+
/* Bypass parameters */
91+
{ "input.bypass.L1-N.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 1, 5, "%.1f", 0, NULL, NULL, NULL },
92+
{ "input.bypass.L2-N.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 7, 11, "%.1f", 0, NULL, NULL, NULL },
93+
{ "input.bypass.L3-N.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 13, 17, "%.1f", 0, NULL, NULL, NULL },
94+
{ "input.bypass.frequency", 0, NULL, "BPS\r", "", 24, '(', "", 19, 22, "%.1f", 0, NULL, NULL, NULL },
95+
96+
/*
97+
* > [F\r]
98+
* < [#230.0 087 288.0 50.0\r]
99+
* 0123456789012345678901
100+
* 0 1 2
101+
*/
102+
103+
/* Nominal parameters (ratings) */
104+
{ "input.voltage.nominal", 0, NULL, "F\r", "", 22, '#', "", 1, 5, "%.0f", QX_FLAG_STATIC, NULL, NULL, NULL },
105+
{ "input.current.nominal", 0, NULL, "F\r", "", 22, '#', "", 7, 9, "%.1f", QX_FLAG_STATIC, NULL, NULL, NULL },
106+
{ "battery.voltage.nominal", 0, NULL, "F\r", "", 22, '#', "", 11, 15, "%.1f", QX_FLAG_STATIC, NULL, NULL, NULL },
107+
{ "input.frequency.nominal", 0, NULL, "F\r", "", 22, '#', "", 17, 20, "%.0f", QX_FLAG_STATIC, NULL, NULL, NULL },
108+
109+
/*
110+
* > [FW?\r]
111+
* < [05516-1100\r]
112+
* 01234567890
113+
* 0 1
114+
*/
115+
116+
/* Firmware version */
117+
{ "ups.firmware", 0, NULL, "FW?\r", "", 0, 0, "", 0, 0, "%s", QX_FLAG_STATIC, NULL, NULL, NULL },
118+
119+
/*
120+
* > [SASV07?\r]
121+
* < [GASV07DN05K10KB100004 \r]
122+
* 0123456789012345678901234567
123+
* 0 1 2
124+
*/
125+
126+
/* UPS serial number */
127+
{ "ups.serial", 0, NULL, "SASV07?\r", "", 28, 0, "", 7, 0, "%s", QX_FLAG_STATIC | QX_FLAG_TRIM, NULL, NULL, NULL },
128+
129+
/*
130+
* > [Q1\r]
131+
* < [(226.0 195.0 226.0 014 49.0 27.5 30.0 00001000\r]
132+
* 01234567890123456789012345678901234567890123456
133+
* 0 1 2 3 4
134+
*/
135+
136+
/* Status bits */
137+
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 38, 38, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Utility Fail (Immediate) */
138+
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 39, 39, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Battery Low */
139+
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 40, 40, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Bypass/Boost or Buck Active */
140+
{ "ups.alarm", 0, NULL, "Q1\r", "", 47, '(', "", 41, 41, NULL, 0, NULL, NULL, blazer_process_status_bits }, /* UPS Failed */
141+
{ "ups.type", 0, NULL, "Q1\r", "", 47, '(', "", 42, 42, "%s", QX_FLAG_STATIC, NULL, NULL, blazer_process_status_bits }, /* UPS Type */
142+
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 43, 43, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Test in Progress */
143+
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 44, 44, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Shutdown Active */
144+
{ "ups.beeper.status", 0, NULL, "Q1\r", "", 47, '(', "", 45, 45, "%s", 0, NULL, NULL, blazer_process_status_bits }, /* Beeper status */
145+
146+
/* Instant commands */
147+
/* NB: seems like beeper toggling doesn't work for Innova RT 3/3 by Ippon - UPS simply doesn't respond */
148+
{ "load.off" , 0, NULL, "S00R0000\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, NULL },
149+
{ "load.on", 0, NULL, "C\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, NULL },
150+
{ "shutdown.return", 0, NULL, "S%s\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, blazer_process_command },
151+
{ "shutdown.stayoff", 0, NULL, "S%sR0000\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, blazer_process_command },
152+
{ "shutdown.stop", 0, NULL, "C\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, NULL },
153+
{ "test.battery.start", 0, NULL, "T%02d\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, blazer_process_command },
154+
{ "test.battery.start.deep", 0, NULL, "TL\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, NULL },
155+
{ "test.battery.start.quick", 0, NULL, "T\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, NULL },
156+
{ "test.battery.stop", 0, NULL, "CT\r", "", 0, 0, "", 0, 0, NULL, QX_FLAG_CMD, NULL, NULL, NULL },
157+
158+
/* Server-side settable vars */
159+
{ "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 },
160+
{ "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 },
161+
162+
/* End of structure. */
163+
{ NULL, 0, NULL, NULL, "", 0, 0, "", 0, 0, NULL, 0, NULL, NULL, NULL }
164+
};
165+
166+
/* Testing table */
167+
#ifdef TESTING
168+
static testing_t innovart33_testing[] = {
169+
{ "Q6\r", "(227.0 225.6 230.0 50.0 229.9 000.0 000.0 49.9 007 000 000 327.8 000.0 23.0 06932 100 32 00000000 00000000 11\r", -1 },
170+
{ "Q1\r", "(215.0 195.0 230.0 014 49.0 22.7 30.0 00000000\r", -1 },
171+
{ "WA\r", "(001.4 000.0 000.0 001.4 000.0 000.0 001.4 001.4 006.5 000.0 000.0 007 00000000\r", -1 },
172+
{ "BPS\r", "(230.4 000.0 000.0 49.9\r", -1 },
173+
{ "F\r", "#230.0 087 288.0 50.0\r", -1 },
174+
{ "FW?\r", "05516-1100\r", -1 },
175+
{ "SASV07?\r", "GASV07DN05K10KB100004 \r", -1 },
176+
{ "S03\r", "", -1 },
177+
{ "C\r", "", -1 },
178+
{ "S02R0005\r", "", -1 },
179+
{ "S.5R0000\r", "", -1 },
180+
{ "T04\r", "ACK", -1 },
181+
{ "TL\r", "ACK", -1 },
182+
{ "T\r", "ACK", -1 },
183+
{ "CT\r", "ACK", -1 },
184+
{ NULL }
185+
};
186+
#endif /* TESTING */
187+
188+
/* == Support functions == */
189+
190+
/* This function allows the subdriver to "claim" a device: return 1 if the device is supported by this subdriver, else 0 */
191+
static int innovart33_claim(void)
192+
{
193+
/* We need Q6, Q1, WA, BPS, F, FW? and SASV07? to use this subdriver */
194+
struct {
195+
char *var;
196+
char *cmd;
197+
} mandatory[] = {
198+
{ "input.L1-N.voltage", "Q6" },
199+
{ "ups.type", "Q1" },
200+
{ "output.current", "WA" },
201+
{ "input.bypass.voltage", "BPS" },
202+
{ "input.voltage.nominal", "F" },
203+
{ "ups.firmware", "FW?" },
204+
{ "ups.serial", "SASV07?" },
205+
{ NULL, NULL}
206+
};
207+
int vari;
208+
char *sp;
209+
item_t *item;
210+
211+
for (vari = 0; mandatory[vari].var; vari++) {
212+
sp = mandatory[vari].var;
213+
item = find_nut_info(sp, 0, 0);
214+
215+
/* Don't know what happened */
216+
if (!item)
217+
return 0;
218+
219+
/* No reply/Unable to get value */
220+
if (qx_process(item, NULL))
221+
return 0;
222+
223+
/* Unable to process value */
224+
if (ups_infoval_set(item) != 1)
225+
return 0;
226+
}
227+
228+
return 1;
229+
}
230+
231+
/* Subdriver-specific initups */
232+
static void innovart33_initups(void)
233+
{
234+
blazer_initups_light(innovart33_qx2nut);
235+
}
236+
237+
/* Subdriver-specific initinfo */
238+
static void innovart33_initinfo(void)
239+
{
240+
dstate_setinfo("input.phases", "%d", 3);
241+
dstate_setinfo("input.bypass.phases", "%d", 3);
242+
dstate_setinfo("output.phases", "%d", 3);
243+
}
244+
245+
/* Subdriver interface */
246+
subdriver_t innovart33_subdriver = {
247+
INNOVART33_VERSION,
248+
innovart33_claim,
249+
innovart33_qx2nut,
250+
innovart33_initups,
251+
innovart33_initinfo,
252+
blazer_makevartable_light,
253+
"ACK",
254+
"NAK\r",
255+
#ifdef TESTING
256+
innovart33_testing,
257+
#endif /* TESTING */
258+
};

0 commit comments

Comments
 (0)