[Nut-upsdev] Patch for optiups to support Zinto D from ONLINE
Peter Selinger
selinger at mathstat.dal.ca
Sun Nov 26 17:40:44 CET 2006
Matthias,
NUT drivers should always detect devices automatically if possible,
rather than requiring the user to set a variable such as "zinto".
Can you modify upsdrv_initinfo to detect the device type based on the
model string (and/or if necessary, based on ups.mfr)? -- Peter
Matthias Goebl wrote:
>
>
> Hi Arnaud,
> Hi Scott,
> Hi list,
>
> Here is a patch to support the Zinto D from ONLINE USV-Systeme AG.
> I already sent a version to Russell Kroll (2006-04-09), without no response
> and I cannot find support for Zinto in svn until now.
> I found a discussion on this list about the Xanto from ONLINE, but the Zinto
> seems to use different commands.
>
> The commands are quite similar to those for Opti-UPS, so I decided not to fork,
> but to patch optiups. Where I found differences, I added if(testvar(OPTI_ZINTO)).
> As soon as someone adds another device with similar commands, one could decide
> how to differentiate within the driver (where to use select-case).
> What do you think?
>
> Yours,
> Matthias
>
> --82I3+IH0IqGh5yIs
> Content-Type: text/plain; charset=us-ascii
> Content-Disposition: attachment; filename="nut.zinto.patch.mg"
>
> Index: data/driver.list
> ===================================================================
> --- data/driver.list (revision 606)
> +++ data/driver.list (working copy)
> @@ -318,6 +318,7 @@
> "Oneac" "EG/ON Series" "advanced interface" "oneac"
>
> "Online" "P-Series" "" "genericups upstype=14"
> +"Online" "Zinto D" "" "optiups zinto=1"
>
> "OnLite" "AQUA" "50" "megatec"
>
> Index: man/optiups.8
> ===================================================================
> --- man/optiups.8 (revision 606)
> +++ man/optiups.8 (working copy)
> @@ -52,6 +52,12 @@
> nut should power down the system soon after you pull the plug. When you are done
> testing, you should remove this flag.
>
> +.IP "zinto"
> +
> +Set this flag if your UPS is a Zinto D (or similar) from ONLINE USV-Systeme AG
> +(www.online-ups.com). The commands are quite similar to those for Opti-UPS,
> +but there are minor differences. The UPS has an additional switchable outlet.
> +
> .SH BUGS
>
> On the 420E, ups.serial and ups.temperature are unsupported features. This
> Index: drivers/optiups.c
> ===================================================================
> --- drivers/optiups.c (revision 606)
> +++ drivers/optiups.c (working copy)
> @@ -3,6 +3,9 @@
> Copyright (C) 1999 Russell Kroll <rkroll at exploits.org>
> Copyright (C) 2006 Scott Heavner [Use my alioth acct: sheavner]
>
> + Support for Zinto D from ONLINE USV (only minor differences to OptiSafe UPS)
> + added by Matthias Goebl <matthias.goebl at goebl.net>
> +
> 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
> @@ -50,6 +53,7 @@
> #define OPTI_MINPOLL "status_only"
> #define OPTI_FAKELOW "fake_lowbatt"
> #define OPTI_NOWARN_NOIMP "nowarn_noimp"
> +#define OPTI_ZINTO "zinto"
>
> /* All serial commands put their response in the same buffer space */
> static char _buf[256];
> @@ -79,6 +83,14 @@
> { "FF", "input.frequency", 0.1 },
> { "BT", "ups.temperature" },
> };
> +static ezfill _pollv_zinto[] = {
> + { "NV", "input.voltage", 2.0 },
> + { "OL", "ups.load", 1.0 },
> + { "OV", "output.voltage", 2.0 },
> + { "OF", "output.frequency", 0.1 },
> + { "NF", "input.frequency", 0.1 },
> + { "BT", "ups.temperature" },
> +};
>
> /* model "IO" is parsed differently in upsdrv_initinfo() */
> static ezfill _initv[] = {
> @@ -105,6 +117,10 @@
> r=-2;
> upsdebugx(1, "READ: <unsupported command>");
> }
> + if ( _buf[0] == 0x06 )
> + {
> + upsdebugx(2, "READ: <command done>");
> + }
> else
> {
> upsdebugx(2, "READ: \"%s\"", _buf );
> @@ -125,6 +141,7 @@
> {
> upsdebugx(2, "SEND: \"%s\"", cmd );
> ser_send( upsfd, cmd );
> + if ( testvar(OPTI_ZINTO) ) ser_send( upsfd, "\r\n" );
> return optireadline();
> }
>
> @@ -179,12 +196,26 @@
> {
> /* You do realize this will kill power to ourself. Would probably only
> * be useful for killing power for a slave computer */
> + if ( testvar(OPTI_ZINTO) )
> + {
> + optiquery( "Ct1" );
> + optiquery( "Cs0000000" );
> + sleep(2);
> + return STAT_INSTCMD_HANDLED;
> + }
> optiquery( "Ct0" );
> optiquery( "Cs00000000" );
> return STAT_INSTCMD_HANDLED;
> }
> else if (!strcasecmp(cmdname, "load.on"))
> {
> + if ( testvar(OPTI_ZINTO) )
> + {
> + optiquery( "Ct1" );
> + optiquery( "Cu0000000" );
> + sleep(2);
> + return STAT_INSTCMD_HANDLED;
> + }
> optiquery( "Ct0" );
> optiquery( "Cu00000000" );
> return STAT_INSTCMD_HANDLED;
> @@ -193,6 +224,13 @@
> {
> /* This shuts down the UPS. When the power returns to the UPS,
> * it will power back up in its default state. */
> + if ( testvar(OPTI_ZINTO) )
> + {
> + optiquery( "Ct1" );
> + optiquery( "Cu0000010" );
> + optiquery( "Cs0000001" );
> + return STAT_INSTCMD_HANDLED;
> + }
> optiquery( "Ct1" );
> optiquery( "Cs00000010" );
> return STAT_INSTCMD_HANDLED;
> @@ -202,6 +240,12 @@
> /* This actually stays off as long as the batteries hold,
> * if the line power comes back before the batteries die,
> * the UPS will never powerup its output stage!!! */
> + if ( testvar(OPTI_ZINTO) )
> + {
> + optiquery( "Ct1" );
> + optiquery( "Cs0000001" );
> + return STAT_INSTCMD_HANDLED;
> + }
> optiquery( "Ct0" );
> optiquery( "Cs00000010" );
> return STAT_INSTCMD_HANDLED;
> @@ -217,11 +261,52 @@
> return STAT_INSTCMD_UNKNOWN;
> }
>
> +/* Handle variable setting */
> +static int setvar(const char *varname, const char *val)
> +{
> + int status;
>
> + if (sscanf(val, "%d", &status) != 1) {
> + return STAT_SET_UNKNOWN;
> + }
> +
> + if (strcasecmp(varname, "outlet.1.switch") == 0) {
> + status = status==1 ? 1 : 0;
> + dstate_setinfo( "outlet.1.switch", "%d", status);
> + optiquery(status ? "Oi11" : "Oi10");
> + dstate_dataok();
> + return STAT_SET_HANDLED;
> + }
> +
> + return STAT_SET_UNKNOWN;
> +}
> +
> void upsdrv_initinfo(void)
> {
> int r;
>
> + if ( testvar(OPTI_ZINTO) )
> + {
> + /* If UPS is off, switch it on first */
> + /* Online-UPS send only "2" when off, without "\r\n" */
> + /* Therefore without power we cannot identify the ups */
> + if ( optiquery( "AG" ) < 1 )
> + {
> + ser_send( upsfd, "AG\r\n" );
> + r = ser_get_char(upsfd, &_buf[0], 1, 0);
> + if ( r == 1 && _buf[0] == '2' )
> + {
> + upslogx( LOG_WARNING, "ups was off, switched on" );
> + optiquery( "Ct1" );
> + optiquery( "Cu0000000" );
> + sleep(12);
> + }
> + }
> + optiquery( "Om11" );
> + optiquery( "Om21" );
> + optiquery( "ON" );
> + }
> +
> dstate_setinfo("driver.version.internal", "%s", DRV_VERSION);
>
> optifill( _initv, sizeof(_initv)/sizeof(_initv[0]) );
> @@ -248,15 +333,45 @@
> dstate_addcmd("test.failure.start");
> dstate_addcmd("load.off");
> dstate_addcmd("load.on");
> - dstate_addcmd("shutdown.stop");
> + if( !testvar(OPTI_ZINTO) )
> + dstate_addcmd("shutdown.stop");
> dstate_addcmd("shutdown.return");
> dstate_addcmd("shutdown.stayoff");
> upsh.instcmd = instcmd;
> +
> + if ( testvar(OPTI_ZINTO) )
> + {
> + dstate_setinfo("outlet.0.desc", "%s", "Main Outlet 1+2");
> + dstate_setinfo("outlet.1.desc", "%s", "Switchable Outlet 3+4");
> + dstate_setinfo("outlet.0.id", "%d", 1);
> + dstate_setinfo("outlet.1.id", "%d", 2);
> + dstate_setinfo("outlet.0.switchable", "%d", 0);
> + dstate_setinfo("outlet.1.switchable", "%d", 1);
> + dstate_setinfo("outlet.1.switch", "%d", 1);
> + dstate_setflags("outlet.1.switch", ST_FLAG_RW | ST_FLAG_STRING);
> + dstate_setaux("outlet.1.switch", 1);
> + upsh.setvar = setvar;
> + }
> }
>
> void upsdrv_updateinfo(void)
> {
> int r = optiquery( "AG" );
> +
> + /* Online-UPS send only "2" when off, without "\r\n" */
> + if ( r < 1 && testvar(OPTI_ZINTO) )
> + {
> + ser_send( upsfd, "AG\r\n" );
> + r = ser_get_char(upsfd, &_buf[0], 1, 0);
> + if ( r == 1 && _buf[0] == '2' )
> + {
> + status_init();
> + status_set("OFF");
> + status_commit();
> + return;
> + }
> + }
> +
> if ( r < 1 )
> {
> upslogx(LOG_ERR, "can't retrieve ups status" );
> @@ -289,7 +404,10 @@
> return;
>
> /* read some easy settings */
> - optifill( _pollv, sizeof(_pollv)/sizeof(_pollv[0]) );
> + if ( testvar(OPTI_ZINTO) )
> + optifill( _pollv_zinto, sizeof(_pollv_zinto)/sizeof(_pollv_zinto[0]) );
> + else
> + optifill( _pollv, sizeof(_pollv)/sizeof(_pollv[0]) );
>
> /* Battery voltage is harder */
> r = optiquery( "BV" );
> @@ -330,6 +448,24 @@
> * turn off ups if on battery */
> optiquery( "Ct1" );
>
> + /* What happens, if the power comes back *after* reading the ups status and
> + * before the shutdown command? For "Online-UPS Zinto D" *always* asking for
> + * "shutdown shortly and power-up later" works perfectly, because it forces
> + * a power cycle, even for the named race condition.*/
> + * For Opti-UPS I have no information, so I didn't dare to change it.
> + * BTW, Zinto expects only 7 digits after Cu/Cs.
> + * (Matthias Goebl)
> + */
> + if ( testvar(OPTI_ZINTO) )
> + {
> + /* On line power: Power up in 60 seconds (30 seconds after the following shutdown) */
> + /* On battery: Power up when the line power returns */
> + optiquery( "Cu0000060" );
> + /* Shutdown in 30 seconds */
> + optiquery( "Cs0000030" );
> + return;
> + }
> +
> /* Just cycling power, schedule output stage to come back on in 60 seconds */
> if ( !(s&OPTISBIT_ON_BATTERY_POWER) )
> optiquery( "Cu00000600" );
> @@ -349,6 +485,7 @@
> addvar(VAR_FLAG, OPTI_MINPOLL, "Only poll for critical status variables");
> addvar(VAR_FLAG, OPTI_FAKELOW, "Fake a low battery status" );
> addvar(VAR_FLAG, OPTI_NOWARN_NOIMP, "Supress warnings of unsupported commands");
> + addvar(VAR_FLAG, OPTI_ZINTO, "UPS is a Zinto D from ONLINE UPS");
> }
>
> void upsdrv_banner(void)
>
> --82I3+IH0IqGh5yIs
> Content-Type: text/plain; charset="us-ascii"
> MIME-Version: 1.0
> Content-Transfer-Encoding: 7bit
> Content-Disposition: inline
>
> _______________________________________________
> Nut-upsdev mailing list
> Nut-upsdev at lists.alioth.debian.org
> http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev
> --82I3+IH0IqGh5yIs--
>
More information about the Nut-upsdev
mailing list