Пример #1
0
static int setvar(const char *varname, const char *val)
{
	dummy_info_t *item;

	upsdebugx(2, "entering setvar(%s, %s)", varname, val);

	/* FIXME: the below is only valid if (mode == MODE_DUMMY)
	 * if (mode == MODE_REPEATER) => forward
	 * if (mode == MODE_META) => ?
	 */
	if (!strncmp(varname, "ups.status", 10))
	{
		status_init();
		 /* FIXME: split and check values (support multiple values), à la usbhid-ups */
		status_set(val);
		status_commit();

		return STAT_SET_HANDLED;
	}

	/* Check variable validity */
	if (!is_valid_data(varname))
	{
		upsdebugx(2, "setvar: invalid variable name (%s)", varname);
		return STAT_SET_UNKNOWN;
	}

	/* Check value validity */
	if (!is_valid_value(varname, val))
	{
		upsdebugx(2, "setvar: invalid value (%s) for variable (%s)", val, varname);
		return STAT_SET_UNKNOWN;
	}

	/* If value is empty, remove the variable (FIXME: do we need
	 * a magic word?) */
	if (strlen(val) == 0)
	{
		dstate_delinfo(varname);
	}
	else
	{
		dstate_setinfo(varname, "%s", val);

		if ( (item = find_info(varname)) != NULL)
		{
			dstate_setflags(item->info_type, item->info_flags);

			/* Set max length for strings, if needed */
			if (item->info_flags & ST_FLAG_STRING)
				dstate_setaux(item->info_type, item->info_len);
		}
	}
	return STAT_SET_HANDLED;
}
Пример #2
0
static int parse_args(int numargs, char **arg)
{
	if (numargs < 1) {
		return 0;
	}

	if (!strcasecmp(arg[0], "PONG")) {
		upsdebugx(3, "Got PONG from UPS");
		return 1;
	}

	if (!strcasecmp(arg[0], "DUMPDONE")) {
		upsdebugx(3, "UPS: dump is done");
		dumpdone = 1;
		return 1;
	}

	if (!strcasecmp(arg[0], "DATASTALE")) {
		dstate_datastale();
		return 1;
	}

	if (!strcasecmp(arg[0], "DATAOK")) {
		dstate_dataok();
		return 1;
	}

	if (numargs < 2) {
		return 0;
	}

	/* DELINFO <var> */
	if (!strcasecmp(arg[0], "DELINFO")) {
		dstate_delinfo(arg[1]);
		return 1;
	}

	if (numargs < 3) {
		return 0;
	}

	/* SETINFO <varname> <value> */
	if (!strcasecmp(arg[0], "SETINFO")) {

		if (!strncasecmp(arg[1], "driver.", 7) ||
				!strcasecmp(arg[1], "battery.charge.low") ||
				!strcasecmp(arg[1], "battery.runtime.low") ||
				!strncasecmp(arg[1], "ups.delay.", 10) ||
				!strncasecmp(arg[1], "ups.timer.", 10)) {
			/* don't pass on upstream driver settings */
			return 1;
		}

		if (!strcasecmp(arg[1], "ups.status")) {
			snprintf(ups.status, sizeof(ups.status), "%s", arg[2]);

			online = strstr(ups.status, "OL") ? 1 : 0;

			if (ups.timer.shutdown > 0) {
				dstate_setinfo("ups.status", "FSD %s", ups.status);
				return 1;
			}
		}

		if (!strcasecmp(arg[1], "battery.charge")) {
			battery.charge.act = strtod(arg[2], NULL);

			dstate_setinfo("battery.charge.low", "%g", battery.charge.low);
			dstate_setflags("battery.charge.low", ST_FLAG_RW | ST_FLAG_STRING);
			dstate_setaux("battery.charge.low", 3);
		}

		if (!strcasecmp(arg[1], "battery.runtime")) {
			battery.runtime.act = strtod(arg[2], NULL);

			dstate_setinfo("battery.runtime.low", "%g", battery.runtime.low);
			dstate_setflags("battery.runtime.low", ST_FLAG_RW | ST_FLAG_STRING);
			dstate_setaux("battery.runtime.low", 4);
		}

		dstate_setinfo(arg[1], "%s", arg[2]);
		return 1;
	}

	return 0;
}
Пример #3
0
void upsdrv_initinfo(void)
{
	char response[MAX_RESPONSE_LENGTH];
	unsigned int min_low_transfer, max_low_transfer;
	unsigned int min_high_transfer, max_high_transfer;
	unsigned int i;
	char *ptr;

	if (!init_comm())
		fatalx(EXIT_FAILURE, "Unable to detect Tripp Lite SmartOnline UPS on port %s\n",
		        device_path);
	min_low_transfer = max_low_transfer = 0;
	min_high_transfer = max_high_transfer = 0;

	/* get all the read-only fields here */
	if (do_command(POLL, MANUFACTURER, "", response) > 0)
		dstate_setinfo("ups.mfr", "%s", response);
	if (do_command(POLL, MODEL, "", response) > 0)
		dstate_setinfo("ups.model", "%s", response);
	if (do_command(POLL, VERSION_CMD, "", response) > 0)
		dstate_setinfo("ups.firmware", "%s", response);
	if (do_command(POLL, RATINGS, "", response) > 0) {
		ptr = field(response, 0);
		if (ptr)
			dstate_setinfo("input.voltage.nominal", "%d",
			               atoi(ptr));
		ptr = field(response, 2);
		if (ptr) {
			dstate_setinfo("output.voltage.nominal", "%d",
			               atoi(ptr));
		}
		ptr = field(response, 14);
		if (ptr)
			dstate_setinfo("battery.voltage.nominal", "%d",
			               atoi(ptr));
		ptr = field(response, 10);
		if (ptr)
			min_low_transfer = atoi(ptr);
		ptr = field(response, 9);
		if (ptr)
			max_low_transfer = atoi(ptr);
		ptr = field(response, 12);
		if (ptr)
			min_high_transfer = atoi(ptr);
		ptr = field(response, 11);
		if (ptr)
			max_high_transfer = atoi(ptr);
	}
	if (do_command(POLL, OUTLET_RELAYS, "", response) > 0)
		ups.outlet_banks = atoi(response);
	/* define things that are settable */
	if (get_identification()) {
		dstate_setflags("ups.id", ST_FLAG_RW | ST_FLAG_STRING);
		dstate_setaux("ups.id", 100);
	}
	if (get_transfer_voltage_low() && max_low_transfer) {
		dstate_setflags("input.transfer.low", ST_FLAG_RW);
		for (i = min_low_transfer; i <= max_low_transfer; i++)
			dstate_addenum("input.transfer.low", "%d", i);
	}
	if (get_transfer_voltage_high() && max_low_transfer) {
		dstate_setflags("input.transfer.high", ST_FLAG_RW);
		for (i = min_high_transfer; i <= max_high_transfer; i++)
			dstate_addenum("input.transfer.high", "%d", i);
	}
	if (get_sensitivity()) {
		dstate_setflags("input.sensitivity", ST_FLAG_RW);
		for (i = 0; i < sizeof(sensitivity) / sizeof(sensitivity[0]);
		     i++)
			dstate_addenum("input.sensitivity", "%s",
			               sensitivity[i].name);
	}
	if (ups.outlet_banks) {
		dstate_addcmd("load.off");
		dstate_addcmd("load.on");
	}
	dstate_addcmd("shutdown.reboot");
	dstate_addcmd("shutdown.reboot.graceful");
	dstate_addcmd("shutdown.return");
#if 0 /* doesn't work */
	dstate_addcmd("shutdown.stayoff");
#endif
	dstate_addcmd("shutdown.stop");
	dstate_addcmd("test.battery.start");
	dstate_addcmd("test.battery.stop");

	/* add all the variables that change regularly */
	upsdrv_updateinfo();

	upsh.instcmd = instcmd;
	upsh.setvar = setvar;

	printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"),
	       dstate_getinfo("ups.model"), device_path);
}
Пример #4
0
/* check which commands this ups supports.
 * Returns TRUE if command list was recieved, FALSE otherwise */
