Exemplo n.º 1
0
static int netxml_alarm_subscribe(const char *page)
{
	int	ret, port = -1, secret = -1;
	char	buf[LARGEBUF], *s;
	ne_request	*request;
	ne_sock_addr	*addr;
	const ne_inet_addr	*ai;
	char	resp_buf[LARGEBUF];

	/* Clear response buffer */
	memset(resp_buf, 0, sizeof(resp_buf));

	upsdebugx(2, "%s: %s", __func__, page);

	sock = ne_sock_create();

	if (gethostname(buf, sizeof(buf)) == 0) {
		dstate_setinfo("driver.hostname", "%s", buf);
	} else {
		dstate_setinfo("driver.hostname", "<unknown>");
	}

#ifdef HAVE_NE_SOCK_CONNECT_TIMEOUT
	ne_sock_connect_timeout(sock, timeout);
#endif
	ne_sock_read_timeout(sock, 1);

	netxml_get_page(subdriver->configure);

	snprintf(buf, sizeof(buf),	"<?xml version=\"1.0\"?>\n");
	snprintfcat(buf, sizeof(buf),	"<Subscribe>\n");
	snprintfcat(buf, sizeof(buf),		"<Class>%s v%s</Class>\n", progname, DRIVER_VERSION);
	snprintfcat(buf, sizeof(buf),		"<Type>connected socket</Type>\n");
	snprintfcat(buf, sizeof(buf),		"<HostName>%s</HostName>\n", dstate_getinfo("driver.hostname"));
	snprintfcat(buf, sizeof(buf),		"<XMLClientParameters>\n");
	snprintfcat(buf, sizeof(buf),		"<ShutdownDuration>%d</ShutdownDuration>\n", shutdown_duration);
	if( shutdown_timer > 0 ) {
		snprintfcat(buf, sizeof(buf),	"<ShutdownTimer>%d</ShutdownTimer>\r\n", shutdown_timer);
	}
	else {
		snprintfcat(buf, sizeof(buf),	"<ShutdownTimer>NONE</ShutdownTimer>\n");
	}
	snprintfcat(buf, sizeof(buf),			"<AutoConfig>LOCAL</AutoConfig>\n");
	snprintfcat(buf, sizeof(buf),			"<OutletGroup>1</OutletGroup>\n");
	snprintfcat(buf, sizeof(buf),		"</XMLClientParameters>\n");
	snprintfcat(buf, sizeof(buf),		"<Warning></Warning>\n");
	snprintfcat(buf, sizeof(buf),	"</Subscribe>\n");

	/* now send subscription message setting all the proper flags */
	request = ne_request_create(session, "POST", page);
	ne_set_request_body_buffer(request, buf, strlen(buf));

	/* as the NMC reply is not xml standard compliant let's parse it this way */
	do {
#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(timeout+1);
#endif
		ret = ne_begin_request(request);

#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(0);
#endif
		if (ret != NE_OK) {
			break;
		}

		ret = ne_read_response_block(request, resp_buf, sizeof(resp_buf));

		if (ret == NE_OK) {
			ret = ne_end_request(request);
		}

	} while (ret == NE_RETRY);

	ne_request_destroy(request);

	/* due to different formats used by the various NMCs, we need to\
	   break up the reply in lines and parse each one separately */
	for (s = strtok(resp_buf, "\r\n"); s != NULL; s = strtok(NULL, "\r\n")) {
		upsdebugx(2, "%s: parsing %s", __func__, s);

		if (!strncasecmp(s, "<Port>", 6) && (sscanf(s+6, "%u", &port) != 1)) {
			return NE_RETRY;
		}

		if (!strncasecmp(s, "<Secret>", 8) && (sscanf(s+8, "%u", &secret) != 1)) {
			return NE_RETRY;
		}
	}

	if ((port == -1) || (secret == -1)) {
		upsdebugx(2, "%s: parsing initial subcription failed", __func__);
		return NE_RETRY;
	}

	/* Resolve the given hostname.  'flags' must be zero.  Hex
	* string IPv6 addresses (e.g. `::1') may be enclosed in brackets
	* (e.g. `[::1]'). */
	addr = ne_addr_resolve(uri.host, 0);

	/* Returns zero if name resolution was successful, non-zero on
	* error. */
	if (ne_addr_result(addr) != 0) {
		upsdebugx(2, "%s: name resolution failure on %s: %s", __func__, uri.host, ne_addr_error(addr, buf, sizeof(buf)));
		ne_addr_destroy(addr);
		return NE_RETRY;
	}

	for (ai = ne_addr_first(addr); ai != NULL; ai = ne_addr_next(addr)) {

		upsdebugx(2, "%s: connecting to host %s port %d", __func__, ne_iaddr_print(ai, buf, sizeof(buf)), port);

#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(timeout+1);
#endif
		ret = ne_sock_connect(sock, ai, port);

#ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT
		alarm(0);
#endif
		if (ret == NE_OK) {
			upsdebugx(2, "%s: connection to %s open on fd %d", __func__, uri.host, ne_sock_fd(sock));
			break;
		}
	}

	ne_addr_destroy(addr);

	if (ai == NULL) {
		upsdebugx(2, "%s: failed to create listening socket", __func__);
		return NE_RETRY;
	}

	snprintf(buf, sizeof(buf), "<Subscription Identification=\"%u\"></Subscription>", secret);
	ret = ne_sock_fullwrite(sock, buf, strlen(buf) + 1);

	if (ret != NE_OK) {
		upsdebugx(2, "%s: send failed: %s", __func__, ne_sock_error(sock));
		return NE_RETRY;
	}

	ret = ne_sock_read(sock, buf, sizeof(buf));

	if (ret < 1) {
		upsdebugx(2, "%s: read failed: %s", __func__, ne_sock_error(sock));
		return NE_RETRY;
	}

	if (strcasecmp(buf, "<Subscription Answer=\"ok\"></Subscription>")) {
		upsdebugx(2, "%s: subscription rejected", __func__);
		return NE_RETRY;
	}

	upslogx(LOG_INFO, "NSM connection to '%s' established", uri.host);
	return NE_OK;
}
Exemplo n.º 2
0
Arquivo: libusb.c Projeto: alfh/nut
/* On success, fill in the curDevice structure and return the report
 * descriptor length. On failure, return -1.
 * Note: When callback is not NULL, the report descriptor will be
 * passed to this function together with the udev and USBDevice_t
 * information. This callback should return a value > 0 if the device
 * is accepted, or < 1 if not. If it isn't accepted, the next device
 * (if any) will be tried, until there are no more devices left.
 */
