[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