Exemple #1
0
void setup_serial(const char *port)
{
    char temp[140];
    int i,ret;
 

   /* Detect the ups baudrate  */
    
    
   for (i=0; i<5; i++) {
	
        ser_set_speed(upsfd, device_path,baud_rates[i].rate);
        ret = ser_send(upsfd, "^P003MAN");
	ret = sec_upsrecv(temp);
	if (ret >= -1) break;

   }
    if (i == 5) {
	printf("Can't talk to UPS on port %s!\n",port);
	printf("Check the cabling and portname and try again\n");
	printf("Please note that this driver only support UPS Models with SEC Protorol\n");
	ser_close(upsfd, device_path);
	exit (1);
    }
printf("Connected to UPS on %s baudrate: %d\n",port, baud_rates[i].name);
}
Exemple #2
0
void upsdrv_initups(void)
{
	const char *val = getval("baudrate");
	speed_t baudrate = B2400;

	if (val) {
		switch (atoi(val))
		{
		case 1200:
			baudrate = B1200;
			break;
		case 2400:
			baudrate = B2400;
			break;
		case 4800:
			baudrate = B4800;
			break;
		case 9600:
			baudrate = B9600;
			break;
		case 19200:
			baudrate = B19200;
			break;
		default:
			fatalx(EXIT_FAILURE, "Baudrate [%s] unsupported", val);
		}
	}

	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, baudrate);
}
Exemple #3
0
int upsdrv_initups(void)
{
	upsfd = ser_open(device_path); 
	ser_set_speed(upsfd, device_path, B2400); 
	send_zeros();

	return 1;
}
Exemple #4
0
void upsdrv_initups(void)
{
	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, B19200);

	/* dtr and rts setting */
	ser_set_dtr(upsfd, 1);
	ser_set_rts(upsfd, 0);
	
}
Exemple #5
0
int upsdrv_initups(void)
{
	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, B9600);

	/*get the UPS in the right frame of mind*/
	ser_send_pace(upsfd, 100, "%s", COMMAND_END);
	ser_send_pace(upsfd, 100, "%s", COMMAND_END);
	sleep (1);

	return 1;
}
Exemple #6
0
void upsdrv_initups(void)
{
	upsfd = ser_open(device_path);

	/* Speed should not matter (see comments in upsdrv_updateinfo),
	 * but set it relatively low in case there are problems with higher
	 * speeds. */
	ser_set_speed(upsfd, device_path, B9600);

	/* raise RTS */
	ser_set_rts(upsfd, 1);
}
Exemple #7
0
int upsdrv_initups(void)
{
	struct termios	tio;
	const char	*val;

	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, B1200);

	if (tcgetattr(upsfd, &tio)) {
		fatal_with_errno(EXIT_FAILURE, "tcgetattr");
	}

	/*
	 * Use canonical mode input processing (to read reply line)
	 */
	tio.c_lflag |= ICANON;	/* Canonical input (erase and kill processing) */
	tio.c_iflag |= IGNCR;	/* Ignore CR */
	tio.c_iflag |= IGNBRK;	/* Ignore break condition */
	tio.c_oflag |= ONLCR;	/* Map NL to CR-NL on output */

	tio.c_cc[VEOF] = _POSIX_VDISABLE;
	tio.c_cc[VEOL] = _POSIX_VDISABLE;
	tio.c_cc[VERASE] = _POSIX_VDISABLE;
	tio.c_cc[VINTR]  = _POSIX_VDISABLE;
	tio.c_cc[VKILL]  = _POSIX_VDISABLE;
	tio.c_cc[VQUIT]  = _POSIX_VDISABLE;
	tio.c_cc[VSUSP]  = _POSIX_VDISABLE;
	tio.c_cc[VSTART] = _POSIX_VDISABLE;
	tio.c_cc[VSTOP]  = _POSIX_VDISABLE;

	if (tcsetattr(upsfd, TCSANOW, &tio)) {
		fatal_with_errno(EXIT_FAILURE, "tcsetattr");
	}

	/*
	 * Set DTR and clear RTS to provide power for the serial interface.
	 */
	ser_set_dtr(upsfd, 1);
	ser_set_rts(upsfd, 0);

	val = dstate_getinfo("battery.voltage.nominal");
	battery.voltage.nom = (val) ? strtod(val, NULL) : 12.00;

	val = dstate_getinfo("battery.voltage.low");
	battery.voltage.low = (val) ? strtod(val, NULL) : 10.80;

	if (battery.voltage.nom <= battery.voltage.low) {
		fatalx(EXIT_FAILURE, "Nominal battery voltage must be higher than low battery voltage!");
	}

	return 1;
}
Exemple #8
0
void upsdrv_initups(void)
{
	int fdm, fds;
//	char *slavename;                       //only for ptmx
//	extern char *ptsname();                //only for ptmx
     
	upsfd = ser_open(device_path);
//	grantpt(upsfd);                        /* change permission of slave , only for ptmx*/
//	unlockpt(upsfd);                       /* unlock slave ,only for ptmx */
//	slavename = ptsname(upsfd);           //only for ptmx
//	printf("the slave name is %s\n",slavename);
	printf("driver initups is running");
	ser_set_speed(upsfd, device_path, BAUDRATE);
}
Exemple #9
0
void riello_comm_setup(const char *port)
{
	uint8_t length;

	upsdebugx(2, "set baudrate 9600");
	ser_set_speed(upsfd, device_path, B9600);

	upsdebugx(2, "try to detect SENTR");
	riello_init_serial();
	bufOut[0] = 192;
	ser_send_buf(upsfd, bufOut, 1);

	riello_serialcomm(&bufIn[0], DEV_RIELLOSENTRY);

	if (buf_ptr_length == 103) {
		typeRielloProtocol = DEV_RIELLOSENTRY;
		upslogx(LOG_INFO, "Connected to UPS SENTR on %s with baudrate %d", port, 9600);
		return;
	}

	upsdebugx(2, "try to detect GPSER");
	riello_init_serial();
	length = riello_prepare_gi(&bufOut[0]);

	ser_send_buf(upsfd, bufOut, length);

	riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);

	if (!wait_packet && !foundbadcrc && !foundnak) {
		typeRielloProtocol = DEV_RIELLOGPSER;
		upslogx(LOG_INFO, "Connected to UPS GPSER on %s with baudrate %d", port, 9600);
		return;
	}

	upsdebugx(2, "set baudrate 1200");
	ser_set_speed(upsfd, device_path, B1200);

	upsdebugx(2, "try to detect SENTR");
	riello_init_serial();
	bufOut[0] = 192;
	ser_send_buf(upsfd, bufOut, 1);

	riello_serialcomm(&bufIn[0], DEV_RIELLOSENTRY);

	if (buf_ptr_length == 103) {
		typeRielloProtocol = DEV_RIELLOSENTRY;
		upslogx(LOG_INFO, "Connected to UPS SENTR on %s with baudrate %d", port, 1200);
		return;
	}

	upsdebugx(2, "try to detect GPSER");
	riello_init_serial();
	length = riello_prepare_gi(&bufOut[0]);

	ser_send_buf(upsfd, bufOut, length);

	riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);

	if (!wait_packet && !foundbadcrc && !foundnak) {
		typeRielloProtocol = DEV_RIELLOGPSER;
		upslogx(LOG_INFO, "Connected to UPS GPSER on %s with baudrate %d", port, 1200);
		return;
	}

	fatalx(EXIT_FAILURE, "Can't connect to the UPS on port %s!\n", port);
}
Exemple #10
0
void upsdrv_initups(void)
{
#ifndef TESTING
	const struct {
		const char	*val;
		const int	dtr;
		const int	rts;
	} cablepower[] = {
		{ "normal",	1, 0 }, /* default */
		{ "reverse",	0, 1 },
		{ "both",	1, 1 },
		{ "none",	0, 0 },
		{ NULL }
	};

	int	i;

	const char	*val;

	struct termios		tio;

	/*
	 * Open and lock the serial port and set the speed to 2400 baud.
	 */
	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, B2400);

	if (tcgetattr(upsfd, &tio)) {
		fatal_with_errno(EXIT_FAILURE, "tcgetattr");
	}

	/*
	 * Use canonical mode input processing (to read reply line)
	 */
	tio.c_lflag |= ICANON;	/* Canonical input (erase and kill processing) */

	tio.c_cc[VEOF]   = _POSIX_VDISABLE;
	tio.c_cc[VEOL]   = '\r';
	tio.c_cc[VERASE] = _POSIX_VDISABLE;
	tio.c_cc[VINTR]  = _POSIX_VDISABLE;
	tio.c_cc[VKILL]  = _POSIX_VDISABLE;
	tio.c_cc[VQUIT]  = _POSIX_VDISABLE;
	tio.c_cc[VSUSP]  = _POSIX_VDISABLE;
	tio.c_cc[VSTART] = _POSIX_VDISABLE;
	tio.c_cc[VSTOP]  = _POSIX_VDISABLE;

	if (tcsetattr(upsfd, TCSANOW, &tio)) {
		fatal_with_errno(EXIT_FAILURE, "tcsetattr");
	}

	val = getval("cablepower");
	for (i = 0; val && cablepower[i].val; i++) {

		if (!strcasecmp(val, cablepower[i].val)) {
			break;
		}
	}

	if (!cablepower[i].val) {
		fatalx(EXIT_FAILURE, "Value '%s' not valid for 'cablepower'", val);
	}

	ser_set_dtr(upsfd, cablepower[i].dtr);
	ser_set_rts(upsfd, cablepower[i].rts);

	/*
	 * Allow some time to settle for the cablepower
	 */
	usleep(100000);