static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDeviceMatcher_t *matcher,
	int (*callback)(usb_dev_handle *udev, USBDevice_t *hd, unsigned char *rdbuf, int rdlen))
{
#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
	int retries;
#endif
	int rdlen1, rdlen2; /* report descriptor length, method 1+2 */
	USBDeviceMatcher_t *m;
	struct usb_device *dev;
	struct usb_bus *bus;
	usb_dev_handle *udev;
	struct usb_interface_descriptor *iface;

	int ret, res;
	unsigned char buf[20];
	unsigned char *p;
	char string[256];
	int i;

	/* report descriptor */
	unsigned char	rdbuf[MAX_REPORT_SIZE];
	int		rdlen;

	/* libusb base init */
	usb_init();
	usb_find_busses();
	usb_find_devices();

#ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */
	/* Causes a double free corruption in linux if device is detached! */
	libusb_close(*udevp);
#endif

	for (bus = usb_busses; bus; bus = bus->next) {
		for (dev = bus->devices; dev; dev = dev->next) {
			upsdebugx(2, "Checking device (%04X/%04X) (%s/%s)", dev->descriptor.idVendor,
				dev->descriptor.idProduct, bus->dirname, dev->filename);

			/* supported vendors are now checked by the
			   supplied matcher */

			/* open the device */
			*udevp = udev = usb_open(dev);
			if (!udev) {
				upsdebugx(2, "Failed to open device, skipping. (%s)", usb_strerror());
				continue;
			}

			/* collect the identifying information of this
			   device. Note that this is safe, because
			   there's no need to claim an interface for
			   this (and therefore we do not yet need to
			   detach any kernel drivers). */

			free(curDevice->Vendor);
			free(curDevice->Product);
			free(curDevice->Serial);
			free(curDevice->Bus);
			memset(curDevice, '\0', sizeof(*curDevice));

			curDevice->VendorID = dev->descriptor.idVendor;
			curDevice->ProductID = dev->descriptor.idProduct;
			curDevice->Bus = strdup(bus->dirname);

			if (dev->descriptor.iManufacturer) {
				ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer,
					string, sizeof(string));
				if (ret > 0) {
					curDevice->Vendor = strdup(string);
				}
			}

			if (dev->descriptor.iProduct) {
				ret = usb_get_string_simple(udev, dev->descriptor.iProduct,
					string, sizeof(string));
				if (ret > 0) {
					curDevice->Product = strdup(string);
				}
			}

			if (dev->descriptor.iSerialNumber) {
				ret = usb_get_string_simple(udev, dev->descriptor.iSerialNumber,
					string, sizeof(string));
				if (ret > 0) {
					curDevice->Serial = strdup(string);
				}
			}

			upsdebugx(2, "- VendorID: %04x", curDevice->VendorID);
			upsdebugx(2, "- ProductID: %04x", curDevice->ProductID);
			upsdebugx(2, "- Manufacturer: %s", curDevice->Vendor ? curDevice->Vendor : "unknown");
			upsdebugx(2, "- Product: %s", curDevice->Product ? curDevice->Product : "unknown");
			upsdebugx(2, "- Serial Number: %s", curDevice->Serial ? curDevice->Serial : "unknown");
			upsdebugx(2, "- Bus: %s", curDevice->Bus ? curDevice->Bus : "unknown");

			upsdebugx(2, "Trying to match device");
			for (m = matcher; m; m=m->next) {
				ret = matches(m, curDevice);
				if (ret==0) {
					upsdebugx(2, "Device does not match - skipping");
					goto next_device;
				} else if (ret==-1) {
					fatal_with_errno(EXIT_FAILURE, "matcher");
					goto next_device;
				} else if (ret==-2) {
					upsdebugx(2, "matcher: unspecified error");
					goto next_device;
				}
			}
			upsdebugx(2, "Device matches");

			/* Now we have matched the device we wanted. Claim it. */

#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
			/* this method requires at least libusb 0.1.8:
			 * it force device claiming by unbinding
			 * attached driver... From libhid */
			retries = 3;
			while (usb_claim_interface(udev, 0) < 0) {

				upsdebugx(2, "failed to claim USB device: %s", usb_strerror());

				if (usb_detach_kernel_driver_np(udev, 0) < 0) {
					upsdebugx(2, "failed to detach kernel driver from USB device: %s", usb_strerror());
				} else {
					upsdebugx(2, "detached kernel driver from USB device...");
				}

				if (retries-- > 0) {
					continue;
				}

				fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
			}
#else
			if (usb_claim_interface(udev, 0) < 0) {
				fatalx(EXIT_FAILURE, "Can't claim USB device [%04x:%04x]: %s", curDevice->VendorID, curDevice->ProductID, usb_strerror());
			}
#endif

			/* set default interface */
			usb_set_altinterface(udev, 0);

			if (!callback) {
				return 1;
			}

			if (!dev->config) { /* ?? this should never happen */
				upsdebugx(2, "  Couldn't retrieve descriptors");
				goto next_device;
			}

			rdlen1 = -1;
			rdlen2 = -1;

			/* Get HID descriptor */

			/* FIRST METHOD: ask for HID descriptor directly. */
			/* res = usb_get_descriptor(udev, USB_DT_HID, 0, buf, 0x9); */
			res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
					      (USB_DT_HID << 8) + 0, 0, buf, 0x9, USB_TIMEOUT);

			if (res < 0) {
				upsdebugx(2, "Unable to get HID descriptor (%s)", usb_strerror());
			} else if (res < 9) {
				upsdebugx(2, "HID descriptor too short (expected %d, got %d)", 8, res);
			} else {

				upsdebug_hex(3, "HID descriptor, method 1", buf, 9);

				rdlen1 = buf[7] | (buf[8] << 8);
			}

			if (rdlen1 < -1) {
				upsdebugx(2, "Warning: HID descriptor, method 1 failed");
			}

			/* SECOND METHOD: find HID descriptor among "extra" bytes of
			   interface descriptor, i.e., bytes tucked onto the end of
			   descriptor 2. */

			/* Note: on some broken UPS's (e.g. Tripp Lite Smart1000LCD),
				only this second method gives the correct result */

			/* for now, we always assume configuration 0, interface 0,
			   altsetting 0, as above. */
			iface = &dev->config[0].interface[0].altsetting[0];
			for (i=0; i<iface->extralen; i+=iface->extra[i]) {
				upsdebugx(4, "i=%d, extra[i]=%02x, extra[i+1]=%02x", i,
					iface->extra[i], iface->extra[i+1]);
				if (i+9 <= iface->extralen && iface->extra[i] >= 9 && iface->extra[i+1] == 0x21) {
					p = &iface->extra[i];
					upsdebug_hex(3, "HID descriptor, method 2", p, 9);
					rdlen2 = p[7] | (p[8] << 8);
					break;
				}
			}

			if (rdlen2 < -1) {
				upsdebugx(2, "Warning: HID descriptor, method 2 failed");
			}

			/* when available, always choose the second value, as it
				seems to be more reliable (it is the one reported e.g. by
				lsusb). Note: if the need arises, can change this to use
				the maximum of the two values instead. */
			rdlen = rdlen2 >= 0 ? rdlen2 : rdlen1;

			if (rdlen < 0) {
				upsdebugx(2, "Unable to retrieve any HID descriptor");
				goto next_device;
			}
			if (rdlen1 >= 0 && rdlen2 >= 0 && rdlen1 != rdlen2) {
				upsdebugx(2, "Warning: two different HID descriptors retrieved (Reportlen = %d vs. %d)", rdlen1, rdlen2);
			}

			upsdebugx(2, "HID descriptor length %d", rdlen);

			if (rdlen > (int)sizeof(rdbuf)) {
				upsdebugx(2, "HID descriptor too long %d (max %d)", rdlen, (int)sizeof(rdbuf));
				goto next_device;
			}

			/* res = usb_get_descriptor(udev, USB_DT_REPORT, 0, bigbuf, rdlen); */
			res = usb_control_msg(udev, USB_ENDPOINT_IN+1, USB_REQ_GET_DESCRIPTOR,
				(USB_DT_REPORT << 8) + 0, 0, rdbuf, rdlen, USB_TIMEOUT);

			if (res < 0)
			{
				upsdebug_with_errno(2, "Unable to get Report descriptor");
				goto next_device;
			}

			if (res < rdlen)
			{
				upsdebugx(2, "Warning: report descriptor too short (expected %d, got %d)", rdlen, res);
				rdlen = res; /* correct rdlen if necessary */
			}

			res = callback(udev, curDevice, rdbuf, rdlen);
			if (res < 1) {
				upsdebugx(2, "Caller doesn't like this device");
				goto next_device;
			}

			upsdebugx(2, "Report descriptor retrieved (Reportlen = %d)", rdlen);
			upsdebugx(2, "Found HID device");
			fflush(stdout);

			return rdlen;

		next_device:
			usb_close(udev);
		}
	}

	*udevp = NULL;
	upsdebugx(2, "No appropriate HID device found");
	fflush(stdout);

	return -1;
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDeviceMatcher_t *matcher,
	int (*callback)(usb_dev_handle *handle, USBDevice_t *device))
{
	struct usb_bus	*bus;

	/* libusb base init */
	usb_init();
	usb_find_busses();
	usb_find_devices();

#ifndef __linux__ /* SUN_LIBUSB (confirmed to work on Solaris and FreeBSD) */
	/* Causes a double free corruption in linux if device is detached! */
	usb_device_close(*handlep);
#endif

	for (bus = usb_busses; bus; bus = bus->next) {

		struct usb_device	*dev;
		usb_dev_handle		*handle;

		for (dev = bus->devices; dev; dev = dev->next) {

			int	i, ret;
			USBDeviceMatcher_t	*m;

			upsdebugx(4, "Checking USB device [%04x:%04x] (%s/%s)", dev->descriptor.idVendor,
				dev->descriptor.idProduct, bus->dirname, dev->filename);
			
			/* supported vendors are now checked by the supplied matcher */

			/* open the device */
			*handlep = handle = usb_open(dev);
			if (!handle) {
				upsdebugx(4, "Failed to open USB device, skipping: %s", usb_strerror());
				continue;
			}

			/* collect the identifying information of this
			   device. Note that this is safe, because
			   there's no need to claim an interface for
			   this (and therefore we do not yet need to
			   detach any kernel drivers). */

			free(device->Vendor);
			free(device->Product);
			free(device->Serial);
			free(device->Bus);

			memset(device, 0, sizeof(*device));

			device->VendorID = dev->descriptor.idVendor;
			device->ProductID = dev->descriptor.idProduct;
			device->Bus = strdup(bus->dirname);
			
			if (dev->descriptor.iManufacturer) {
				char	buf[SMALLBUF];
				ret = usb_get_string_simple(handle, dev->descriptor.iManufacturer,
					buf, sizeof(buf));
				if (ret > 0) {
					device->Vendor = strdup(buf);
				}
			}

			if (dev->descriptor.iProduct) {
				char	buf[SMALLBUF];
				ret = usb_get_string_simple(handle, dev->descriptor.iProduct,
					buf, sizeof(buf));
				if (ret > 0) {
					device->Product = strdup(buf);
				}
			}

			if (dev->descriptor.iSerialNumber) {
				char	buf[SMALLBUF];
				ret = usb_get_string_simple(handle, dev->descriptor.iSerialNumber,
					buf, sizeof(buf));
				if (ret > 0) {
					device->Serial = strdup(buf);
				}
			}

			upsdebugx(4, "- VendorID     : %04x", device->VendorID);
			upsdebugx(4, "- ProductID    : %04x", device->ProductID);
			upsdebugx(4, "- Manufacturer : %s", device->Vendor ? device->Vendor : "unknown");
			upsdebugx(4, "- Product      : %s", device->Product ? device->Product : "unknown");
			upsdebugx(4, "- Serial Number: %s", device->Serial ? device->Serial : "unknown");
			upsdebugx(4, "- Bus          : %s", device->Bus ? device->Bus : "unknown");

			for (m = matcher; m; m = m->next) {
				
				switch (m->match_function(device, m->privdata))
				{
				case 0:
					upsdebugx(4, "Device does not match - skipping");
					goto next_device;
				case -1:
					fatal_with_errno(EXIT_FAILURE, "matcher");
					goto next_device;
				case -2:
					upsdebugx(4, "matcher: unspecified error");
					goto next_device;
				}
			}

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

				ret = callback(handle, device);
				if (ret >= 0) {
					upsdebugx(4, "USB device [%04x:%04x] opened", device->VendorID, device->ProductID);
					return ret;
				}
#ifdef HAVE_USB_DETACH_KERNEL_DRIVER_NP
				/* this method requires at least libusb 0.1.8:
				 * it force device claiming by unbinding
				 * attached driver... From libhid */
				if (usb_detach_kernel_driver_np(handle, 0) < 0) {
					upsdebugx(4, "failed to detach kernel driver from USB device: %s", usb_strerror());
				} else {
					upsdebugx(4, "detached kernel driver from USB device...");
				}
#endif
			}

			fatalx(EXIT_FAILURE, "USB device [%04x:%04x] matches, but driver callback failed: %s",
				device->VendorID, device->ProductID, usb_strerror());

		next_device:
			usb_close(handle);
		}
	}

	*handlep = NULL;
	upsdebugx(4, "No matching USB device found");

	return -1;
}
Exemplo n.º 5
0
static void blazer_initbattery(void)
{
    const char	*val;

    /* If no values were provided by the user in ups.conf, try to guesstimate
     * battery.charge, but announce it! */
    if ((batt.volt.nom != 1) && ((batt.volt.high == -1) || (batt.volt.low == -1))) {
        upslogx(LOG_INFO, "No values provided for battery high/low voltages in ups.conf\n");

        /* Basic formula, which should cover most cases */
        batt.volt.low = 104 * batt.volt.nom / 120;
        batt.volt.high = 130 * batt.volt.nom / 120;

        /* Publish these data too */
        dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low);
        dstate_setinfo("battery.voltage.high", "%.2f", batt.volt.high);

        upslogx(LOG_INFO, "Using 'guestimation' (low: %f, high: %f)!", batt.volt.low, batt.volt.high);
    }

    val = getval("runtimecal");
    if (val) {
        double	rh, lh, rl, ll;

        time(&lastpoll);

        if (sscanf(val, "%lf,%lf,%lf,%lf", &rh, &lh, &rl, &ll) < 4) {
            fatalx(EXIT_FAILURE, "Insufficient parameters for runtimecal");
        }

        if ((rl < rh) || (rh <= 0)) {
            fatalx(EXIT_FAILURE, "Parameter out of range (runtime)");
        }

        if ((lh > 100) || (ll > lh) || (ll <= 0)) {
            fatalx(EXIT_FAILURE, "Parameter out of range (load)");
        }

        batt.runt.exp = log(rl / rh) / log(lh / ll);
        upsdebugx(2, "battery runtime exponent : %.3f", batt.runt.exp);

        batt.runt.nom = rh * pow(lh / 100, batt.runt.exp);
        upsdebugx(2, "battery runtime nominal  : %.1f", batt.runt.nom);

    } else {
        upslogx(LOG_INFO, "Battery runtime will not be calculated (runtimecal not set)");
        return;
    }

    if (batt.chrg.act < 0) {
        batt.volt.low = batt.volt.nom;
        batt.volt.high = 1.15 * batt.volt.nom;

        blazer_battery(dstate_getinfo("battery.voltage"), NULL);
    }

    val = dstate_getinfo("battery.charge");
    if (val) {
        batt.runt.est = batt.runt.nom * strtod(val, NULL) / 100;
        upsdebugx(2, "battery runtime estimate : %.1f", batt.runt.est);
    } else {
        fatalx(EXIT_FAILURE, "Initial battery charge undetermined");
    }

    val = getval("chargetime");
    if (val) {
        batt.chrg.time = strtol(val, NULL, 10);

        if (batt.chrg.time <= 0) {
            fatalx(EXIT_FAILURE, "Charge time out of range [1..s]");
        }

        upsdebugx(2, "battery charge time      : %ld", batt.chrg.time);
    } else {
        upslogx(LOG_INFO, "No charge time specified, using built in default [%ld seconds]", batt.chrg.time);
    }

    val = getval("idleload");
    if (val) {
        load.low = strtod(val, NULL) / 100;

        if ((load.low <= 0) || (load.low > 1)) {
            fatalx(EXIT_FAILURE, "Idle load out of range [0..100]");
        }

        upsdebugx(2, "minimum load used (idle) : %.3f", load.low);
    } else {
        upslogx(LOG_INFO, "No idle load specified, using built in default [%.1f %%]", 100 * load.low);
    }
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
0
static int do_command(char type, const char *command, const char *parameters, char *response)
{
	char	buffer[SMALLBUF];
	int	count, ret;

	ser_flush_io(upsfd);

	if (response) {
		*response = '\0';
	}

	snprintf(buffer, sizeof(buffer), "~00%c%03d%s%s", type, (int)(strlen(command) + strlen(parameters)), command, parameters);

	ret = ser_send_pace(upsfd, 10000, "%s", buffer);
	if (ret <= 0) {
		upsdebug_with_errno(3, "do_command: send [%s]", buffer);
		return -1;
	}

	upsdebugx(3, "do_command: %d bytes sent [%s] -> OK", ret, buffer);

	ret = ser_get_buf_len(upsfd, (unsigned char *)buffer, 4, 3, 0);
	if (ret < 0) {
		upsdebug_with_errno(3, "do_command: read");
		return -1;
	}
	if (ret == 0) {
		upsdebugx(3, "do_command: read -> TIMEOUT");
		return -1;
	}

	buffer[ret] = '\0';
	upsdebugx(3, "do_command: %d byted read [%s]", ret, buffer);

	if (!strcmp(buffer, "~00D")) {

		ret = ser_get_buf_len(upsfd, (unsigned char *)buffer, 3, 3, 0);
		if (ret < 0) {
			upsdebug_with_errno(3, "do_command: read");
			return -1;
		}
		if (ret == 0) {
			upsdebugx(3, "do_command: read -> TIMEOUT");
			return -1;
		}

		buffer[ret] = '\0';
		upsdebugx(3, "do_command: %d bytes read [%s]", ret, buffer);

		count = atoi(buffer);
		if (count >= MAX_RESPONSE_LENGTH) {
			upsdebugx(3, "do_command: response exceeds expected size!");
			return -1;
		}

		if (count && !response) {
			upsdebugx(3, "do_command: response not expected!");
			return -1;
		}

		if (count == 0) {
			return 0;
		}

		ret = ser_get_buf_len(upsfd, (unsigned char *)response, count, 3, 0);
		if (ret < 0) {
			upsdebug_with_errno(3, "do_command: read");
			return -1;
		}
		if (ret == 0) {
			upsdebugx(3, "do_command: read -> TIMEOUT");
			return -1;
		}

		response[ret] = '\0';
		upsdebugx(3, "do_command: %d bytes read [%s]", ret, response);

		/* Tripp Lite pads their string responses with spaces.
		   I don't like that, so I remove them.  This is safe to
		   do with all responses for this protocol, so I just
		   do that here. */
		rtrim(response, ' ');

		return ret;
	}

	if (!strcmp(buffer, "~00A")) {
		return 0;
	}

	return -1;
}
Exemplo n.º 8
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]);
	}

}
Exemplo n.º 9
0
void upsdrv_updateinfo(void)
{
	CFPropertyListRef power_dictionary;
	CFStringRef power_source_state;
	CFNumberRef battery_voltage, battery_runtime;
	CFNumberRef current_capacity;
	CFBooleanRef is_charging;
	double max_capacity_value = 100.0, current_capacity_value;

	upsdebugx(1, "upsdrv_updateinfo()");

	power_dictionary = copy_power_dictionary( g_power_key );
	assert(power_dictionary); /* TODO: call dstate_datastale()? */

	status_init();

	/* Retrieve OL/OB state */
	power_source_state = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSPowerSourceStateKey));
	assert(power_source_state);
	CFRetain(power_source_state);

	upsdebugx(3, "Power Source State:");
	if(nut_debug_level >= 3) CFShow(power_source_state);

	if(!CFStringCompare(power_source_state, CFSTR(kIOPSACPowerValue), 0)) {
		status_set("OL");
	} else {
		status_set("OB");
	}

	CFRelease(power_source_state);

	/* Retrieve CHRG state */
	is_charging = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSIsChargingKey));
        if(is_charging) {
		Boolean is_charging_value;

		is_charging_value = CFBooleanGetValue(is_charging);
		if(is_charging_value) {
			status_set("CHRG");
		}
	}

	status_commit();

	/* Retrieve battery voltage */

	battery_voltage = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSVoltageKey));
	if(battery_voltage) {
		int battery_voltage_value;

		CFNumberGetValue(battery_voltage, kCFNumberIntType, &battery_voltage_value);
		upsdebugx(2, "battery_voltage = %d mV", battery_voltage_value);
		dstate_setinfo("battery.voltage", "%.3f", battery_voltage_value/1000.0);
	}

	/* Retrieve battery runtime */
	battery_runtime = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSTimeToEmptyKey));
	if(battery_runtime) {
		double battery_runtime_value;

		CFNumberGetValue(battery_runtime, kCFNumberDoubleType, &battery_runtime_value);

		upsdebugx(2, "battery_runtime = %.f minutes", battery_runtime_value);
		if(battery_runtime_value > 0) {
			dstate_setinfo("battery.runtime", "%d", (int)(battery_runtime_value*60));
		} else {
			dstate_delinfo("battery.runtime");
		}
	} else {
		dstate_delinfo("battery.runtime");
	}

	/* Retrieve current capacity */
	current_capacity = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSCurrentCapacityKey));
	if(current_capacity) {
		CFNumberGetValue(current_capacity, kCFNumberDoubleType, &current_capacity_value);

		upsdebugx(2, "Current Capacity = %.f/%.f units", current_capacity_value, max_capacity_value);
		if(max_capacity_value > 0) {
			dstate_setinfo("battery.charge", "%.f", 100.0 * current_capacity_value / max_capacity_value);
		}
	}

	/* TODO: it should be possible to set poll_interval (and maxage in the
	 * server) to an absurdly large value, and use notify(3) to get
	 * updates.
         */

	/*
	 * poll_interval = 2;
	 */

	dstate_dataok();
	CFRelease(power_dictionary);
}
Exemplo n.º 10
0
/* set DTR and RTS lines on a serial port to supply a passive
 * serial interface: DTR to 0 (-V), RTS to 1 (+V)
 */
