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

First attempt to add support for Ippon Innova RT 3/1 #2712

Merged
merged 14 commits into from
Dec 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions NEWS.adoc
Original file line number Diff line number Diff line change
@@ -144,9 +144,11 @@ https://github.com/networkupstools/nut/milestone/11
In fact, the driver should try fully reconnecting upon getting into
a prolonged data stale condition. [issue #704, PR #2564]

- added Visench C1K (using serial port converter with USB ID `1a86:7523`)
as known supported by `nutdrv_qx` (Megatec protocol) since at least
NUT v2.7.4 release [#2395]
- nutdrv_qx updates:
* added Visench C1K (using serial port converter with USB ID `1a86:7523`)
as known supported by `nutdrv_qx` (Megatec protocol) since at least
NUT v2.7.4 release. [#2395]
* introduced `innovart31` protocol support for Innova RT 3/1 UPSes. [#2712]

- bicker_ser: added new driver for Bicker 12/24Vdc UPS via RS-232 serial
communication protocol, which supports any UPS shipped with the PSZ-1053
1 change: 1 addition & 0 deletions data/driver.list.in
Original file line number Diff line number Diff line change
@@ -590,6 +590,7 @@
"Ippon" "ups" "2" "Smart Power Pro II Euro 1200/1600/2200" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/2702 https://github.com/networkupstools/nut/issues/701
"Ippon" "ups" "2" "Pacific 1000/2000/3000" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/2702
"Ippon" "ups" "2" "Ampere 1000/1500/2000/3000 bl" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/2702
"Ippon" "ups" "2" "Innova RT 3/1 10K/10K compact/20K" "USB" "nutdrv_qx" # https://github.com/networkupstools/nut/issues/2712
"Ippon" "ups" "2" "Innova RTB 1000/1500/2000/3000" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/2702
"Ippon" "ups" "2" "Innova TBE 1000/2000/3000" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/2702
"Ippon" "ups" "2" "Innova TB 1000/2000/3000" "USB" "usbhid-ups" # https://github.com/networkupstools/nut/issues/2702
14 changes: 7 additions & 7 deletions docs/man/nutdrv_qx.txt
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ If you set stayoff in linkman:ups.conf[5] when FSD arises the UPS will call a *s

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


BESTUPS, MECER, MEGATAEC, MEGATEC/OLD, MUSTEK, Q1, VOLTRONIC-QS, VOLTRONIC-QS-HEX, ZINTO PROTOCOLS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BESTUPS, INNOVART31, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, VOLTRONIC-QS, VOLTRONIC-QS-HEX, ZINTO PROTOCOLS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*ignoresab*::
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).
@@ -196,8 +196,8 @@ Safeguard against talking to the wrong one of several identical UPSes on the sam
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.


Q1 PROTOCOL
~~~~~~~~~~~
INNOVART31, Q1 PROTOCOLS
~~~~~~~~~~~~~~~~~~~~~~~~

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


BESTUPS, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, ZINTO PROTOCOLS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BESTUPS, INNOVART31, MECER, MEGATEC, MEGATEC/OLD, MUSTEK, Q1, ZINTO PROTOCOLS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

*test.battery.start* 'value'::
Perform a battery test for the duration of 'value' seconds (truncated to 60 seconds) [+60..5940+].
7 changes: 6 additions & 1 deletion docs/nut.dict
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
personal_ws-1.1 en 3264 utf-8
personal_ws-1.1 en 3269 utf-8
AAC
AAS
ABI
@@ -2065,6 +2065,7 @@ iDialog
iDowell
iManufacturer
iPlug
iProduct
iSerial
iUSB
ib
@@ -2108,6 +2109,7 @@ initups
inline
inlined
innotech
innovart
inode
inplace
installable
@@ -2920,6 +2922,7 @@ subdirectories
subdirectory
subdriver
subdriver's
subdrivername
subdrivers
subdrv
sublicense
@@ -3129,6 +3132,8 @@ usbhid
usbif
usbinfo
usbmisc
usbsubdriver
usbsubdrvname
usbups
usbus
usd
28 changes: 28 additions & 0 deletions docs/nutdrv_qx-subdrivers.txt
Original file line number Diff line number Diff line change
@@ -11,6 +11,33 @@ It consists of a core driver that handles most of the work of talking to the har

Adding support for a new UPS device is easy, because it requires only the creation of a new sub-driver.

[NOTE]
======
Due to historic reasons, there is a bit of a mess with terminology here:
among the set of driver parameters passed on command-line or via `ups.conf`,
the `subdriver` value is for Serial-over-USB dialect ("usbsubdriver" in code),
and the `protocol` value is for Qx dialect (but referred to as "subdriver"
in most of the documentation, and variable names in the code itself)..

An additional set of source code files named `nutdrv_qx_subdrivername.{c,h}`
defines a `subdriver_t` entry that is listed as in `subdrivers_list` array in
the main `nutdrv_qx.c` file. However, in `ups.conf` this entity is referred
to via the communication `protocol` keyword, if the end-user wants to pick
one explicitly (bypassing auto-detection).

Confusingly, there *is* also an optional USB `subdriver` setting (available
when the driver is built with USB support), for "Serial-over-USB subdriver
selection", corresponding to entries in the `usbsubdriver` array and several
`usbsubdrvname_command()` methods defined directly in `nutdrv_qx.c`.

There are also methods called `usbsubdrvname_subdriver()` which are called
via `qx_usb_id[]` array for USB VendorID/ProductID/iManufacturer/iProduct
based matching, and typically set the `subdriver_command` variable to point
to the corresponding `usbsubdrvname_command()` method when auto-detection
happens. Otherwise, this variable is set according to a text name requested
in the `subdriver` driver parameter.
======


Creating a subdriver
~~~~~~~~~~~~~~~~~~~~
@@ -1144,6 +1171,7 @@ You can then recompile +nutdrv_qx+, and start experimenting with the new subdriv
For more details, have a look at the currently available subdrivers:

- +nutdrv_qx_bestups.+{+c+,+h+}
- +nutdrv_qx_innovart31.+{+c+,+h+}
- +nutdrv_qx_masterguard.+{+c+,+h+}
- +nutdrv_qx_mecer.+{+c+,+h+}
- +nutdrv_qx_megatec.+{+c+,+h+}
2 changes: 2 additions & 0 deletions drivers/Makefile.am
Original file line number Diff line number Diff line change
@@ -379,6 +379,7 @@ nutdrv_qx_SOURCES += $(LIBUSB_IMPL) usb-common.c
nutdrv_qx_LDADD += $(LIBUSB_LIBS)
endif
NUTDRV_QX_SUBDRIVERS = nutdrv_qx_bestups.c nutdrv_qx_blazer-common.c \
nutdrv_qx_innovart31.c \
nutdrv_qx_masterguard.c \
nutdrv_qx_mecer.c nutdrv_qx_megatec.c nutdrv_qx_megatec-old.c \
nutdrv_qx_mustek.c nutdrv_qx_q1.c nutdrv_qx_voltronic.c \
@@ -404,6 +405,7 @@ dist_noinst_HEADERS = \
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_innovart31.h \
nutdrv_qx_masterguard.h \
nutdrv_qx_mecer.h nutdrv_qx_ablerex.h \
nutdrv_qx_megatec.h nutdrv_qx_megatec-old.h nutdrv_qx_mustek.h nutdrv_qx_q1.h nutdrv_qx_hunnox.h \
8 changes: 5 additions & 3 deletions drivers/nutdrv_qx.c
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
# define DRIVER_NAME "Generic Q* Serial driver"
#endif /* QX_USB */

#define DRIVER_VERSION "0.38"
#define DRIVER_VERSION "0.39"

#ifdef QX_SERIAL
# include "serial.h"
@@ -71,6 +71,7 @@
/* Include all known subdrivers */
#include "nutdrv_qx_bestups.h"
#include "nutdrv_qx_hunnox.h"
#include "nutdrv_qx_innovart31.h"
#include "nutdrv_qx_mecer.h"
#include "nutdrv_qx_megatec.h"
#include "nutdrv_qx_megatec-old.h"
@@ -97,6 +98,7 @@ static subdriver_t *subdriver_list[] = {
&masterguard_subdriver,
&hunnox_subdriver,
&ablerex_subdriver,
&innovart31_subdriver,
/* Fallback Q1 subdriver */
&q1_subdriver,
NULL
@@ -2913,7 +2915,7 @@ void upsdrv_help(void)
* are listed in usbsubdriver[] array (just above in this
* source file).
*/
printf("\nAcceptable values for 'subdriver' via -x or ups.conf in this driver: ");
printf("\nAcceptable values for USB 'subdriver' via -x or ups.conf in this driver: ");
for (i = 0; usbsubdriver[i].name != NULL; i++) {
if (i>0)
printf(", ");
@@ -3325,7 +3327,7 @@ void upsdrv_initups(void)

if (!regex_array[0] || !regex_array[1]) {
fatalx(EXIT_FAILURE,
"When specifying a subdriver, "
"When specifying a USB 'subdriver', "
"'vendorid' and 'productid' are mandatory.");
}

2 changes: 1 addition & 1 deletion drivers/nutdrv_qx_blazer-common.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* nutdrv_qx_blazer-common.c - Common functions/settings for nutdrv_qx_{mecer,megatec,megatec-old,mustek,q1,voltronic-qs,zinto}.{c,h}
/* nutdrv_qx_blazer-common.c - Common functions/settings for nutdrv_qx_{innovart31,mecer,megatec,megatec-old,mustek,q1,voltronic-qs,zinto}.{c,h}
*
* Copyright (C)
* 2013 Daniele Pezzini <[email protected]>
2 changes: 1 addition & 1 deletion drivers/nutdrv_qx_blazer-common.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* nutdrv_qx_blazer-common.h - Common functions/settings for nutdrv_qx_{mecer,megatec,megatec-old,mustek,q1,voltronic-qs,zinto}.{c,h}
/* nutdrv_qx_blazer-common.h - Common functions/settings for nutdrv_qx_{innovart31,mecer,megatec,megatec-old,mustek,q1,voltronic-qs,zinto}.{c,h}
*
* Copyright (C)
* 2013 Daniele Pezzini <[email protected]>
214 changes: 214 additions & 0 deletions drivers/nutdrv_qx_innovart31.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/* nutdrv_qx_innovart31.c - Subdriver for INNOVA RT 3/1 UPSes
*
* Copyright (C)
* 2024 Viktor Drobot <linux776@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_innovart31.h"

#define INNOVART31_VERSION "INNOVART31 0.01"

/* Internal function: used to convert kilo-values to their full representation */
static int innovart31_x1000(item_t *item, char *value, const size_t valuelen) {
float s = 0;

if (sscanf(item->value, "%f", &s) != 1) {
upsdebugx(2, "unparsable ss.ss %s", item->value);
return -1;
}

snprintf(value, valuelen, "%.2f", s * 1000.0);
return 0;
}
/* qx2nut lookup table */
static item_t innovart31_qx2nut[] = {

/*
* > [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]
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
* 0 1 2 3 4 5 6 7 8 9 10
*/

/* Common parameters */
{ "input.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 1, 5, "%.1f", 0, NULL, NULL, NULL },
{ "input.L1-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 1, 5, "%.1f", 0, NULL, NULL, NULL },
{ "input.L2-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 7, 11, "%.1f", 0, NULL, NULL, NULL },
{ "input.L3-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 13, 17, "%.1f", 0, NULL, NULL, NULL },
{ "input.frequency", 0, NULL, "Q6\r", "", 110, '(', "", 19, 22, "%.1f", 0, NULL, NULL, NULL },
{ "output.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 24, 28, "%.1f", 0, NULL, NULL, NULL },
/* { "output.L1-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 24, 28, "%.1f", 0, NULL, NULL, NULL },
{ "output.L2-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 30, 34, "%.1f", 0, NULL, NULL, NULL },
{ "output.L3-N.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 36, 40, "%.1f", 0, NULL, NULL, NULL },*/
{ "output.frequency", 0, NULL, "Q6\r", "", 110, '(', "", 42, 45, "%.1f", 0, NULL, NULL, NULL },
{ "ups.load", 0, NULL, "Q6\r", "", 110, '(', "", 47, 49, "%.0f", 0, NULL, NULL, NULL },
{ "ups.temperature", 0, NULL, "Q6\r", "", 110, '(', "", 71, 74, "%.1f", 0, NULL, NULL, NULL },
{ "battery.voltage", 0, NULL, "Q6\r", "", 110, '(', "", 59, 63, "%.2f", 0, NULL, NULL, qx_multiply_battvolt },
{ "battery.runtime", 0, NULL, "Q6\r", "", 110, '(', "", 76, 80, "%.0f", 0, NULL, NULL, NULL },
{ "battery.charge", 0, NULL, "Q6\r", "", 110, '(', "", 82, 84, "%.0f", 0, NULL, NULL, NULL },

/*
* > [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]
* 01234567890123456789012345678901234567890123456789012345678901234567890123456789
* 0 1 2 3 4 5 6 7
*/

/* Output consumption parameters */
{ "output.current", 0, NULL, "WA\r", "", 80, '(', "", 49, 53, "%.1f", 0, NULL, NULL, NULL },
{ "ups.realpower", 0, NULL, "WA\r", "", 80, '(', "", 37, 41, "%.1f", 0, NULL, NULL, innovart31_x1000 },
{ "ups.power", 0, NULL, "WA\r", "", 80, '(', "", 43, 47, "%.1f", 0, NULL, NULL, innovart31_x1000 },

/*
* > [BPS\r]
* < [(230.4 000.0 000.0 49.9\r]
* 012345678901234567890123
* 0 1 2
*/

/* Bypass parameters */
{ "input.bypass.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 1, 5, "%.1f", 0, NULL, NULL, NULL },
/* { "input.bypass.L1-N.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 1, 5, "%.1f", 0, NULL, NULL, NULL },
{ "input.bypass.L2-N.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 7, 11, "%.1f", 0, NULL, NULL, NULL },
{ "input.bypass.L3-N.voltage", 0, NULL, "BPS\r", "", 24, '(', "", 13, 17, "%.1f", 0, NULL, NULL, NULL },*/
{ "input.bypass.frequency", 0, NULL, "BPS\r", "", 24, '(', "", 19, 22, "%.1f", 0, NULL, NULL, NULL },

/*
* > [F\r]
* < [#230.0 087 288.0 50.0\r]
* 0123456789012345678901
* 0 1 2
*/

/* Nominal parameters (ratings) */
{ "input.voltage.nominal", 0, NULL, "F\r", "", 22, '#', "", 1, 5, "%.0f", QX_FLAG_STATIC, NULL, NULL, NULL },
{ "input.current.nominal", 0, NULL, "F\r", "", 22, '#', "", 7, 9, "%.1f", QX_FLAG_STATIC, NULL, NULL, NULL },
{ "battery.voltage.nominal", 0, NULL, "F\r", "", 22, '#', "", 11, 15, "%.1f", QX_FLAG_STATIC, NULL, NULL, NULL },
{ "input.frequency.nominal", 0, NULL, "F\r", "", 22, '#', "", 17, 20, "%.0f", QX_FLAG_STATIC, NULL, NULL, NULL },

/*
* > [FW?\r]
* < [05516-1100\r]
* 01234567890
* 0 1
*/

/* Firmware version */
{ "ups.firmware", 0, NULL, "FW?\r", "", 0, 0, "", 0, 0, "%s", QX_FLAG_STATIC, NULL, NULL, NULL },

/*
* > [SASV07?\r]
* < [GASV07DN05K10KB100004 \r]
* 0123456789012345678901234567
* 0 1 2
*/

/* UPS serial number */
{ "ups.serial", 0, NULL, "SASV07?\r", "", 28, 0, "", 7, 0, "%s", QX_FLAG_STATIC | QX_FLAG_TRIM, NULL, NULL, NULL },

/*
* > [Q1\r]
* < [(226.0 195.0 226.0 014 49.0 27.5 30.0 00001000\r]
* 01234567890123456789012345678901234567890123456
* 0 1 2 3 4
*/

/* Status bits */
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 38, 38, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Utility Fail (Immediate) */
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 39, 39, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Battery Low */
{ "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 */
{ "ups.alarm", 0, NULL, "Q1\r", "", 47, '(', "", 41, 41, NULL, 0, NULL, NULL, blazer_process_status_bits }, /* UPS Failed */
{ "ups.type", 0, NULL, "Q1\r", "", 47, '(', "", 42, 42, "%s", QX_FLAG_STATIC, NULL, NULL, blazer_process_status_bits }, /* UPS Type */
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 43, 43, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Test in Progress */
{ "ups.status", 0, NULL, "Q1\r", "", 47, '(', "", 44, 44, NULL, QX_FLAG_QUICK_POLL, NULL, NULL, blazer_process_status_bits }, /* Shutdown Active */
{ "ups.beeper.status", 0, NULL, "Q1\r", "", 47, '(', "", 45, 45, "%s", 0, NULL, NULL, blazer_process_status_bits }, /* Beeper status */

/* Instant commands */
/* NB: seems like beeper toggling doesn't work for Innova RT 3/1 by Ippon - UPS simply doesn't respond */
{ "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 innovart31_testing[] = {
{ "Q1\r", "(215.0 195.0 230.0 014 49.0 22.7 30.0 00000000\r", -1 },
{ "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 },
{ "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 },
{ "BPS\r", "(230.4 000.0 000.0 49.9\r", -1 },
{ "F\r", "#230.0 087 288.0 50.0\r", -1 },
{ "FW?\r", "05516-1100\r", -1 },
{ "SASV07?\r", "GASV07DN05K10KB100004 \r", -1 },
{ "S03\r", "", -1 },
{ "C\r", "", -1 },
{ "S02R0005\r", "", -1 },
{ "S.5R0000\r", "", -1 },
{ "T04\r", "ACK", -1 },
{ "TL\r", "ACK", -1 },
{ "T\r", "ACK", -1 },
{ "CT\r", "ACK", -1 },
{ NULL }
};
#endif /* TESTING */

/* Subdriver-specific initups */
static void innovart31_initups(void)
{
blazer_initups(innovart31_qx2nut);
}

/* Subdriver-specific initinfo */
static void innovart31_initinfo(void)
{
dstate_setinfo("input.phases", "%u", 3);
dstate_setinfo("input.bypass.phases", "%u", 1);
dstate_setinfo("output.phases", "%u", 1);
}

/* Subdriver interface */
subdriver_t innovart31_subdriver = {
INNOVART31_VERSION,
blazer_claim,
innovart31_qx2nut,
innovart31_initups,
innovart31_initinfo,
blazer_makevartable,
"ACK",
"NAK\r",
#ifdef TESTING
innovart31_testing,
#endif /* TESTING */
};
29 changes: 29 additions & 0 deletions drivers/nutdrv_qx_innovart31.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* nutdrv_qx_innovart31.h - Subdriver for INNOVA RT 3/1 UPSes
*
* Copyright (C)
* 2024 Viktor Drobot <linux776@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_INNOVART31_H
#define NUTDRV_QX_INNOVART31_H

#include "nutdrv_qx.h"

extern subdriver_t innovart31_subdriver;

#endif /* NUTDRV_QX_INNOVART31_H */