static int upsc_commandlist(void)
{
	char buf[UPSC_BUFLEN];
	cmd_t *cp;

	upsc_flush_input();
	upscsend("UPCL");
	while (1) {
		upscrecv(buf);
		if (strlen(buf) == 0) {
			upslogx(LOG_ERR, "Missing UPCL after UPCL");
			return 0;
		}
		upsdebugx(2, "Supports command: %s", buf);

		if (strcmp(buf, "UPBS") == 0)
			can_upbs = 1;
		else if (strcmp(buf, "UPPM") == 0)
			can_uppm = 1;
		else if (strcmp(buf, "UPID") == 0)
			can_upid = 1;
		else if (strcmp(buf, "UPDA") == 0)
			can_upda = 1;
		else if (strcmp(buf, "UPDT") == 0)
			can_updt = 1;
		else if (strcmp(buf, "UPTM") == 0)
			can_uptm = 1;
		else if (strcmp(buf, "UPSD") == 0)
			can_upsd = 1;
		else if (strcmp(buf, "UPPC") == 0)
			can_uppc = 1;

		for (cp = commands; cp->cmd; cp++) {
			if (cp->upsc && strcmp(cp->upsc, buf) == 0) {
				upsdebugx(1, "instcmd: %s %s", cp->cmd, cp->upsc);
				dstate_addcmd(cp->cmd);
				cp->enabled = 1;
	            break;
			}
		}

		for (cp = variables; cp->cmd; cp++) {
			if (cp->upsc && strcmp(cp->upsc, buf) == 0) {
				upsdebugx(1, "setvar: %s %s", cp->cmd, cp->upsc);
				cp->enabled = 1;
				break;
			}
		}

		if (strcmp(buf, "UPCL") == 0)
			break;
	}

	for (cp = variables; cp->cmd; cp++) {
		if (cp->enabled) {
			upsc_getvalue(cp->upsc, "0000", cp->upsp, cp->cmd, NULL);
			dstate_setflags(cp->cmd, ST_FLAG_RW | ST_FLAG_STRING);
			dstate_setaux(cp->cmd, 7);
		}
	}

	return 1;
}
Пример #5
0
void upsdrv_initinfo(void)
{
	dummy_info_t *item;

	switch (mode)
	{
		case MODE_DUMMY:
			/* Initialise basic essential variables */
			for ( item = nut_data ; item->info_type != NULL ; item++ )
			{
				if (item->drv_flags & DU_FLAG_INIT)
				{
					dstate_setinfo(item->info_type, "%s", item->default_value);
					dstate_setflags(item->info_type, item->info_flags);

					/* Set max length for strings, if needed */
					if (item->info_flags & ST_FLAG_STRING)
						dstate_setaux(item->info_type, item->info_len);
				}
			}

			/* Now get user's defined variables */
			if (parse_data_file(upsfd) < 0)
				upslogx(LOG_NOTICE, "Unable to parse the definition file %s", device_path);

			/* Initialize handler */
			upsh.setvar = setvar;

			dstate_dataok();
			break;
		case MODE_META:
		case MODE_REPEATER:
			/* Obtain the target name */
			if (upscli_splitname(device_path, &client_upsname, &hostname, &port) != 0)
			{
				fatalx(EXIT_FAILURE, "Error: invalid UPS definition.\nRequired format: upsname[@hostname[:port]]");
			}
			/* Connect to the target */
			ups = xmalloc(sizeof(*ups));
			if (upscli_connect(ups, hostname, port, UPSCLI_CONN_TRYSSL) < 0)
			{
				fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
			}
			else
			{
				upsdebugx(1, "Connected to %s@%s", client_upsname, hostname);
			}
			if (upsclient_update_vars() < 0)
			{
				/* check for an old upsd */
				if (upscli_upserror(ups) == UPSCLI_ERR_UNKCOMMAND)
				{
					fatalx(EXIT_FAILURE, "Error: upsd is too old to support this query");
				}
				fatalx(EXIT_FAILURE, "Error: %s", upscli_strerror(ups));
			}
			/* FIXME: commands and settable variable! */
			break;
		default:
		case MODE_NONE:
			fatalx(EXIT_FAILURE, "no suitable definition found!");
			break;
	}
	upsh.instcmd = instcmd;

	dstate_addcmd("load.off");
}
Пример #6
0
void upsdrv_initinfo(void)
{
	int i,j, k;
	int VRange=0;
	int timevalue;
	int RetValue;
	char buffer[256], buffer2[32];

	/* All families should reply to this request so we can confirm that it is
	 *  an ONEAC UPS
	 */

	ser_flush_in(upsfd,"",0);
	ser_send(upsfd,"%c%s",GET_FAMILY,COMMAND_END);

	if(OneacGetResponse (buffer, sizeof(buffer), 2))
	{
		fatalx(EXIT_FAILURE, "Serial timeout with ONEAC UPS on %s\n",
																device_path);
	}
	else
	{
		if (strncmp(buffer,FAMILY_ON,FAMILY_SIZE) != 0 && 
			strncmp(buffer,FAMILY_OZ,FAMILY_SIZE) != 0 &&
			strncmp(buffer,FAMILY_OB,FAMILY_SIZE) != 0 && 
			strncmp(buffer,FAMILY_EG,FAMILY_SIZE) != 0)
		{
			fatalx(EXIT_FAILURE, "Did not find an ONEAC UPS on %s\n",
																device_path);	
		}
	}

	/* UPS Model (either EG, ON, OZ or OB series of UPS) */
	strncpy(UpsFamily, buffer, FAMILY_SIZE);
	UpsFamily[2] = '\0';
	dstate_setinfo("device.model", "%s",UpsFamily);
	printf("Found %s family of Oneac UPS\n", UpsFamily);

	dstate_setinfo("ups.type", "%s", "Line Interactive");
	
	dstate_addcmd("test.battery.start.quick");
	dstate_addcmd("test.battery.stop");
	dstate_addcmd("test.failure.start");
	dstate_addcmd("shutdown.return");
	dstate_addcmd("shutdown.stop");
	dstate_addcmd("shutdown.reboot");

	upsh.setvar = setcmd;
	upsh.instcmd = instcmd;

	/* set some stuff that shouldn't change after initialization */
	/* this stuff is common to all families of UPS */

	ser_send(upsfd,"%c%s",GET_ALL,COMMAND_END);

	if (strncmp(UpsFamily, FAMILY_EG, FAMILY_SIZE) == 0)
	{
		RetValue = OneacGetResponse (buffer, sizeof(buffer), 
														GETALL_EG_RESP_SIZE);
	}
	else
	{
		RetValue = OneacGetResponse (buffer, sizeof(buffer), GETALL_RESP_SIZE);
	}

	if(RetValue)
	{
		fatalx(EXIT_FAILURE, "Serial timeout(2) with ONEAC UPS on %s\n",
																device_path);
	}

	/* Manufacturer */
	dstate_setinfo("device.mfr", "%.5s", buffer);

	/*firmware revision*/
	dstate_setinfo("ups.firmware", "%.3s",buffer+7);

	/*nominal AC frequency setting --either 50 or 60*/
	dstate_setinfo("input.frequency.nominal", "%.2s", buffer+20);
	dstate_setinfo("output.frequency.nominal", "%.2s", buffer+20);

	/* Shutdown delay in seconds...can be changed by user */
	if (getval("offdelay") == NULL)
		dstate_setinfo("ups.delay.shutdown", "0");
	else
		dstate_setinfo("ups.delay.shutdown", "%s", getval("offdelay"));

	dstate_setflags("ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW);
	dstate_setaux("ups.delay.shutdown", GET_SHUTDOWN_RESP_SIZE);
	
	/* Setup some ON/OZ/OB only stuff ... i.e. not EG */

	if (strncmp(UpsFamily, FAMILY_EG, FAMILY_SIZE) != 0)
	{
		dstate_addcmd("reset.input.minmax");

		/*nominal input voltage*/

		VRange = buffer[26];			/* Keep for later use also */
		
		switch (VRange)					/* Will be '1' or '2' */
		{
			case V120AC:
				dstate_setinfo("input.voltage.nominal", "120");
				dstate_setinfo("output.voltage.nominal", "120");
				break;

			case V230AC:
				dstate_setinfo("input.voltage.nominal", "230");
				dstate_setinfo("output.voltage.nominal", "230");
				break;

			default:
				upslogx(LOG_INFO,"Oneac: "
					"Invalid nom voltage parameter from UPS [%c]", VRange);
		}
	}
		  
	/* Setup some OZ/OB only stuff */
	
	if ((strncmp (UpsFamily, FAMILY_OZ, FAMILY_SIZE) == 0) ||
		(strncmp (UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0))
	{
		dstate_addcmd("test.panel.start");
		dstate_addcmd("test.battery.start.deep");
		dstate_addcmd("beeper.enable");
		dstate_addcmd("beeper.disable");
		dstate_addcmd("beeper.mute");
		
		dstate_setaux("ups.delay.shutdown", GETX_SHUTDOWN_RESP_SIZE);

		ser_flush_in(upsfd,"",0);
		ser_send(upsfd,"%c%s",GETX_ALL_2,COMMAND_END);
		if(OneacGetResponse (buffer, sizeof(buffer), GETX_ALL2_RESP_SIZE))
		{
			fatalx(EXIT_FAILURE, "Serial timeout(3) with ONEAC UPS on %s\n",
																device_path);
		}

		/* Low and high output trip points */
		EliminateLeadingZeroes (buffer+73, 3, buffer2, sizeof(buffer2));
		dstate_setinfo("input.transfer.low", "%s", buffer2);
		dstate_setflags("input.transfer.low", ST_FLAG_STRING | ST_FLAG_RW );
		dstate_setaux("input.transfer.low", 3);

		EliminateLeadingZeroes (buffer+76, 3, buffer2, sizeof(buffer2));
		dstate_setinfo("input.transfer.high", "%s", buffer2);
		dstate_setflags("input.transfer.high", ST_FLAG_STRING | ST_FLAG_RW);
		dstate_setaux("input.transfer.high", 3);

		/* Restart delay */
		EliminateLeadingZeroes (buffer+84, 4, buffer2, sizeof(buffer2));
		dstate_setinfo("ups.delay.start", "%s", buffer2);
		dstate_setflags("ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW);
		dstate_setaux("ups.delay.start", 4);
		
		/* Low Batt at time */
		strncpy(buffer2, buffer+82, 2);
		buffer2[2]='\0';
		timevalue = atoi(buffer2) * 60;		/* Change minutes to seconds */
		dstate_setinfo("battery.runtime.low", "%d",timevalue);
		dstate_setflags("battery.runtime.low", ST_FLAG_STRING | ST_FLAG_RW);
		dstate_setaux("battery.runtime.low", 2);
		
		/*Get the actual model string for ON UPS reported as OZ/OB family*/

		/*UPS Model (full string)*/
		memset(buffer2, '\0', 32);
		strncpy(buffer2, buffer+5, 10);
		for (i = 9; i >= 0 && buffer2[i] == ' '; --i) 
		{
			buffer2[i] = '\0';
		}

		dstate_setinfo("device.model", "%s", buffer2);
		
		/* Serial number */
		dstate_setinfo("device.serial", "%.4s-%.4s", buffer+18, buffer+22);
		printf("Found %.10s UPS with serial number %.4s-%.4s\n", 
												buffer2, buffer+18, buffer+22);
		
		/* Manufacture Date */
		dstate_setinfo("ups.mfr.date", "%.6s (yymmdd)", buffer+38);

		/* Battery Replace Date */
		dstate_setinfo("battery.date", "%.6s (yymmdd)", buffer+44);
		dstate_setflags("battery.date", ST_FLAG_STRING | ST_FLAG_RW);
		dstate_setaux("battery.date", 6);
		
		/* Real power nominal */
		EliminateLeadingZeroes (buffer+55, 5, buffer2, sizeof(buffer2));
		dstate_setinfo("ups.realpower.nominal", "%s", buffer2);

		/* Set up ups.start.auto to be writable */
		dstate_setinfo("ups.start.auto", "yes");
		dstate_setflags("ups.start.auto", ST_FLAG_STRING | ST_FLAG_RW);
		dstate_setaux("ups.start.auto", 3);

		/* Get output window min/max points from OB or OZ v1.9 or later */
		if ((strncmp (UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0) ||
			(strcmp (dstate_getinfo("ups.firmware"), MIN_ALLOW_FW) >= 0 ))
		{
			upsdebugx (2,"Can get output window min/max! (%s)", 
												dstate_getinfo("ups.firmware"));

			ser_send(upsfd,"%s%s",GETX_ALLOW_RANGE,COMMAND_END);
			if(OneacGetResponse (buffer, sizeof(buffer), GETX_RANGE_RESP_SIZE))
			{
				fatalx(EXIT_FAILURE, 
						"Serial timeout(4) with ONEAC UPS on %s\n",device_path);
			}

			strncpy(buffer2, buffer, 3);
			buffer2[3]='\0';
			i = atoi(buffer2);		/* Minimum voltage */
			
			strncpy(buffer2, buffer+4, 3);
			j = atoi(buffer2);		/* Maximum voltage */

			strncpy(buffer2, buffer+8, 2);
			buffer2[2]='\0';
			k = atoi(buffer2);		/* Spread between */
			
			dstate_setinfo("input.transfer.low.min", "%3d", i);
			dstate_setinfo("input.transfer.low.max", "%3d", j-k);
			dstate_setinfo("input.transfer.high.min", "%3d", i+k);
			dstate_setinfo("input.transfer.high.max", "%3d", j);

		}
		else
		{
			/* Use default values from firmware */
			upsdebugx (2,"Using trip defaults (%s)...", 
												dstate_getinfo("ups.firmware"));

			switch (VRange)				/* Held from initial use */
			{
				case V120AC:
					dstate_setinfo("input.transfer.low.min", "90");
					dstate_setinfo("input.transfer.low.max", "120");
					dstate_setinfo("input.transfer.high.min", "110");
					dstate_setinfo("input.transfer.high.max", "140");
					break;

				case V230AC:
					dstate_setinfo("input.transfer.low.min", "172");
					dstate_setinfo("input.transfer.low.max", "228");
					dstate_setinfo("input.transfer.high.min", "212");
					dstate_setinfo("input.transfer.high.max", "268");
					break;

				default:
					;

			}
		}
	}
}
Пример #7
0
void upsdrv_initinfo(void)
{
	unsigned char my_answer[255];
	char serial[13];
	int res, i;

	/* Initial setup of variables */
#ifdef EXTRADATA
	 dstate_setinfo("output.power", "%d", -1);
	dstate_setflags("output.power", ST_FLAG_RW);
#endif
	 dstate_setinfo("output.voltage", "%d", -1);
	dstate_setflags("output.voltage", ST_FLAG_RW);
	 dstate_setinfo("output.current", "%d", -1);
	dstate_setflags("output.current", ST_FLAG_RW);
#ifdef EXTRADATA
	 dstate_setinfo("output.current.peak", "%2.2f", -1);	
	dstate_setflags("output.current.peak", ST_FLAG_RW);
	 dstate_setinfo("input.power", "%d", -1);
	dstate_setflags("input.power", ST_FLAG_RW);
#endif
	 dstate_setinfo("input.voltage", "%d", -1);
	dstate_setflags("input.voltage", ST_FLAG_RW);
#ifdef EXTRADATA
	 dstate_setinfo("input.current", "%2.2f", -1);
	dstate_setflags("input.current", ST_FLAG_RW);
	 dstate_setinfo("input.current.peak", "%2.2f", -1);	
	dstate_setflags("input.current.peak", ST_FLAG_RW);
#endif
	 dstate_setinfo("battery.voltage", "%d", -1);
	dstate_setflags("battery.voltage", ST_FLAG_RW);
#ifdef EXTRADATA
	 dstate_setinfo("battery.voltage.low", "%2.2f", -1);
	dstate_setflags("battery.voltage.low", ST_FLAG_RW);
	 dstate_setinfo("battery.voltage.exhaust", "%2.2f", -1);
	dstate_setflags("battery.voltage.exhaust", ST_FLAG_RW);
	 dstate_setinfo("ups.total.runtime", "retrieving...");
	dstate_setflags("ups.total.runtime", ST_FLAG_STRING | ST_FLAG_RW);
	  dstate_setaux("ups.total.runtime", 20);
	 dstate_setinfo("ups.inverter.runtime", "retrieving...");
	dstate_setflags("ups.inverter.runtime", ST_FLAG_STRING | ST_FLAG_RW);
	  dstate_setaux("ups.inverter.runtime", 20);
	 dstate_setinfo("ups.inverter.interventions", "%d", -1);
	dstate_setflags("ups.inverter.interventions", ST_FLAG_RW);
	 dstate_setinfo("battery.full.discharges", "%d", -1);
	dstate_setflags("battery.full.discharges", ST_FLAG_RW);
	 dstate_setinfo("ups.bypass.interventions", "%d", -1);
	dstate_setflags("ups.bypass.interventions", ST_FLAG_RW);
	 dstate_setinfo("ups.overheatings", "%d", -1);
	dstate_setflags("ups.overheatings", ST_FLAG_RW);
#endif
	 dstate_setinfo("ups.load", "%d", -1);
	dstate_setflags("ups.load", ST_FLAG_RW);
	 dstate_setinfo("ups.delay.shutdown", "%d", -1);
	dstate_setflags("ups.delay.shutdown", ST_FLAG_RW);
	 dstate_setinfo("ups.delay.start", "%d", -1);
	dstate_setflags("ups.delay.start", ST_FLAG_RW);
	 dstate_setinfo("ups.temperature", "%d", -1);
	dstate_setflags("ups.temperature", ST_FLAG_RW);
	 dstate_setinfo("ups.test.result", "not yet done...");
	dstate_setflags("ups.test.result", ST_FLAG_STRING | ST_FLAG_RW);
	  dstate_setaux("ups.test.result", 20);
	
	/* UPS INFO READ */
	res = command_read_sequence(UPS_INFO, my_answer);
	if (res < 0) fatal_with_errno(EXIT_FAILURE, "Could not communicate with the ups");
	/* the manufacturer is hard coded into the driver, the model type is in the second 
		byte of the answer, the third byte identifies the model version */
	dstate_setinfo("ups.mfr", "Meta System");
	i = my_answer[1] * 10 + my_answer[2];
	switch (i) {	
		case 11:
			dstate_setinfo("ups.model", "%s", "HF Line (1 board)");
			nominal_power = 630;
			break;
		case 12:
			dstate_setinfo("ups.model", "%s", "HF Line (2 boards)");
			nominal_power = 1260;
			break;
		case 13:
			dstate_setinfo("ups.model", "%s", "HF Line (3 boards)");
			nominal_power = 1890;
			break;
		case 14:
			dstate_setinfo("ups.model", "%s", "HF Line (4 boards)");
			nominal_power = 2520;
			break;
		case 21:
			dstate_setinfo("ups.model", "%s", "ECO Network 750/1000");
			nominal_power = 500;
			break;	
		case 22:
			dstate_setinfo("ups.model", "%s", "ECO Network 1050/1500");
			nominal_power = 700;
			break;	
		case 23:
			dstate_setinfo("ups.model", "%s", "ECO Network 1500/2000");
			nominal_power = 1000;
			break;	
		case 24:
			dstate_setinfo("ups.model", "%s", "ECO Network 1800/2500");
			nominal_power = 1200;
			break;	
		case 25:
			dstate_setinfo("ups.model", "%s", "ECO Network 2100/3000");
			nominal_power = 1400;
			break;	
		case 31:
			dstate_setinfo("ups.model", "%s", "ECO 308");
			nominal_power = 500;
			break;	
		case 32:
			dstate_setinfo("ups.model", "%s", "ECO 311");
			nominal_power = 700;
			break;	
		case 44:
			dstate_setinfo("ups.model", "%s", "HF Line (4 boards)/2");
			nominal_power = 2520;
			break;
		case 45:
			dstate_setinfo("ups.model", "%s", "HF Line (5 boards)/2");
			nominal_power = 3150;
			break;
		case 46:
			dstate_setinfo("ups.model", "%s", "HF Line (6 boards)/2");
			nominal_power = 3780;
			break;
		case 47:
			dstate_setinfo("ups.model", "%s", "HF Line (7 boards)/2");
			nominal_power = 4410;
			break;
		case 48:
			dstate_setinfo("ups.model", "%s", "HF Line (8 boards)/2");
			nominal_power = 5040;
			break;
		case 51:
			dstate_setinfo("ups.model", "%s", "HF Millennium 810");
			nominal_power = 700;
			break;
		case 52:
			dstate_setinfo("ups.model", "%s", "HF Millennium 820");
			nominal_power = 1400;
			break;
		case 61:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 910");
			nominal_power = 700;
			break;
		case 62:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 920");
			nominal_power = 1400;
			break;
		case 63:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 930");
			nominal_power = 2100;
			break;
		case 64:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 940");
			nominal_power = 2800;
			break;
		case 74:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 940/2");
			nominal_power = 2800;
			break;
		case 75:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 950/2");
			nominal_power = 3500;
			break;
		case 76:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 960/2");
			nominal_power = 4200;
			break;
		case 77:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 970/2");
			nominal_power = 4900;
			break;
		case 78:
			dstate_setinfo("ups.model", "%s", "HF TOP Line 980/2");
			nominal_power = 5600;
			break;
		case 81:
			dstate_setinfo("ups.model", "%s", "ECO 508");
			nominal_power = 500;
			break;
		case 82:
			dstate_setinfo("ups.model", "%s", "ECO 511");
			nominal_power = 700;
			break;
		case 83:
			dstate_setinfo("ups.model", "%s", "ECO 516");
			nominal_power = 1000;
			break;
		case 84:
			dstate_setinfo("ups.model", "%s", "ECO 519");
			nominal_power = 1200;
			break;
		case 85:
			dstate_setinfo("ups.model", "%s", "ECO 522");
			nominal_power = 1400;
			break;
		case 91:
			dstate_setinfo("ups.model", "%s", "ECO 305 / Harviot 530 SX");
			nominal_power = 330;
			break;
		case 92:
			dstate_setinfo("ups.model", "%s", "ORDINATORE 2");
			nominal_power = 330;
			break;
		case 93:
			dstate_setinfo("ups.model", "%s", "Harviot 730 SX");
			nominal_power = 430;
			break;
		case 101:
			dstate_setinfo("ups.model", "%s", "ECO 308 SX / SX Interactive / Ordinatore");
			nominal_power = 500;
			break;
		case 102:
			dstate_setinfo("ups.model", "%s", "ECO 311 SX / SX Interactive");
			nominal_power = 700;
			break;
		case 111:
			dstate_setinfo("ups.model", "%s", "ally HF 800 / BI-TWICE 800");
			nominal_power = 560;
			break;
		case 112:
			dstate_setinfo("ups.model", "%s", "ally HF 1600");
			nominal_power = 1120;
			break;
		case 121:
			dstate_setinfo("ups.model", "%s", "ally HF 1000 / BI-TWICE 1000");
			nominal_power = 700;
			break;
		case 122:
			dstate_setinfo("ups.model", "%s", "ally HF 2000");
			nominal_power = 1400;
			break;
		case 131:
			dstate_setinfo("ups.model", "%s", "ally HF 1250 / BI-TWICE 1250");
			nominal_power = 875;
			break;
		case 132:
			dstate_setinfo("ups.model", "%s", "ally HF 2500");
			nominal_power = 1750;
			break;
		case 141:
			dstate_setinfo("ups.model", "%s", "Megaline 1250");
			nominal_power = 875;
			break;
		case 142:
			dstate_setinfo("ups.model", "%s", "Megaline 2500");
			nominal_power = 1750;
			break;
		case 143:
			dstate_setinfo("ups.model", "%s", "Megaline 3750");
			nominal_power = 2625;
			break;
		case 144:
			dstate_setinfo("ups.model", "%s", "Megaline 5000");
			nominal_power = 3500;
			break;
		case 154:
			dstate_setinfo("ups.model", "%s", "Megaline 5000 / 2");
			nominal_power = 3500;
			break;
		case 155:
			dstate_setinfo("ups.model", "%s", "Megaline 6250 / 2");
			nominal_power = 4375;
			break;
		case 156:
			dstate_setinfo("ups.model", "%s", "Megaline 7500 / 2");
			nominal_power = 5250;
			break;
		case 157:
			dstate_setinfo("ups.model", "%s", "Megaline 8750 / 2");
			nominal_power = 6125;
			break;
		case 158:
			dstate_setinfo("ups.model", "%s", "Megaline 10000 / 2");
			nominal_power = 7000;
			break;

		default:
			fatal_with_errno(EXIT_FAILURE, "Unknown UPS");
			break;
	} 
		
	/* Get the serial number */
	memcpy(serial, my_answer + 7, res - 7);
	/* serial number start from the 8th byte */
	serial[12]=0;		/* terminate string */
	dstate_setinfo("ups.serial", "%s", serial);
	
	/* get the ups firmware. The major number is in the 5th byte, the minor is in the 6th */
	dstate_setinfo("ups.firmware", "%u.%u", my_answer[5], my_answer[6]);

	printf("Detected %s [%s] v.%s on %s\n", dstate_getinfo("ups.model"), dstate_getinfo("ups.serial"), dstate_getinfo("ups.firmware"), device_path);
	
	/* Add instant commands */
	dstate_addcmd("shutdown.return");
	dstate_addcmd("shutdown.stayoff");
	dstate_addcmd("shutdown.stop");
	dstate_addcmd("test.failure.start");
	dstate_addcmd("test.failure.stop");
	dstate_addcmd("test.battery.start");
	dstate_addcmd("beeper.enable");
	dstate_addcmd("beeper.mute");
	dstate_addcmd("beeper.on");
	dstate_addcmd("beeper.off");
	upsh.instcmd = instcmd;
	return;
}