static void dtr0rts1 (void)
{
	ser_set_dtr(upsfd, 0); 
	ser_set_rts(upsfd, 1); 
	upsdebugx(2, "DTR => 0, RTS => 1");
}
Exemplo n.º 11
0
/* update information */
void upsdrv_updateinfo(void)
{
	char	val[32];
	
	if (!ups_getinfo()){
		return;
	}
	
	/* input.frequency */
	upsdebugx(3, "input.frequency   (raw data): [raw: %u]",
	                            raw_data[INPUT_FREQUENCY]);
	dstate_setinfo("input.frequency", "%02.2f", input_freq());
	upsdebugx(2, "input.frequency: %s", dstate_getinfo("input.frequency"));

	/* output.frequency */
	upsdebugx(3, "output.frequency   (raw data): [raw: %u]",
	                            raw_data[OUTPUT_FREQUENCY]);
	dstate_setinfo("output.frequency", "%02.2f", output_freq());
	upsdebugx(2, "output.frequency: %s", dstate_getinfo("output.frequency"));

	/* ups.load */	
	upsdebugx(3, "ups.load  (raw data): [raw: %u]",
	                            raw_data[UPS_LOAD]);
	dstate_setinfo("ups.load", "%03.1f", load_level());
	upsdebugx(2, "ups.load: %s", dstate_getinfo("ups.load"));

	/* battery.charge */
	upsdebugx(3, "battery.charge (raw data): [raw: %u]",
	                            raw_data[BATTERY_CHARGE]);
	dstate_setinfo("battery.charge", "%03.1f", batt_level());
	upsdebugx(2, "battery.charge: %s", dstate_getinfo("battery.charge"));

	/* input.voltage */	
	upsdebugx(3, "input.voltage (raw data): [raw: %u]",
	                            raw_data[INPUT_VOLTAGE]);
	dstate_setinfo("input.voltage", "%03.1f",input_voltage());
	upsdebugx(2, "input.voltage: %s", dstate_getinfo("input.voltage"));
	
	/* output.voltage */	
	upsdebugx(3, "output.voltage (raw data): [raw: %u]",
	                            raw_data[OUTPUT_VOLTAGE]);
	dstate_setinfo("output.voltage", "%03.1f",output_voltage());
	upsdebugx(2, "output.voltage: %s", dstate_getinfo("output.voltage"));

	status_init();
	
	*val = 0;
	if (!(raw_data[STATUS_A] & MAINS_FAILURE)) {
		!(raw_data[STATUS_A] & OFF) ? 
			status_set("OL") : status_set("OFF");
	} else {
		status_set("OB");
	}

	if (raw_data[STATUS_A] & LOW_BAT)  status_set("LB");

	if (raw_data[STATUS_A] & AVR_ON) {
		input_voltage() < linevoltage ? 
			status_set("BOOST") : status_set("TRIM");
	}

	if (raw_data[STATUS_A] & OVERLOAD)  status_set("OVER");

	if (raw_data[STATUS_B] & BAD_BAT)  status_set("RB");

	if (raw_data[STATUS_B] & TEST)  status_set("TEST");

	status_commit();

	upsdebugx(2, "STATUS: %s", dstate_getinfo("ups.status"));
	dstate_dataok();
}
Exemplo n.º 12
0
static int detect_hardware(void)
{
	unsigned char OutBuff[20] ;
	unsigned char InpBuff[260] ;
	unsigned char *p ;
	int i, retries ;
	struct tm *Time ;
	time_t lTime ;

	ups.ge_2kVA = 0 ;

	for (retries=0 ; retries <= 4 ; retries++)
		{
		/* Identify UPS model */
		OutBuff[0] = CMD_GET_EEP_BLOCK ;		/* get EEPROM data */
		OutBuff[1] = EEP_UPS_MODEL ;			/* UPS model */
		OutBuff[2] = 8 ;							/* number of bytes */
		if ((p = CmdSerial(OutBuff, LEN_GET_EEP_BLOCK, InpBuff)) != NULL)
			{
			/* got UPS model */
			for (i=0 ; i<8 ; i++)
				ups.UpsModel[i] = p[i+5] ;
			ups.UpsModel[8] = '\0' ;
			upsdebugx(2, "get 'UPS model': %s", PrintErr(ups.ErrCode));
			break ;	/* UPS identified: exit from ' for' LOOP */
			}
		else
			{
			upsdebugx(1, "[%d] get 'UPS model': %s", retries, PrintErr(ups.ErrCode));
			upslogx(LOG_ERR, "[%d] Unable to identify UPS model [%s]", retries, PrintErr(ups.ErrCode));
			usleep(100000) ; /* small delay (1/10 s) for next retry */
			}
		}

	/* check if I was unable to find the UPS */
	if (retries == 4)	/* UPS not found! */
		return -1;

	/* UPS serial number */
	OutBuff[0] = CMD_GET_EEP_BLOCK ;		/* get EEPROM data */
	OutBuff[1] = EEP_SERIAL_NUM ;			/* UPS serial # */
	OutBuff[2] = 8 ;							/* number of bytes */
	if ((p = CmdSerial(OutBuff, LEN_GET_EEP_BLOCK, InpBuff)) != NULL)
		{
		/* got UPS serial # */
		for (i=0 ; i<8 ; i++)
			ups.SerialNumber[i] = p[i+5] ;
		ups.SerialNumber[8] = '\0' ;
		upsdebugx(2, "get 'UPS Serial #': %s", PrintErr(ups.ErrCode));
		}
	else
		{
		upsdebugx(1, "get 'UPS Serial #': %s", PrintErr(ups.ErrCode));
		upslogx(LOG_ERR, "Unable to identify UPS serial # [%s]", PrintErr(ups.ErrCode));
		return -1;
		}


	/* Get Production date & FW info */
	OutBuff[0] = CMD_GET_EEP_BLOCK ;		/* get EEPROM data */
	OutBuff[1] = EEP_PROD_DATE ;			/* Production date + HW version */
	OutBuff[2] = 8 ;							/* number of bytes */
	if ((p = CmdSerial(OutBuff, LEN_GET_EEP_BLOCK, InpBuff)) != NULL)
		{
		/* got Production date & FW info */
		p += 5 ;	/* 'p' points to eeprom data */
		ups.YearOfProd = 2000 + p[0] ;  /* Production year of the UPS */
		ups.MonthOfProd = p[1] ;        /* Production month of the UPS */
		ups.DayOfProd = p[2] ;          /* Production day of the UPS */
		ups.HW_MajorVersion = (p[3]>>4) & 0x0F ;  /* Hardware: Major version */
		ups.HW_MinorVersion = (p[3] & 0x0F)    ;  /* Hardware: Minor version */
		ups.BR_MajorVersion = (p[4]>>4) & 0x0F ;  /* BoardHardware: Major version */
		ups.BR_MinorVersion = (p[4] & 0x0F)    ;  /* BoardHardware: Minor version */
		ups.FW_MajorVersion = (p[5]>>4) & 0x0F ;  /* Firmware: Major version */
		ups.FW_MinorVersion = (p[5] & 0x0F)    ;  /* Firmware: Minor version */
		ups.FW_SubVersion = p[6] ;      /* Firmware: SUBVERSION (special releases */
		ups.BatteryNumber = p[7] ;      /* number of batteries in UPS */
		upsdebugx(2, "get 'Production date': %s", PrintErr(ups.ErrCode));
		}
Exemplo n.º 13
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");
}
Exemplo n.º 14
0
/* for dummy mode
 * parse the definition file and process its content
 */ 