#endif
	blazer_initups();
}
Exemple #11
0
void upsdrv_initups(void)
{
	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, B2400);
}
Exemple #12
0
void pw_comm_setup(const char *port)
{
	unsigned char	command = PW_SET_REQ_ONLY_MODE;
	unsigned char	id_command = PW_ID_BLOCK_REQ;
	unsigned char	answer[256];
	int		i = 0, baud, mybaud = 0, ret = -1;

	if (getval("baud_rate") != NULL)
	{
		baud = atoi(getval("baud_rate"));
		
		for(i = 0; i < PW_MAX_BAUD; i++) {
			if (baud == pw_baud_rates[i].name) {
				mybaud = pw_baud_rates[i].rate;
				break;
			}
		}

		if (mybaud == 0) {
			fatalx(EXIT_FAILURE, "Specified baudrate \"%s\" is invalid!", getval("baud_rate"));
		}

		ser_set_speed(upsfd, device_path, mybaud);
		ser_send_char(upsfd, 0x1d);	/* send ESC to take it out of menu */
		usleep(90000);
		send_write_command(AUT, 4);
		usleep(500000);
		ret = command_sequence(&command, 1, answer);
		if (ret <= 0) {
			usleep(500000);
			ret = command_sequence(&id_command, 1, answer);
		}

		if (ret > 0) {
			upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %d", port, baud);
			return;
		}

		upslogx(LOG_ERR, "No response from UPS on %s with baudrate %d", port, baud);
	}

	upslogx(LOG_INFO, "Attempting to autodect baudrate");

	for (i=0; i<PW_MAX_BAUD; i++) {

		ser_set_speed(upsfd, device_path, pw_baud_rates[i].rate);
		ser_send_char(upsfd, 0x1d);	/* send ESC to take it out of menu */
		usleep(90000);
		send_write_command(AUT, 4);
		usleep(500000);
		ret = command_sequence(&command, 1, answer);
		if (ret <= 0) {
			usleep(500000);
			ret = command_sequence(&id_command, 1, answer);
		}

		if (ret > 0) {
			upslogx(LOG_INFO, "Connected to UPS on %s with baudrate %d", port, pw_baud_rates[i].name);
			return;
		}

		upsdebugx(2, "No response from UPS on %s with baudrate %d", port, pw_baud_rates[i].name);
	}

	fatalx(EXIT_FAILURE, "Can't connect to the UPS on port %s!\n", port);
}
Exemple #13
0
void upsdrv_initups(void)
{
	struct termios tio;
	int baud = B1200;
	char *str;

	if ((str = getval("baudrate")) != NULL) {
		int temp = atoi(str);
		switch (temp) {
		case   300:
			baud =   B300; break;
		case   600:
			baud =   B600; break;
		case  1200:
			baud =  B1200; break;
		case  2400:
			baud =  B2400; break;
		case  4800:
			baud =  B4800; break;
		case  9600:
			baud =  B9600; break;
		case 19200:
			baud = B19200; break;
		case 38400:
			baud = B38400; break;
		default:
			fatalx(EXIT_FAILURE, "Unrecognized baudrate: %s", str);
		}
		upsdebugx(1, "baud_rate = %d", temp);
	}
	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, baud);

	if (tcgetattr(upsfd, &tio) != 0)
		fatal_with_errno(EXIT_FAILURE, "tcgetattr(%s)", device_path);
	tio.c_lflag = ICANON;
	tio.c_iflag |= IGNCR;	/* Ignore CR */
	tio.c_cc[VMIN] = 0;
	tio.c_cc[VTIME] = 0;
	tcsetattr(upsfd, TCSANOW, &tio);

	if ((str = getval("input_timeout")) != NULL) {
		int temp = atoi(str);
		if (temp <= 0)
			fatalx(EXIT_FAILURE, "Bad input_timeout parameter: %s", str);
		input_timeout_sec = temp;
	}
	upsdebugx(1, "input_timeout = %d Sec", input_timeout_sec);

	if ((str = getval("output_pace")) != NULL) {
		int temp = atoi(str);
		if (temp <= 0)
			fatalx(EXIT_FAILURE, "Bad output_pace parameter: %s", str);
		output_pace_usec = temp;
	}
	upsdebugx(1, "output_pace = %d uSec", output_pace_usec);

	if ((str = getval("full_update_timer")) != NULL) {
		int temp = atoi(str);
		if (temp <= 0)
			fatalx(EXIT_FAILURE, "Bad full_update_timer parameter: %s", str);
		full_update_timer = temp;
	}
	upsdebugx(1, "full_update_timer = %d Sec", full_update_timer);

	use_crlf = testvar("use_crlf");
	upsdebugx(1, "use_crlf = %d", use_crlf);
	use_pre_lf = testvar("use_pre_lf");
	upsdebugx(1, "use_pre_lf = %d", use_pre_lf);
}
Exemple #14
0
/* initialize UPS */
void upsdrv_initups(void)
{
	int tmp,model = 0;
	unsigned int i;
	static char buf[20];

	/* check manufacturer name from arguments */
	if (getval("manufacturer") != NULL) 
		manufacturer = getval("manufacturer");
	
	/* check model name from arguments */
	if (getval("modelname") != NULL) 
		modelname = getval("modelname");
	
	/* check serial number from arguments */
	if (getval("serialnumber") != NULL) 
		serialnumber = getval("serialnumber");
	
	/* get and check type */
	if (getval("type") != NULL) {
		for (i = 0; 
			 i < NUM_OF_SUBTYPES  &&  strcmp(types[i].name, getval("type"));
			 i++) ;
		if (i >= NUM_OF_SUBTYPES) {
			printf("Given UPS type '%s' isn't valid!\n", getval("type"));
			exit (1);
		}
		type = i;	
	};
	
	/* check line voltage from arguments */
	if (getval("linevoltage") != NULL) {
		tmp = atoi(getval("linevoltage"));
		if (! ( (tmp >= 200 && tmp <= 240) || (tmp >= 100 && tmp <= 120) ) ) {
			printf("Given line voltage '%d' is out of range (100-120 or 200-240 V)\n", tmp);
			exit (1);
		};
		linevoltage = (unsigned int) tmp;
	};

	if (getval("numOfBytesFromUPS") != NULL) {
		tmp = atoi(getval("numOfBytesFromUPS"));
		if (! (tmp > 0 && tmp <= MAX_NUM_OF_BYTES_FROM_UPS) ) {
			printf("Given numOfBytesFromUPS '%d' is out of range (1 to %d)\n",
	               tmp, MAX_NUM_OF_BYTES_FROM_UPS);
			exit (1);
		};
		types[type].num_of_bytes_from_ups = (unsigned char) tmp;
	}

	if (getval("methodOfFlowControl") != NULL) {
		for (i = 0; 
			 i < NUM_OF_SUBTYPES  &&  
					strcmp(types[i].flowControl.name,
							getval("methodOfFlowControl"));
			 i++) ;
		if (i >= NUM_OF_SUBTYPES) {
			printf("Given methodOfFlowControl '%s' isn't valid!\n", 
					getval("methodOfFlowControl"));
			exit (1);
		};
		types[type].flowControl = types[i].flowControl;	
	}

	if (getval("validationSequence")  &&
            sscanf(getval("validationSequence"),
					"{{%u,%x},{%u,%x},{%u,%x}}",
			                &types[type].validation[0].index_of_byte,
			                &types[type].validation[0].required_value,
			                &types[type].validation[1].index_of_byte,
			                &types[type].validation[1].required_value,
			                &types[type].validation[2].index_of_byte,
			                &types[type].validation[2].required_value
			      ) < 6
	   ) {
		printf("Given validationSequence '%s' isn't valid!\n", 
								         getval("validationSequence"));
		exit (1);
	}

	if (getval("shutdownArguments")  &&
	    sscanf(getval("shutdownArguments"), "{{%u,%u},%c}",
	                &types[type].shutdown_arguments.delay[0],
	                &types[type].shutdown_arguments.delay[1],
	                &types[type].shutdown_arguments.minutesShouldBeUsed 
	          ) < 3
	   ) {
	    printf("Given shutdownArguments '%s' isn't valid!\n", 
								         getval("shutdownArguments"));
		exit (1);
	} 

	if (getval("frequency")  &&
            sscanf(getval("frequency"), "{%f,%f}",
			                &types[type].freq[0], &types[type].freq[1]
	              ) < 2
	   ) {
		printf("Given frequency '%s' isn't valid!\n", 
										getval("frequency"));
		exit (1);
	}

	if (getval("loadPercentage")  && 
            sscanf(getval("loadPercentage"), "{%f,%f,%f,%f}",
	            &types[type].loadpct[0], &types[type].loadpct[1],
	            &types[type].loadpct[2], &types[type].loadpct[3]
	              ) < 4
	   ) {
		printf("Given loadPercentage '%s' isn't valid!\n", 
								         getval("loadPercentage"));
		exit (1);
	}

	if (getval("batteryPercentage")  && 
            sscanf(getval("batteryPercentage"), "{%f,%f,%f,%f,%f}",
	                &types[type].battpct[0], &types[type].battpct[1],
	                &types[type].battpct[2], &types[type].battpct[3],
	                &types[type].battpct[4]
	              ) < 5
	   ) {
		printf("Given batteryPercentage '%s' isn't valid!\n", 
								         getval("batteryPercentage"));
		exit (1);
	}

	if (getval("voltage")  &&
            sscanf(getval("voltage"), "{%f,%f,%f,%f}",
	            &types[type].voltage[0], &types[type].voltage[1],
	            &types[type].voltage[2], &types[type].voltage[3]
				  ) < 4
	   ) {
		printf("Given voltage '%s' isn't valid!\n", getval("voltage"));
		exit (1);
	}

	/* open serial port */
	upsfd = ser_open(device_path);
	ser_set_speed(upsfd, device_path, B1200);
	
	/* setup flow control */
	types[type].flowControl.setup_flow_control();

	/* Setup Model and LineVoltage */
	if (!strncmp(types[type].name, "BNT",3) || !strcmp(types[type].name, "KIN") || !strcmp(types[type].name, "IMP") || !strcmp(types[type].name, "OPTI")) {
		if (!ups_getinfo()) return;
		/* Give "BNT-other" a chance! */
		if (raw_data[MODELNAME]==0x42 || raw_data[MODELNAME]==0x4B || raw_data[MODELNAME]==0x4F){
			/* Give "IMP" a chance also! */
			if (raw_data[UPSVERSION]==0xFF){
				types[type].name="IMP";
				model=IMPmodels[raw_data[MODELNUMBER]/16];
			}
			else {
				model=BNTmodels[raw_data[MODELNUMBER]/16];
				if (!strcmp(types[type].name, "BNT-other"))
					types[type].name="BNT-other";
				else if (raw_data[MODELNAME]==0x42)
					types[type].name="BNT";
				else if (raw_data[MODELNAME]==0x4B){
					types[type].name="KIN";
					model=KINmodels[raw_data[MODELNUMBER]/16];
				} else if (raw_data[MODELNAME]==0x4F){
					types[type].name="OPTI";
					model=OPTImodels[raw_data[MODELNUMBER]/16];
				}
			}
		}
		else if (raw_data[UPSVERSION]==0xFF){
			types[type].name="IMP";
			model=IMPmodels[raw_data[MODELNUMBER]/16];
		}
		linevoltage=voltages[raw_data[MODELNUMBER]%16];
		if (!strcmp(types[type].name, "OPTI")) {
			snprintf(buf,sizeof(buf),"%s-%d",types[type].name,model);
		} else {
			snprintf(buf,sizeof(buf),"%s-%dAP",types[type].name,model);
		}
		if (!strcmp(modelname, "Unknown"))
			modelname=buf;
		upsdebugx(1,"Detected: %s , %dV",buf,linevoltage);
		if (ser_send_char (upsfd, BATTERY_TEST) != 1) {
			upslogx(LOG_NOTICE, "writing error");
			dstate_datastale();
			return;
		}
	}
	
	upsdebugx(1, "Values of arguments:");
	upsdebugx(1, " manufacturer            : '%s'", manufacturer);
	upsdebugx(1, " model name              : '%s'", modelname);
	upsdebugx(1, " serial number           : '%s'", serialnumber);
	upsdebugx(1, " line voltage            : '%u'", linevoltage);
	upsdebugx(1, " type                    : '%s'", types[type].name);
	upsdebugx(1, " number of bytes from UPS: '%u'", 
	                        types[type].num_of_bytes_from_ups);
	upsdebugx(1, " method of flow control  : '%s'", 
    	                    types[type].flowControl.name);
	upsdebugx(1, " validation sequence: '{{%u,%#x},{%u,%#x},{%u,%#x}}'",
			            types[type].validation[0].index_of_byte,
			            types[type].validation[0].required_value,
			            types[type].validation[1].index_of_byte,
			            types[type].validation[1].required_value,
			            types[type].validation[2].index_of_byte,
			            types[type].validation[2].required_value);
	upsdebugx(1, " shutdown arguments: '{{%u,%u},%c}'",
	                types[type].shutdown_arguments.delay[0],
	                types[type].shutdown_arguments.delay[1],
	                types[type].shutdown_arguments.minutesShouldBeUsed); 
	if ( strcmp(types[type].name, "KIN") && strcmp(types[type].name, "BNT") && strcmp(types[type].name, "IMP")) {
		upsdebugx(1, " frequency calculation coefficients: '{%f,%f}'",
								types[type].freq[0], types[type].freq[1]);
		upsdebugx(1, " load percentage calculation coefficients: "
					"'{%f,%f,%f,%f}'",
						types[type].loadpct[0], types[type].loadpct[1],
						types[type].loadpct[2], types[type].loadpct[3]);
		upsdebugx(1, " battery percentage calculation coefficients: " 
					"'{%f,%f,%f,%f,%f}'",
						types[type].battpct[0], types[type].battpct[1],
						types[type].battpct[2], types[type].battpct[3],
						types[type].battpct[4]);
		upsdebugx(1, " voltage calculation coefficients: '{%f,%f}'",
							types[type].voltage[2], types[type].voltage[3]);
	}

}
Exemple #15
0
void upsdrv_initups ()
{
  char	temp[256], fcstring[512];

  upsfd = ser_open(device_path);
  ser_set_speed(upsfd, device_path, B1200);
  setup_serial();
  ups_sync();

  fc.model = UNKNOWN;
  /* Obtain Model */
  if (execute("id\r", fcstring, sizeof(fcstring)) < 1) {
    fatalx(EXIT_FAILURE, "Failed execute in ups_ident()");
  }
  
  /* response is a one-line packed string starting with $ */
  if (memcmp(fcstring, "Unit", 4)) {
    fatalx(EXIT_FAILURE, 
	"Bad response from formatconfig command in ups_ident()\n"
	"id: %s\n", fcstring
    );
  }

  if (debugging)
    fprintf(stderr, "id: %s\n", fcstring);
  
  /* chars 4:2  are a two-digit ascii hex enumerated model code */
  memcpy(temp, fcstring+9, 2);
  temp[2] = '\0';

  if (memcmp(temp, "ME", 2) == 0)  {
    fc.model = ME3100;
  } else if ((memcmp(temp, "RE", 2) == 0)) {
    fc.model = RE1800;
  } else if (memcmp(temp, "C1", 2) == 0)  {
    /* Better way to identify unit is using "d 15\r", which results in
       "15 M#    MD1KVA", "id\r" yields "Unit ID "C1K03588"" */
    fc.model = MD1KVA;
  }
 
  switch(fc.model) {
    case ME3100:
      fc.va = 3100;
      fc.watts = 2200;
      /* determine shutdown battery voltage */
      if (execute("d 29\r", fcstring, sizeof(fcstring)) > 0) {
        sscanf(fcstring, "29 LowBat   %f", &fc.emptyvolts);
      }
      /* determine fully charged battery voltage */
      if (execute("d 31\r", fcstring, sizeof(fcstring)) > 0) {
        sscanf(fcstring, "31 HiBatt   %f", &fc.fullvolts);
      }
      fc.fullvolts = 54.20;
      /* determine "ideal" voltage by a guess */
      fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
      break;
    case RE1800:
      fc.va = 1800;
      fc.watts = 1200;
      /* determine shutdown battery voltage */
      if (execute("d 29\r", fcstring, sizeof(fcstring)) > 0) {
        sscanf(fcstring, "29 LowBat   %f", &fc.emptyvolts);
      }
      /* determine fully charged battery voltage */
      if (execute("d 31\r", fcstring, sizeof(fcstring)) > 0) {
        sscanf(fcstring, "31 HiBatt   %f", &fc.fullvolts);
      }
      fc.fullvolts = 54.20;
      /* determine "ideal" voltage by a guess */
      fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
      break;
    case MD1KVA:
      fc.va = 1100;
      fc.watts = 770; /* Approximate, based on 0.7 power factor */
      /* determine shutdown battery voltage */
      if (execute("d 27\r", fcstring, sizeof(fcstring)) > 0) {
        sscanf(fcstring, "27 LowBatt  %f", &fc.emptyvolts);
      }
      /* determine fully charged battery voltage */
      if (execute("d 28\r", fcstring, sizeof(fcstring)) > 0) {
        sscanf(fcstring, "28 Hi Batt  %f", &fc.fullvolts);
      }
      fc.fullvolts = 13.70;
      /* determine "ideal" voltage by a guess */
      fc.idealbvolts = ((fc.fullvolts - fc.emptyvolts) * 0.7) + fc.emptyvolts;
      break;
    default:
      fatalx(EXIT_FAILURE, "Uknown model %s in ups_ident()", temp);
  }

  fc.valid = 1;
  return;
}