static int parse_data_file(int upsfd)
{
	char	fn[SMALLBUF];
	char	*ptr, var_value[MAX_STRING_SIZE];
	int		value_args = 0, counter;
	time_t	now;

	time(&now);

	upsdebugx(1, "entering parse_data_file()");

	if (now < next_update)
	{
		upsdebugx(1, "leaving (paused)...");
		return 1;
	}

	/* initialise everything, to loop back at the beginning of the file */
	if (ctx == NULL)
	{
		ctx = (PCONF_CTX_t *)xmalloc(sizeof(PCONF_CTX_t));

		if (device_path[0] == '/')
			snprintf(fn, sizeof(fn), "%s", device_path);
		else
			snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path);

		pconf_init(ctx, upsconf_err);

		if (!pconf_file_begin(ctx, fn))
			fatalx(EXIT_FAILURE, "Can't open dummy-ups definition file %s: %s",
				fn, ctx->errmsg);
	}

	/* Reset the next call time, so that we can loop back on the file
	 * if there is no blocking action (ie TIMER) until the end of the file */
	next_update = -1;

	/* Now start or continue parsing... */
	while (pconf_file_next(ctx))
	{
		if (pconf_parse_error(ctx))
		{
			upsdebugx(2, "Parse error: %s:%d: %s",
				fn, ctx->linenum, ctx->errmsg);
			continue;
		}

		/* Check if we have something to process */
		if (ctx->numargs < 1)
			continue;

		/* Process actions (only "TIMER" ATM) */
		if (!strncmp(ctx->arglist[0], "TIMER", 5))
		{
			/* TIMER <seconds> will wait "seconds" before
			 * continuing the parsing */
			int delay = atoi (ctx->arglist[1]);
			time(&next_update);
			next_update += delay;
			upsdebugx(1, "suspending execution for %i seconds...", delay);
			break;
		}

		/* Remove ":" suffix, after the variable name */
		if ((ptr = strchr(ctx->arglist[0], ':')) != NULL)
			*ptr = '\0';

		upsdebugx(3, "parse_data_file: variable \"%s\" with %d args",
			ctx->arglist[0], (int)ctx->numargs);

		/* Skip the driver.* collection data */
		if (!strncmp(ctx->arglist[0], "driver.", 7))
		{
			upsdebugx(2, "parse_data_file: skipping %s", ctx->arglist[0]);
			continue;
		}

		/* From there, we get varname in arg[0], and values in other arg[1...x] */
		/* special handler for status */
		if (!strncmp( ctx->arglist[0], "ups.status", 10))
		{
			status_init();
			for (counter = 1, value_args = ctx->numargs ;
				counter < value_args ; counter++)
			{
				status_set(ctx->arglist[counter]);
			}
			status_commit();
		}
		else
		{
			for (counter = 1, value_args = ctx->numargs ;
				counter < value_args ; counter++)
			{
				if (counter == 1) /* don't append the first space separator */
					snprintf(var_value, sizeof(var_value), "%s", ctx->arglist[counter]);
				else
					snprintfcat(var_value, sizeof(var_value), " %s", ctx->arglist[counter]);
			}

			if (setvar(ctx->arglist[0], var_value) == STAT_SET_UNKNOWN)
			{
				upsdebugx(2, "parse_data_file: can't add \"%s\" with value \"%s\"\nError: %s",
					ctx->arglist[0], var_value, ctx->errmsg);
			}
			else
			{ 
				upsdebugx(3, "parse_data_file: added \"%s\" with value \"%s\"",
					ctx->arglist[0], var_value);
			}
		}
	}

	/* Cleanup parseconf if there is no pending action */
	if (next_update == -1)
	{
		pconf_finish(ctx);
		free(ctx);
		ctx=NULL;
	}
	return 1;
}
Exemplo n.º 15
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);
}
Exemplo n.º 16
0
void upsdrv_initups(void)
{
	CFArrayRef power_source_key_list;
	CFIndex num_keys, index;
	CFDictionaryRef power_dictionary;
	CFTypeRef power_blob;
	CFStringRef potential_key, potential_model;
	char *device_name = device_path, *model_name; /* regex(3) */
	char potential_device_name[80], potential_model_name[80];
        regex_t name_regex, model_regex;
	int ret;

	upsdebugx(3, "upsdrv_initups(): Power Sources blob:");
	/* upsfd = ser_open(device_path); */
	/* ser_set_speed(upsfd, device_path, B1200); */
	power_blob = IOPSCopyPowerSourcesInfo();
	if(!power_blob) {
		fatalx(EXIT_FAILURE, "Couldn't retrieve Power Sources blob");
	}

	if(nut_debug_level >= 3) CFShow(power_blob);

	if(!strcmp(device_name, "auto")) {
		device_name = "/UPS";
	}

	upsdebugx(2, "Matching power supply key names against regex '%s'", device_name);

        ret = regcomp(&name_regex, device_name, REG_EXTENDED|REG_NOSUB|REG_ICASE);

	if(ret) {
		fatalx(EXIT_FAILURE,
				"Failed to compile regex from 'port' parameter: '%s'.",
				device_name);
	}

	if((model_name = getval("model"))) {
		upsdebugx(2, "Matching power supply model names against regex '%s'", model_name);
		ret = regcomp(&model_regex, model_name, REG_EXTENDED|REG_NOSUB|REG_ICASE);

		if(ret) {
			fatalx(EXIT_FAILURE,
					"Failed to compile regex from 'model' parameter: '%s'.",
					model_name);
		}
	}

	power_source_key_list = IOPSCopyPowerSourcesList(power_blob);

	num_keys = CFArrayGetCount(power_source_key_list);
	upsdebugx(1, "Number of power supplies found: %d", (int)num_keys);

	if(nut_debug_level >= 3) CFShow(power_source_key_list);

	if(num_keys < 1) {
		/* bail */
		fatalx(EXIT_FAILURE, "Couldn't find any UPS or battery");
	}

	for(index=0; index < num_keys; index++) {
		potential_key = CFArrayGetValueAtIndex(power_source_key_list, index);
		CFStringGetCString(potential_key, potential_device_name,
				sizeof(potential_device_name), kCFStringEncodingUTF8);
		upsdebugx(1, "    Power supply: %s", potential_device_name);

		ret = regexec(&name_regex, potential_device_name, 0,0,0);

		power_dictionary = copy_power_dictionary(potential_key);

		upsdebugx(2, "Getting 'Name' key (UPS model)");

		potential_model = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSNameKey));
		CFStringGetCString(potential_model, potential_model_name, sizeof(potential_model_name), kCFStringEncodingUTF8);
		upsdebugx(1, "        model name: %s", potential_model_name);

		CFRelease(power_dictionary);

		/* Does key match? Check model: */
		if (!ret) {
			if(model_name) {
				ret = regexec(&model_regex, potential_model_name, 0,0,0);
				if(!ret) {
					upsdebugx(2, "Matched model name");
					break;
				}
			} else {
				upsdebugx(2, "Matched key name");
				break;
			}
		}
	}

        regfree(&name_regex);
	if(model_name) {
		regfree(&model_regex);
	}

	if(ret) {
		fatalx(EXIT_FAILURE, "Couldn't find UPS or battery matching both 'port' (%s) and 'model' (%s)",
			device_name, model_name);
	}

	g_power_key = potential_key;
	CFRetain(g_power_key);
	upsdebugx(2, "g_power_key = ");
	if(nut_debug_level >= 2) CFShow(g_power_key);
	upsdebugx(2, "end g_power_key.");

	power_dictionary = copy_power_dictionary(g_power_key);
	assert(power_dictionary);
	if(nut_debug_level >= 3) CFShow(power_dictionary);

	/* the upsh handlers can't be done here, as they get initialized
	 * shortly after upsdrv_initups returns to main.
	 */

	/* don't try to detect the UPS here */

	/* do stuff */

	CFRelease(power_dictionary);
}
Exemplo n.º 17
0
void upsdrv_updateinfo(void)
{
	time_t now;
	int ok;
	float load;

	if (status & UPSC_STAT_NOTINIT) {
		upsdrv_initinfo();
	}

	if (status & UPSC_STAT_NOTINIT) {
		return;
	}

	status = 0;

	ok = upsc_getparams("UPDS", simple);

	time(&now);
	if (ok && now - last_full > full_update_timer) {
		last_full = now;
		ok = upsc_getparams("UPDV", nominal);
		if (ok && can_upbs)
			ok = upsc_getparams("UPBS", battery);
	}

	if (!ok) {
		dstate_datastale();
		last_full = 0;
		return;
	}

	if (!inited_phaseinfo) {
		if (dstate_getinfo("input.L3-L1.voltage") ||
				dstate_getinfo("input.L3-N.voltage")) {
			num_inphases = 3;

			change_name(simple,
				"input.current", "input.L1.current");
			change_name(simple,
				"input.realpower", "input.L1.realpower");
			change_name(simple,
				"input.power", "input.L1.power");
			change_name(simple,
				"input.voltage", "input.L1-N.voltage");
		}
		if (dstate_getinfo("output.L3-L1.voltage") ||
				dstate_getinfo("output.L3-N.voltage")) {
			const char *s;

			num_outphases = 3;

			if ((s=dstate_getinfo("ups.model")) &&
					(!strncmp(s, "UPS9075", 7) ||
					!strncmp(s, "UPS9100", 7) ||
					!strncmp(s, "UPS9150", 7) ||
					!strncmp(s, "UPS9200", 7) ||
					!strncmp(s, "UPS9250", 7) ||
					!strncmp(s, "UPS9300", 7) ||
					!strncmp(s, "UPS9400", 7) ||
					!strncmp(s, "UPS9500", 7) ||
					!strncmp(s, "UPS9600", 7)) ) {
				/* Insert kludges for Fiskars UPS9000 here */
				upslogx(LOG_INFO, "Fiskars UPS9000 detected, protocol kludges activated");
				batt_volt_nom = 384;
				dstate_setinfo("battery.voltage.nominal", "%.0f", batt_volt_nom);

			}
			else {
				outpwr_factor *= 3;
			}

			change_name(simple,
				"output.current", "output.L1.current");
			change_name(simple,
				"output.current.peak", "output.L1.current.peak");
			change_name(simple,
				"output.realpower", "output.L1.realpower");
			change_name(simple,
				"output.power", "output.L1.power");
			change_name(simple,
				"output.voltage", "output.L1-N.voltage");
		}

		dstate_setinfo("input.phases", "%d", num_inphases);
		dstate_setinfo("output.phases", "%d", num_outphases);

		inited_phaseinfo=1;
	}

	load = calc_upsload();

	if (load >= 0) {
		upsdebugx(2, "ups.load: %.1f", load*100);
		dstate_setinfo("ups.load", "%.1f", load*100);
	}
	else {
		upsdebugx(2, "ups.load: No value");
	}

	/* TODO/FIXME: Set UPS date/time on startup and daily if needed */
	if (can_updt) {
		char dtbuf[UPSC_BUFLEN];
		if (upsc_getvalue("UPDT", "0", "ACDT", NULL, dtbuf)) {
			dstate_setinfo("ups.date", "%s", dtbuf);
		}
	}
	if (can_uptm) {
		char tmbuf[UPSC_BUFLEN];
		if (upsc_getvalue("UPTM", "0", "ACTM", NULL, tmbuf)) {
			dstate_setinfo("ups.time", "%s", tmbuf);
		}
	}


	if (batt_charge < 0) {
		if (batt_current < 0) {
			/* Reset battery current history if discharging */
			numbatthist = lastbatthist = 0;
		}
		batt_charge = batt_charge_pct();
	}
	if (batt_charge >= 0) {
		dstate_setinfo("battery.charge", "%.1f", batt_charge);
	}
	else {
		dstate_delinfo("battery.charge");
	}

	/* 9999 == unknown value */
	if (batt_runtime >= 0 && batt_runtime < 9999) {
		dstate_setinfo("battery.runtime", "%.0f", batt_runtime*60);
	}
	else if (load > 0 && batt_disch_curr_max != 0) {
		float est_battcurr = load * abs(batt_disch_curr_max);
		/* Peukert equation */
		float runtime = (batt_cap_nom*3600)/pow(est_battcurr, 1.35);

		upsdebugx(2, "Calculated runtime: %.0f seconds", runtime);
		if (batt_runtime_max > 0 && runtime > batt_runtime_max*60) {
			runtime = batt_runtime_max*60;
		}
		dstate_setinfo("battery.runtime", "%.0f", runtime);

	}
	else if (batt_runtime_max > 0) {
		/* Show max possible runtime as reported by UPS */
		dstate_setinfo("battery.runtime", "%.0f", batt_runtime_max*60);
	}
	else {
		dstate_delinfo("battery.runtime");
	}
	/* Some UPSen only provides this when on battery, so reset between
	 * each iteration to make sure we use the right value */
	batt_charge = -1;
	batt_runtime = -1;


	if (!(status & UPSC_STAT_ONBATT))
		status |= UPSC_STAT_ONLINE;

	upsc_setstatus(status);

	dstate_dataok();
	ser_comm_good();
}
Exemplo n.º 18
0
static int phoenix_command(const char *cmd, char *buf, size_t buflen)
{
	char	tmp[SMALLBUF];
	int	ret;
	size_t	i;

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

		/* Read data in 8-byte chunks */
		/* ret = usb->get_interrupt(udev, (unsigned char *)tmp, 8, 1000); */
		ret = usb_interrupt_read(udev, 0x81, tmp, 8, 1000);

		/*
		 * This USB to serial implementation is crappy. In order to read correct
		 * replies we need to flush the output buffers of the converter until we
		 * get no more data (ie, it times out).
		 */
		switch (ret)
		{
		case -EPIPE:		/* Broken pipe */
			usb_clear_halt(udev, 0x81);
		case -ETIMEDOUT:	/* Connection timed out */
			break;
		}

		if (ret < 0) {
			upsdebugx(3, "flush: %s", usb_strerror());
			break;
		}

		upsdebug_hex(4, "dump", tmp, ret);
	}

	memset(tmp, 0, sizeof(tmp));
	snprintf(tmp, sizeof(tmp), "%s", cmd);

	for (i = 0; i < strlen(tmp); i += ret) {

		/* Write data in 8-byte chunks */
		/* ret = usb->set_report(udev, 0, (unsigned char *)&tmp[i], 8); */
		ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
			0x09, 0x200, 0, &tmp[i], 8, 1000);

		if (ret <= 0) {
			upsdebugx(3, "send: %s", ret ? usb_strerror() : "timeout");
			return ret;
		}
	}

	upsdebugx(3, "send: %.*s", (int)strcspn(tmp, "\r"), tmp);

	memset(buf, 0, buflen);

	for (i = 0; (i <= buflen-8) && (strchr(buf, '\r') == NULL); i += ret) {

		/* Read data in 8-byte chunks */
		/* ret = usb->get_interrupt(udev, (unsigned char *)&buf[i], 8, 1000); */
		ret = usb_interrupt_read(udev, 0x81, &buf[i], 8, 1000);

		/*
		 * Any errors here mean that we are unable to read a reply (which
		 * will happen after successfully writing a command to the UPS)
		 */
		if (ret <= 0) {
			upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
			return ret;
		}
	}

	upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
	return i;
}
Exemplo n.º 19
0
/* get the answer of a command from the ups. And check that the answer is for this command */
int get_answer(unsigned char *data, unsigned char command)
{
	unsigned char	my_buf[128];	/* packet has a maximum length of 121+5 bytes */
	int		length, end_length = 0, res, endblock = 0, start = 0;
	unsigned char	block_number, sequence, pre_sequence = 0;

	while (endblock != 1){

		do {
			/* Read PW_COMMAND_START_BYTE byte */
			res = ser_get_char(upsfd, my_buf, 1, 0);

			if (res != 1) {
				upsdebugx(1,"Receive error (PW_COMMAND_START_BYTE): %d, cmd=%x!!!\n", res, command);
				return -1;
			}

			start++;

		} while ((my_buf[0] != PW_COMMAND_START_BYTE) && (start < 128));
		
		if (start == 128) {
			ser_comm_fail("Receive error (PW_COMMAND_START_BYTE): packet not on start!!%x\n", my_buf[0]);
			return -1;
		}

		/* Read block number byte */
		res = ser_get_char(upsfd, my_buf+1, 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (Block number): %d!!!\n", res);
			return -1;
		}

		block_number = (unsigned char)my_buf[1];

		if (command <= 0x43) {
			if ((command - 0x30) != block_number){
				ser_comm_fail("Receive error (Request command): %x!!!\n", block_number);
				return -1;
			}
		}

		if (command >= 0x89) {
			if ((command == 0xA0) && (block_number != 0x01)){
				ser_comm_fail("Receive error (Requested only mode command): %x!!!\n", block_number);
				return -1;
			}

			if ((command != 0xA0) && (block_number != 0x09)){
				ser_comm_fail("Receive error (Control command): %x!!!\n", block_number);
				return -1;
			}
		}

		/* Read data length byte */
		res = ser_get_char(upsfd, my_buf+2, 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (length): %d!!!\n", res);
			return -1;
		}

		length = (unsigned char)my_buf[2];

		if (length < 1) {
			ser_comm_fail("Receive error (length): packet length %x!!!\n", length);
			return -1;
		}

		/* Read sequence byte */
		res = ser_get_char(upsfd, my_buf+3, 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (sequence): %d!!!\n", res);
			return -1;
		}

		sequence = (unsigned char)my_buf[3];

		if ((sequence & 0x80) == 0x80) {
			endblock = 1;
		}

		if ((sequence & 0x07) != (pre_sequence + 1)) {
			ser_comm_fail("Not the right sequence received %x!!!\n", sequence);
			return -1;
		}

		pre_sequence = sequence;

		/* Try to read all the remainig bytes */
		res = ser_get_buf_len(upsfd, my_buf+4, length, 1, 0);

		if (res != length) {
			ser_comm_fail("Receive error (data): got %d bytes instead of %d!!!\n", res, length);
			return -1;
		}

		/* Get the checksum byte */
		res = ser_get_char(upsfd, my_buf+(4+length), 1, 0);

		if (res != 1) {
			ser_comm_fail("Receive error (checksum): %x!!!\n", res);
			return -1;
		}

		/* now we have the whole answer from the ups, we can checksum it */
		if (!checksum_test(my_buf)) {
			ser_comm_fail("checksum error! ");
			return -1;
		}

		memcpy(data+end_length, my_buf+4, length);
		end_length += length;

	}

	upsdebug_hex (5, "get_answer", data, end_length);
	ser_comm_good();

	return end_length;
}
Exemplo n.º 20
0
static int krauler_command(const char *cmd, char *buf, size_t buflen)
{
	/*
	 * Still not implemented:
	 * 0x6	T<n>	(don't know how to pass the parameter)
	 * 0x68 and 0x69 both cause shutdown after an undefined interval
	*/
	const struct {
		const char	*str;		/* Megatec command */
		const int	index;	/* Krauler string index for this command */
		const char	prefix;	/* character to replace the first byte in reply */
	}  command[] = {
		{ "Q1\r", 0x03, '(' },
		{ "F\r",  0x0d, '#' },
		{ "I\r",  0x0c, '#' },
		{ "T\r",  0x04, '\r' },
		{ "TL\r", 0x05, '\r' },
		{ "Q\r",  0x07, '\r' },
		{ "C\r",  0x0b, '\r' },
		{ "CT\r", 0x0b, '\r' },
		{ NULL }
	};

	int	i;

	upsdebugx(3, "send: %.*s", (int)strcspn(cmd, "\r"), cmd);

	for (i = 0; command[i].str; i++) {
		int	retry;

		if (strcmp(cmd, command[i].str)) {
			continue;
		}

		for (retry = 0; retry < 10; retry++) {
			int	ret;

			if (langid_fix != -1) {
				/* Apply langid_fix value */
				ret = usb_get_string(udev, command[i].index, langid_fix, buf, buflen);
			}
			else {
				ret = usb_get_string_simple(udev, command[i].index, buf, buflen);
			}

			if (ret <= 0) {
				upsdebugx(3, "read: %s", ret ? usb_strerror() : "timeout");
				return ret;
			}

			/* this may serve in the future */
			upsdebugx(1, "received %d (%d)", ret, buf[0]);

			if (langid_fix != -1) {
				/* Limit this check, at least for now */
				/* Invalid receive size - message corrupted */
				if (ret != buf[0]) 
				{
					upsdebugx(1, "size mismatch: %d / %d", ret, buf[0]);
					continue;
				}

				/* Simple unicode -> ASCII inplace conversion
				 * FIXME: this code is at least shared with mge-shut/libshut
				 * Create a common function? */
				unsigned int di, si, size = buf[0];
				for (di = 0, si = 2; si < size; si += 2) {
					if (di >= (buflen - 1))
						break;

					if (buf[si + 1]) /* high byte */
						buf[di++] = '?';
					else
						buf[di++] = buf[si];
				}
				buf[di] = 0;
				ret = di;
			}

			/* "UPS No Ack" has a special meaning */
			if (!strcasecmp(buf, "UPS No Ack")) {
				upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
				continue;
			}

			/* Replace the first byte of what we received with the correct one */
			buf[0] = command[i].prefix;

			upsdebugx(3, "read: %.*s", (int)strcspn(buf, "\r"), buf);
			return ret;
		}

		return 0;
	}

	/* echo the unknown command back */
	upsdebugx(3, "read: %.*s", (int)strcspn(cmd, "\r"), cmd);
	return snprintf(buf, buflen, "%s", cmd);
}
Exemplo n.º 21
0
void upsdrv_initinfo(void)
{
	struct {
		const char	*var;
		unsigned char	len;
	} vartab[] = {
		{ "ups.model",15 },
		{ "ups.firmware",8 },
		{ "ups.serial",10 },
		{ "ups.mfr.date",4 },
		{ NULL }
	};

	char	buf[LARGEBUF];
	int	i,bitn,vari,ret=0,offset=4,readok=0;
	char	command[6], reply[8];
	unsigned int	value;

	dstate_setinfo("ups.mfr", "%s", "Liebert");

	for (vari = 0; vartab[vari].var; vari++) {
		upsdebugx(1, "reading: %s", vartab[vari].var);

		for (i = 0; i < vartab[vari].len; i++) {
			snprintf(command, sizeof(command), "\x01\x88\x02\x01%c", i+offset);
		command[5] = cksum(command, 5);

		ret = do_command((unsigned char *)command, reply, 6);
			if (ret < 8) {
				upsdebug_hex(2, "send: truncated", command, ret);
				break;
			}

			buf[i<<1] = reply[6];
			buf[(i<<1)+1] = reply[5];
	}

	buf[i<<1] = 0;
		upsdebugx(1, "return: %d (8=success)", ret);

		if (ret == 8) { /* last command successful */
			dstate_setinfo(vartab[vari].var,"%s",buf);
			readok++;
		}
		offset+=vartab[vari].len;
	} /* for */
	if (!readok) {
		fatalx(EXIT_FAILURE, "ESP-II capable UPS not detected");
	}

	/* determine number of input & output phases and ups type */
	memcpy(command,cmd_upstype,6);
	ret = do_command((unsigned char *)command, reply, 6);
	if (ret < 8) {
		upsdebug_hex(2, "send: phase detection: truncated", command, ret);
	}
	else {
		/* input: from bit 0 to bit 1 (2 bits) */
		for (value=0,bitn=0;bitn<2;bitn++) {
			if (IsBitSet(reply[6],(unsigned short int)bitn)) /* bit range measurement on LSByte*/
				value+=(1<<(unsigned short int)(bitn - 0));
		}
		num_inphases=value;
		dstate_setinfo("input.phases", "%d", value);

		/* output: from bit 4 to bit 5  (2 bits)*/
		for (value=0,bitn=4;bitn<6;bitn++) {
			if (IsBitSet(reply[6],(unsigned short int)bitn)) /* bit range measurement on LSByte*/
				value+=(1<<(unsigned short int)(bitn - 4));
		}
		num_outphases=value;
		dstate_setinfo("output.phases", "%d", value);

		if (reply[5] & (1<<4)) {	/* ISOFFLINE */
			dstate_setinfo("ups.type", "offline") ;
		}
		else if (reply[5] & (1<<5)) { /* ISINTERACTIVE */
			dstate_setinfo("ups.type", "line-interactive") ;
		}
		else {
			dstate_setinfo("ups.type", "online") ;
		}
	}

	/* determine scaling */
	/* full scaling output not defined yet, but we can differentiate sets of 
	 * multipliers based on a sample scaling reading */
	memcpy(command,cmd_scaling1,6);
	ret = do_command((unsigned char *)command, reply, 6);
	if (ret < 8) {
		upsdebug_hex(2, "send: scaling detection: truncated", command, ret);
	}
	else { /* add here multipliers that differentiate between models */
		switch (reply[6]) {
		case 1: /* GXT-2 */
			multi[M_FREQUENCY]=0.1;
			multi[M_VOLT_DC]=1.0;
			multi[M_POWER]=1.0;
			multi[M_NOMPOWER]=1.0;
			break;
		case 2: /* NXe */
			multi[M_FREQUENCY]=0.01;
			multi[M_VOLT_DC]=0.1;
			multi[M_POWER]=100.0;
			multi[M_NOMPOWER]=100.0;
			break;
		default: /* the default values from definition of multi will be used */
			break;
		}
	}

	upsh.instcmd = instcmd;
	upsh.setvar = setvar;
}
Exemplo n.º 22
0
/*
 * Generic command processing function. Send a command and read a reply.
 * Returns < 0 on error, 0 on timeout and the number of bytes read on
 * success.
 */
int blazer_command(const char *cmd, char *buf, size_t buflen)
{
#ifndef TESTING
	int	ret;

	if (udev == NULL) {
		ret = usb->open(&udev, &usbdevice, reopen_matcher, NULL);

		if (ret < 1) {
			return ret;
		}
	}

	ret = (*subdriver_command)(cmd, buf, buflen);
	if (ret >= 0) {
		return ret;
	}

	switch (ret)
	{
	case -EBUSY:		/* Device or resource busy */
		fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver");

	case -EPERM:		/* Operation not permitted */
		fatal_with_errno(EXIT_FAILURE, "Permissions problem");

	case -EPIPE:		/* Broken pipe */
		if (usb_clear_halt(udev, 0x81) == 0) {
			upsdebugx(1, "Stall condition cleared");
			break;
		}
#ifdef ETIME
	case -ETIME:		/* Timer expired */
#endif
		if (usb_reset(udev) == 0) {
			upsdebugx(1, "Device reset handled");
		}
	case -ENODEV:		/* No such device */
	case -EACCES:		/* Permission denied */
	case -EIO:		/* I/O error */
	case -ENXIO:		/* No such device or address */
	case -ENOENT:		/* No such file or directory */
		/* Uh oh, got to reconnect! */
		usb->close(udev);
		udev = NULL;
		break;

	case -ETIMEDOUT:	/* Connection timed out */
	case -EOVERFLOW:	/* Value too large for defined data type */
#ifdef EPROTO
	case -EPROTO:		/* Protocol error */
#endif
	default:
		break;
	}

	return ret;
#else
	const struct {
		const char	*command;
		const char	*answer;
	} testing[] = {
		{ "Q1\r", "(215.0 195.0 230.0 014 49.0 2.27 30.0 00101000\r" },
		{ "F\r",  "#230.0 000 024.0 50.0\r" },
		{ "I\r",  "#-------------   ------     VT12046Q  \r" },
		{ NULL }
	};

	int	i;

	memset(buf, 0, buflen);

	for (i = 0; testing[i].command; i++) {

		if (strcasecmp(cmd, testing[i].command)) {
			continue;
		}

		return snprintf(buf, buflen, "%s", testing[i].answer);
	}

	return snprintf(buf, buflen, "%s", testing[i].command);
#endif
}
Exemplo n.º 23
0
static int blazer_status(const char *cmd)
{
    const struct {
        const char	*var;
        const char	*fmt;
        double	(*conv)(const char *, char **);
    } status[] = {
        { "input.voltage", "%.1f", strtod },
        { "input.voltage.fault", "%.1f", strtod },
        { "output.voltage", "%.1f", strtod },
        { "ups.load", "%.0f", blazer_load },
        { "input.frequency", "%.1f", strtod },
        { "battery.voltage", "%.2f", blazer_battery },
        { "ups.temperature", "%.1f", strtod },
        { NULL }
    };

    char	buf[SMALLBUF], *val, *last = NULL;
    int	i;

    /*
     * > [Q1\r]
     * < [(226.0 195.0 226.0 014 49.0 27.5 30.0 00001000\r]
     *    01234567890123456789012345678901234567890123456
     *    0         1         2         3         4
     */
    if (blazer_command(cmd, buf, sizeof(buf)) < 46) {
        upsdebugx(2, "%s: short reply", __func__);
        return -1;
    }

    if (buf[0] != '(') {
        upsdebugx(2, "%s: invalid start character [%02x]", __func__, buf[0]);
        return -1;
    }

    for (i = 0, val = strtok_r(buf+1, " ", &last); status[i].var; i++, val = strtok_r(NULL, " \r\n", &last)) {

        if (!val) {
            upsdebugx(2, "%s: parsing failed", __func__);
            return -1;
        }

        if (strspn(val, "0123456789.") != strlen(val)) {
            upsdebugx(2, "%s: non numerical value [%s]", __func__, val);
            continue;
        }

        dstate_setinfo(status[i].var, status[i].fmt, status[i].conv(val, NULL));
    }

    if (!val) {
        upsdebugx(2, "%s: parsing failed", __func__);
        return -1;
    }

    if (strspn(val, "01") != 8) {
        upsdebugx(2, "Invalid status [%s]", val);
        return -1;
    }

    if (val[7] == '1') {	/* Beeper On */
        dstate_setinfo("ups.beeper.status", "enabled");
    } else {
        dstate_setinfo("ups.beeper.status", "disabled");
    }

    if (val[4] == '1') {	/* UPS Type is Standby (0 is On_line) */
        dstate_setinfo("ups.type", "offline / line interactive");
    } else {
        dstate_setinfo("ups.type", "online");
    }

    status_init();

    if (val[0] == '1') {	/* Utility Fail (Immediate) */
        status_set("OB");
        online = 0;
    } else {
        status_set("OL");
        online = 1;
    }

    if (val[1] == '1') {	/* Battery Low */
        status_set("LB");
    }

    if (val[2] == '1') {	/* Bypass/Boost or Buck Active */

        double	vi, vo;

        vi = strtod(dstate_getinfo("input.voltage"),  NULL);
        vo = strtod(dstate_getinfo("output.voltage"), NULL);

        if (vo < 0.5 * vi) {
            upsdebugx(2, "%s: output voltage too low", __func__);
        } else if (vo < 0.95 * vi) {
            status_set("TRIM");
        } else if (vo < 1.05 * vi) {
            status_set("BYPASS");
        } else if (vo < 1.5 * vi) {
            status_set("BOOST");
        } else {
            upsdebugx(2, "%s: output voltage too high", __func__);
        }
    }

    if (val[5] == '1') {	/* Test in Progress */
        status_set("CAL");
    }

    alarm_init();

    if (val[3] == '1') {	/* UPS Failed */
        alarm_set("UPS selftest failed!");
    }

    if (val[6] == '1') {	/* Shutdown Active */
        alarm_set("Shutdown imminent!");
        status_set("FSD");
    }

    alarm_commit();

    status_commit();

    return 0;
}
Exemplo n.º 24
0
void upsdrv_initups(void)
{
#ifndef TESTING
	const struct {
		const char	*name;
		int		(*command)(const char *cmd, char *buf, size_t buflen);
	} subdriver[] = {
		{ "cypress", &cypress_command },
		{ "phoenix", &phoenix_command },
		{ "ippon", &ippon_command },
		{ "krauler", &krauler_command },
		{ NULL }
	};

	int	ret, langid;
	char	tbuf[255]; /* Some devices choke on size > 255 */
	char	*regex_array[6];

	char	*subdrv = getval("subdriver");

	regex_array[0] = getval("vendorid");
	regex_array[1] = getval("productid");
	regex_array[2] = getval("vendor");
	regex_array[3] = getval("product");
	regex_array[4] = getval("serial");
	regex_array[5] = getval("bus");

	/* check for language ID workaround (#1) */
	if (getval("langid_fix")) {
		/* skip "0x" prefix and set back to hexadecimal */
		if (sscanf(getval("langid_fix") + 2, "%x", &langid_fix) != 1) {
			upslogx(LOG_NOTICE, "Error enabling language ID workaround");
		}
		else {
			upsdebugx(2, "language ID workaround enabled (using '0x%x')", langid_fix);
		}
	}

	/* pick up the subdriver name if set explicitly */
	if (subdrv) {
		int	i;

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

		for (i = 0; subdriver[i].name; i++) {

			if (strcasecmp(subdrv, subdriver[i].name)) {
				continue;
			}

			subdriver_command =  subdriver[i].command;
			break;
		}

		if (!subdriver_command) {
			fatalx(EXIT_FAILURE, "Subdriver \"%s\" not found!", subdrv);
		}
	}

	ret = USBNewRegexMatcher(&regex_matcher, regex_array, REG_ICASE | REG_EXTENDED);
	switch (ret)
	{
	case -1:
		fatal_with_errno(EXIT_FAILURE, "USBNewRegexMatcher");
	case 0:
		break;	/* all is well */
	default:
		fatalx(EXIT_FAILURE, "invalid regular expression: %s", regex_array[ret]);
	}


	/* link the matchers */
	regex_matcher->next = &device_matcher;

	ret = usb->open(&udev, &usbdevice, regex_matcher, NULL);
	if (ret < 0) {
		fatalx(EXIT_FAILURE,
			"No supported devices found. Please check your device availability with 'lsusb'\n"
			"and make sure you have an up-to-date version of NUT. If this does not help,\n"
			"try running the driver with at least 'subdriver', 'vendorid' and 'productid'\n"
			"options specified. Please refer to the man page for details about these options\n"
			"(man 8 blazer_usb).\n");
	}

	if (!subdriver_command) {
		fatalx(EXIT_FAILURE, "No subdriver selected");
	}

	/* create a new matcher for later reopening */
	ret = USBNewExactMatcher(&reopen_matcher, &usbdevice);
	if (ret) {
		fatal_with_errno(EXIT_FAILURE, "USBNewExactMatcher");
	}

	/* link the matchers */
	reopen_matcher->next = regex_matcher;

	dstate_setinfo("ups.vendorid", "%04x", usbdevice.VendorID);
	dstate_setinfo("ups.productid", "%04x", usbdevice.ProductID);

	/* check for language ID workaround (#2) */
	if (langid_fix != -1) {
		/* Future improvement:
		 *   Asking for the zero'th index is special - it returns a string
		 *   descriptor that contains all the language IDs supported by the
		 *   device. Typically there aren't many - often only one. The
		 *   language IDs are 16 bit numbers, and they start at the third byte
		 *   in the descriptor. See USB 2.0 specification, section 9.6.7, for
		 *   more information on this.
		 * This should allow automatic application of the workaround */
		ret = usb_get_string(udev, 0, 0, tbuf, sizeof(tbuf));
		if (ret >= 4) {
			langid = tbuf[2] | (tbuf[3] << 8);
			upsdebugx(1, "First supported language ID: 0x%x (please report to the NUT maintainer!)", langid);
		}
	}
#endif
	blazer_initups();
}
Exemplo n.º 25
0
void blazer_initinfo(void)
{
    const char	*protocol = getval("protocol");
    int	retry;

    for (proto = 0; command[proto].status; proto++) {

        int	ret;

        if (protocol && strcasecmp(protocol, command[proto].name)) {
            upsdebugx(2, "Skipping %s protocol...", command[proto].name);
            continue;
        }

        upsdebugx(2, "Trying %s protocol...", command[proto].name);

        for (retry = 1; retry <= MAXTRIES; retry++) {

            ret = blazer_status(command[proto].status);
            if (ret < 0) {
                upsdebugx(2, "Status read %d failed", retry);
                continue;
            }

            upsdebugx(2, "Status read in %d tries", retry);
            break;
        }

        if (!ret) {
            upslogx(LOG_INFO, "Supported UPS detected with %s protocol", command[proto].name);
            break;
        }
    }

    if (!command[proto].status) {
        fatalx(EXIT_FAILURE, "No supported UPS detected");
    }

    if (command[proto].rating && !testvar("norating")) {
        int	ret;

        for (retry = 1; retry <= MAXTRIES; retry++) {

            ret = blazer_rating(command[proto].rating);
            if (ret < 0) {
                upsdebugx(1, "Rating read %d failed", retry);
                continue;
            }

            upsdebugx(2, "Ratings read in %d tries", retry);
            break;
        }

        if (ret) {
            upslogx(LOG_DEBUG, "Rating information unavailable");
        }
    }

    if (command[proto].vendor && !testvar("novendor")) {
        int	ret;

        for (retry = 1; retry <= MAXTRIES; retry++) {

            ret = blazer_vendor(command[proto].vendor);
            if (ret < 0) {
                upsdebugx(1, "Vendor information read %d failed", retry);
                continue;
            }

            upslogx(LOG_INFO, "Vendor information read in %d tries", retry);
            break;
        }

        if (ret) {
            upslogx(LOG_DEBUG, "Vendor information unavailable");
        }
    }

    blazer_initbattery();

    dstate_setinfo("ups.delay.start", "%d", 60 * ondelay);
    dstate_setinfo("ups.delay.shutdown", "%d", offdelay);

    dstate_addcmd("beeper.toggle");
    dstate_addcmd("load.off");
    dstate_addcmd("load.on");
    dstate_addcmd("shutdown.return");
    dstate_addcmd("shutdown.stayoff");
    dstate_addcmd("shutdown.stop");
    dstate_addcmd("test.battery.start");
    dstate_addcmd("test.battery.start.deep");
    dstate_addcmd("test.battery.start.quick");
    dstate_addcmd("test.battery.stop");

    upsh.instcmd = blazer_instcmd;
}
Exemplo n.º 26
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;
}
Exemplo n.º 27
0
Arquivo: clone.c Projeto: AlexLov/nut
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;
}
Exemplo n.º 28
0
static int upsc_simple(const simple_t *sp, const char *var, const char *val)
{
	int stat;
	float fval;

	while (sp->code) {
		if (strcmp(sp->code, var) == 0) {
			switch (sp->type) {
			case t_setval:
				stat = sscanf(val, "%f", &fval);
				if (stat != 1)
					upslogx(LOG_ERR, "Bad float: %s %s", var, val);
				if (sp->desc)
					dstate_setinfo(sp->desc, "%.2f", fval);
				*sp->aux = fval;
				break;
			case t_setrecip:
				stat = sscanf(val, "%f", &fval);
				if (stat != 1)
					upslogx(LOG_ERR, "Bad float: %s %s", var, val);
				if (sp->desc)
					dstate_setinfo(sp->desc, "%s", val);
				*sp->aux = 1/fval;
				break;
			case t_setpct:
				stat = sscanf(val, "%f", &fval);
				if (stat != 1)
					upslogx(LOG_ERR, "Bad float: %s %s", var, val);
				*sp->aux = fval*100;
				if (sp->desc)
					dstate_setinfo(sp->desc, "%s", val);
				break;
			case t_setrecpct:
				stat = sscanf(val, "%f", &fval);
				if (stat != 1)
					upslogx(LOG_ERR, "Bad float: %s %s", var, val);
				*sp->aux = 1/fval*100;
				if (sp->desc)
					dstate_setinfo(sp->desc, "%s", val);
				break;
			case t_final:
				buffer_empty = 1;
			case t_value:
				if (!sp->desc) {
					break;
				}
				if (sscanf(val, "%f", &fval) == 1) {
					if (sp->aux != NULL) {
						fval *= *(sp->aux);
					}
					dstate_setinfo(sp->desc, "%.2f", fval);
				}
				else {
					upslogx(LOG_ERR, "Bad float in %s: %s", var, val);
					dstate_setinfo(sp->desc, "%s", val);
				}
				break;
			case t_finstr:
				buffer_empty = 1;
			case t_string:
				if (!sp->desc) {
					break;
				}
				dstate_setinfo(sp->desc, "%s", val);
				break;
			case t_status:
				if (strcmp(val, "00") == 0)
					;
				else if (strcmp(val, "11") == 0)
					status |= sp->status;
				else
					upslogx(LOG_ERR, "Unknown status value: '%s' '%s'", var, val);
				break;
			case t_alarm:
				if (strcmp(val, "00") == 0)
					;
				else if (strcmp(val, "11") == 0)
					status |= sp->status;
				else
					upslogx(LOG_ERR, "Unknown alarm value: '%s' '%s'", var, val);
				break;
			case t_ignore:
				upsdebugx(3, "Ignored value: %s %s", var, val);
				break;
			case t_list:
				if (!upsc_simple(sp->stats, val, "11"))
					upslogx(LOG_ERR, "Unknown value: %s %s",
						var, val);
				break;
			default:
				upslogx(LOG_ERR, "Unknown type for %s", var);
				break;
			}
			return 1;
		}
		sp++;
	}
	return 0;
}
Exemplo n.º 29
0
int riello_instcmd(const char *cmdname, const char *extra)
{
	uint8_t length;
	uint16_t delay;
	const char	*delay_char;

	if (!riello_test_bit(&DevData.StatusCode[0], 1)) {
		if (!strcasecmp(cmdname, "load.off")) {
			delay = 0;
			riello_init_serial();

			if (typeRielloProtocol == DEV_RIELLOGPSER)
				length = riello_prepare_cs(bufOut, gpser_error_control, delay);
			else
				length = riello_prepare_shutsentr(bufOut, delay);

			if (ser_send_buf(upsfd, bufOut, length) == 0) {
				upsdebugx (3, "Command load.off communication error");
				return STAT_INSTCMD_FAILED;
			}

			riello_serialcomm(&bufIn[0], typeRielloProtocol);
			if (!wait_packet && foundbadcrc) {
				upsdebugx (3, "Command load.off Ko: bad CRC or Checksum");
				return STAT_INSTCMD_FAILED;
			}

			if (!wait_packet && foundnak) {
				upsdebugx (3, "Command load.off Ko: command not supported");
				return STAT_INSTCMD_FAILED;
			}

			upsdebugx (3, "Command load.off Ok");
			return STAT_INSTCMD_HANDLED;
		}

		if (!strcasecmp(cmdname, "load.off.delay")) {
			delay_char = dstate_getinfo("ups.delay.shutdown");
			delay = atoi(delay_char);
			riello_init_serial();

			if (typeRielloProtocol == DEV_RIELLOGPSER)
				length = riello_prepare_cs(bufOut, gpser_error_control, delay);
			else
				length = riello_prepare_shutsentr(bufOut, delay);

			if (ser_send_buf(upsfd, bufOut, length) == 0) {
				upsdebugx (3, "Command load.off delay communication error");
				return STAT_INSTCMD_FAILED;
			}

			riello_serialcomm(&bufIn[0], typeRielloProtocol);
			if (!wait_packet && foundbadcrc) {
				upsdebugx (3, "Command load.off.delay Ko: bad CRC or Checksum");
				return STAT_INSTCMD_FAILED;
			}

			if (!wait_packet && foundnak) {
				upsdebugx (3, "Command load.off.delay Ko: command not supported");
				return STAT_INSTCMD_FAILED;
			}

			upsdebugx (3, "Command load.off delay Ok");
			return STAT_INSTCMD_HANDLED;
		}

		if (!strcasecmp(cmdname, "load.on")) {
			delay = 0;
			riello_init_serial();

			if (typeRielloProtocol == DEV_RIELLOGPSER)
				length = riello_prepare_cr(bufOut, gpser_error_control, delay);
			else {
				length = riello_prepare_setrebsentr(bufOut, delay);
				
				if (ser_send_buf(upsfd, bufOut, length) == 0) {
					upsdebugx (3, "Command load.on communication error");
					return STAT_INSTCMD_FAILED;
				}

				riello_serialcomm(&bufIn[0], typeRielloProtocol);
				if (!wait_packet && foundbadcrc) {
					upsdebugx (3, "Command load.on Ko: bad CRC or Checksum");
					return STAT_INSTCMD_FAILED;
				}

				if (!wait_packet && foundnak) {
					upsdebugx (3, "Command load.on Ko: command not supported");
					return STAT_INSTCMD_FAILED;
				}

				length = riello_prepare_rebsentr(bufOut, delay);
			}

			if (ser_send_buf(upsfd, bufOut, length) == 0) {
				upsdebugx (3, "Command load.on communication error");
				return STAT_INSTCMD_FAILED;
			}

			riello_serialcomm(&bufIn[0], typeRielloProtocol);
			if (!wait_packet && foundbadcrc) {
				upsdebugx (3, "Command load.on Ko: bad CRC or Checksum");
				return STAT_INSTCMD_FAILED;
			}

			if (!wait_packet && foundnak) {
				upsdebugx (3, "Command load.on Ko: command not supported");
				return STAT_INSTCMD_FAILED;
			}

			upsdebugx (3, "Command load.on Ok");
			return STAT_INSTCMD_HANDLED;
		}

		if (!strcasecmp(cmdname, "load.on.delay")) {
			delay_char = dstate_getinfo("ups.delay.reboot");
			delay = atoi(delay_char);
			riello_init_serial();

			if (typeRielloProtocol == DEV_RIELLOGPSER)
				length = riello_prepare_cr(bufOut, gpser_error_control, delay);
			else {
				length = riello_prepare_setrebsentr(bufOut, delay);

				if (ser_send_buf(upsfd, bufOut, length) == 0) {
					upsdebugx (3, "Command load.on delay communication error");
					return STAT_INSTCMD_FAILED;
				}

				riello_serialcomm(&bufIn[0], typeRielloProtocol);
				if (!wait_packet && foundbadcrc) {
					upsdebugx (3, "Command load.on delay Ko: bad CRC or Checksum");
					return STAT_INSTCMD_FAILED;
				}

				if (!wait_packet && foundnak) {
					upsdebugx (3, "Command load.on delay Ko: command not supported");
					return STAT_INSTCMD_FAILED;
				}

				length = riello_prepare_rebsentr(bufOut, delay);
			}

			if (ser_send_buf(upsfd, bufOut, length) == 0) {
				upsdebugx (3, "Command load.on delay communication error");
				return STAT_INSTCMD_FAILED;
			}

			riello_serialcomm(&bufIn[0], typeRielloProtocol);
			if (!wait_packet && foundbadcrc) {
				upsdebugx (3, "Command load.on.delay Ko: bad CRC or Checksum");
				return STAT_INSTCMD_FAILED;
			}

			if (!wait_packet && foundnak) {
				upsdebugx (3, "Command load.on.delay Ko: command not supported");
				return STAT_INSTCMD_FAILED;
			}

			upsdebugx (3, "Command load.on delay Ok");
			return STAT_INSTCMD_HANDLED;
		}
	}
	else {
		if (!strcasecmp(cmdname, "shutdown.return")) {
			delay_char = dstate_getinfo("ups.delay.shutdown");
			delay = atoi(delay_char);
			riello_init_serial();

			if (typeRielloProtocol == DEV_RIELLOGPSER)
				length = riello_prepare_cs(bufOut, gpser_error_control, delay);
			else
				length = riello_prepare_shutsentr(bufOut, delay);

			if (ser_send_buf(upsfd, bufOut, length) == 0) {
				upsdebugx (3, "Command shutdown.return communication error");
				return STAT_INSTCMD_FAILED;
			}

			riello_serialcomm(&bufIn[0], typeRielloProtocol);
			if (!wait_packet && foundbadcrc) {
				upsdebugx (3, "Command shutdown.return Ko: bad CRC or Checksum");
				return STAT_INSTCMD_FAILED;
			}

			if (!wait_packet && foundnak) {
				upsdebugx (3, "Command shutdown.return Ko: command not supported");
				return STAT_INSTCMD_FAILED;
			}

			upsdebugx (3, "Command shutdown.return Ok");
			return STAT_INSTCMD_HANDLED;
		}
	}

	if (!strcasecmp(cmdname, "shutdown.stop")) {
		riello_init_serial();

		if (typeRielloProtocol == DEV_RIELLOGPSER) 
			length = riello_prepare_cd(bufOut, gpser_error_control);
		else
			length = riello_prepare_cancelsentr(bufOut);

		if (ser_send_buf(upsfd, bufOut, length) == 0) {
			upsdebugx (3, "Command shutdown.stop communication error");
			return STAT_INSTCMD_FAILED;
		}

		riello_serialcomm(&bufIn[0], typeRielloProtocol);
		if (!wait_packet && foundbadcrc) {
			upsdebugx (3, "Command shutdown.stop Ko: bad CRC or Checksum");
			return STAT_INSTCMD_FAILED;
		}

		if (!wait_packet && foundnak) {
			upsdebugx (3, "Command shutdown.stop Ko: command not supported");
			return STAT_INSTCMD_FAILED;
		}

		upsdebugx (3, "Command shutdown.stop Ok");
		return STAT_INSTCMD_HANDLED;
	}

	if (!strcasecmp(cmdname, "test.panel.start")) {
		riello_init_serial();
		length = riello_prepare_tp(bufOut, gpser_error_control);

		if (ser_send_buf(upsfd, bufOut, length) == 0) {
			upsdebugx (3, "Command test.panel.start communication error");
			return STAT_INSTCMD_FAILED;
		}

		riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER);
		if (!wait_packet && foundbadcrc) {
			upsdebugx (3, "Command test.panel.start Ko: bad CRC or Checksum");
			return STAT_INSTCMD_FAILED;
		}

		if (!wait_packet && foundnak) {
			upsdebugx (3, "Command test.panel.start Ko: command not supported");
			return STAT_INSTCMD_FAILED;
		}

		upsdebugx (3, "Command test.panel.start Ok");
		return STAT_INSTCMD_HANDLED;
	}

	if (!strcasecmp(cmdname, "test.battery.start")) {
		riello_init_serial();
		if (typeRielloProtocol == DEV_RIELLOGPSER)
			length = riello_prepare_tb(bufOut, gpser_error_control);
		else
			length = riello_prepare_tbsentr(bufOut);

		if (ser_send_buf(upsfd, bufOut, length) == 0) {
			upsdebugx (3, "Command test.battery.start communication error");
			return STAT_INSTCMD_FAILED;
		}

		riello_serialcomm(&bufIn[0], typeRielloProtocol);
		if (!wait_packet && foundbadcrc) {
			upsdebugx (3, "Command battery.start Ko: bad CRC or Checksum");
			return STAT_INSTCMD_FAILED;
		}

		if (!wait_packet && foundnak) {
			upsdebugx (3, "Command battery.start Ko: command not supported");
			return STAT_INSTCMD_FAILED;
		}

		upsdebugx (3, "Command test.battery.start Ok");
		return STAT_INSTCMD_HANDLED;
	}

	upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
	return STAT_INSTCMD_UNKNOWN;
}
Exemplo n.º 30
0
void upsdrv_initups(void)
{
	int	ret;
	char	*val;
	FILE	*fp;

#if HAVE_NE_SET_CONNECT_TIMEOUT && HAVE_NE_SOCK_CONNECT_TIMEOUT
	/* we don't need to use alarm() */
#else
	struct sigaction	sa;

	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;

	sa.sa_handler = netxml_alarm_handler;
	sigaction(SIGALRM, &sa, NULL);
#endif
	/* allow override of default network timeout value */
	val = getval("timeout");
	if (val) {
		timeout = atoi(val);

		if (timeout < 1) {
			fatalx(EXIT_FAILURE, "timeout must be greater than 0");
		}
	}

	val = getval("shutdown_duration");
	if (val) {
		shutdown_duration = atoi(val);

		if (shutdown_duration < 0) {
			fatalx(EXIT_FAILURE, "shutdown duration must be greater than or equal to 0");
		}
	}

	val = getval("shutdown_timer");
	if (val) {
		shutdown_timer = atoi(val);

		if (shutdown_timer < 0) {
			fatalx(EXIT_FAILURE, "shutdown timer must be greater than or equal to 0");
		}
	}

	if (nut_debug_level > 5) {
		ne_debug_init(stderr, NE_DBG_HTTP | NE_DBG_HTTPBODY);
	}

	if (ne_sock_init()) {
		fatalx(EXIT_FAILURE, "%s: failed to initialize socket libraries", progname);
	}

	if (ne_uri_parse(device_path, &uri) || uri.host == NULL) {
		fatalx(EXIT_FAILURE, "%s: invalid hostname '%s'", progname, device_path);
	}
/*
	if (uri.scheme == NULL) {
		uri.scheme = strdup("http");
	}
 
	if (uri.host == NULL) {
		uri.host = strdup(device_path);
	}
 */
	if (uri.port == 0) {
		uri.port = ne_uri_defaultport(uri.scheme);
	}

	upsdebugx(1, "using %s://%s port %d", uri.scheme, uri.host, uri.port);

	session = ne_session_create(uri.scheme, uri.host, uri.port);
	
	/* timeout if we can't (re)connect to the UPS */
#ifdef HAVE_NE_SET_CONNECT_TIMEOUT
	ne_set_connect_timeout(session, timeout);
#endif

	/* just wait for a couple of seconds */
	ne_set_read_timeout(session, timeout);

	ne_set_useragent(session, subdriver->version);

	if (strcasecmp(uri.scheme, "https") == 0) {
		ne_ssl_trust_default_ca(session);
	}

	ne_set_server_auth(session, netxml_authenticate, NULL);

	/* if debug level is set, direct output to stderr */
	if (!nut_debug_level) {
		fp = fopen("/dev/null", "w");
	} else {
		fp = stderr;
	}

	if (!fp) {
		fatal_with_errno(EXIT_FAILURE, "Connectivity test failed");
	}

	/* see if we have a connection */
	ret = ne_get(session, subdriver->initups, fileno(fp));

	if (!nut_debug_level) {
		fclose(fp);
	} else {
		fprintf(fp, "\n");
	}

	if (ret != NE_OK) {
		fatalx(EXIT_FAILURE, "Connectivity test: %s", ne_get_error(session));
	}

	upslogx(LOG_INFO, "Connectivity test: %s", ne_get_error(session));
}