---------- Forwarded Message ---------- Subject: [PATCH] New to nut project Date: Friday, 6. November 2009 From: Patrick Levesque <patri...@verint.com> To: Thomas Jarosch <thomas.jaro...@intra2net.com>
As requested, here is my patch file including all my modification to the 2.4.1 tarball from the web site. On Friday 06 November 2009 05:41:29 you wrote: > Hello Patrick, > > On Wednesday, 4. November 2009 14:12:09 Levesque, Patrick wrote: > > I have tried to support a TrippLite Internet350SER UPS using a serial > > cable (The only connection on this model) using the 2.4 code branch. It > > uses the Protocol 1004 from the tripplite specification that can be use > > either used on serial or USB device. Since my device was only serial, I > > worked only on the serial integration. Since I found nothing in > > tripplite.c, tripplite-hid.c, tripplitesu.c to support my model, I have > > done trippliteser.c in order to support my unit. Not all the > > functionality are there but the core functionality is there. Since it > > is licence as GPLv2, I just want to push back my modifs to the community > > but really don't know the procedure. > > Do you know how diff/patch works? Just send your changes > as unified diff (diff -u) to the devel list. Might be a good > idea to prefix your mail subject with "[PATCH]". > > If possible, try to prevent winmail.dat attachments on the mailing list, > so people with a normal email client can open the attachment. > > Cheers, > Thomas
diff -crBN a/data/driver.list b/data/driver.list *** a/data/driver.list 2009-02-17 04:20:45.000000000 -0500 --- b/data/driver.list 2009-09-01 13:53:08.000000000 -0400 *************** *** 627,632 **** --- 627,633 ---- "Tripp-Lite" "AVR750U" "USB" "usbhid-ups" "Tripp-Lite" "SmartOnline SU1500RTXL2ua" "USB" "usbhid-ups" "Tripp-Lite" "smart2200RMXL2U" "USB, newer models" "usbhid-ups" + "Tripp-Lite" "INTERNET350SER" "" "trippliteser" "Trust" "UPS 1000 Management PW-4105" "" "megatec" "Trust" "UPS 1200VA Management PW-4120M" "" "megatec" diff -crBN a/drivers/genericups.c b/drivers/genericups.c *** a/drivers/genericups.c 2009-02-17 04:20:48.000000000 -0500 --- b/drivers/genericups.c 2009-10-16 15:06:42.000000000 -0400 *************** *** 66,71 **** --- 66,74 ---- if (strstr(value, "RNG")) { fatalx(EXIT_FAILURE, "Can't override output with RNG (not an output)"); } + if (strstr(value, "DSR")) { + fatalx(EXIT_FAILURE, "Can't override output with DSR (not an output)"); + } } static void parse_input_signals(const char *value, int *line, int *val) *************** *** 98,103 **** --- 101,113 ---- *val |= TIOCM_RNG; } } + if (strstr(value, "DSR")) { + *line |= TIOCM_DSR; + + if (!strstr(value, "-DSR")) { + *val |= TIOCM_DSR; + } + } if (strstr(value, "DTR")) { fatalx(EXIT_FAILURE, "Can't override input with DTR (not an input)"); diff -crBN a/drivers/Makefile.in b/drivers/Makefile.in *** a/drivers/Makefile.in 2009-02-17 04:24:10.000000000 -0500 --- b/drivers/Makefile.in 2009-10-16 15:07:30.000000000 -0400 *************** *** 110,116 **** newmge-shut$(EXEEXT) oneac$(EXEEXT) optiups$(EXEEXT) \ powercom$(EXEEXT) rhino$(EXEEXT) safenet$(EXEEXT) \ skel$(EXEEXT) solis$(EXEEXT) tripplite$(EXEEXT) \ ! tripplitesu$(EXEEXT) upscode2$(EXEEXT) victronups$(EXEEXT) \ powerpanel$(EXEEXT) blazer_ser$(EXEEXT) am__EXEEXT_2 = snmp-ups$(EXEEXT) am__EXEEXT_3 = usbhid-ups$(EXEEXT) bcmxcp_usb$(EXEEXT) \ --- 110,116 ---- newmge-shut$(EXEEXT) oneac$(EXEEXT) optiups$(EXEEXT) \ powercom$(EXEEXT) rhino$(EXEEXT) safenet$(EXEEXT) \ skel$(EXEEXT) solis$(EXEEXT) tripplite$(EXEEXT) \ ! tripplitesu$(EXEEXT) trippliteser$(EXEEXT) upscode2$(EXEEXT) victronups$(EXEEXT) \ powerpanel$(EXEEXT) blazer_ser$(EXEEXT) am__EXEEXT_2 = snmp-ups$(EXEEXT) am__EXEEXT_3 = usbhid-ups$(EXEEXT) bcmxcp_usb$(EXEEXT) \ *************** *** 334,339 **** --- 334,343 ---- tripplitesu_OBJECTS = $(am_tripplitesu_OBJECTS) tripplitesu_LDADD = $(LDADD) tripplitesu_DEPENDENCIES = $(am__DEPENDENCIES_2) + am_trippliteser_OBJECTS = trippliteser.$(OBJEXT) + trippliteser_OBJECTS = $(am_trippliteser_OBJECTS) + trippliteser_LDADD = $(LDADD) + trippliteser_DEPENDENCIES = $(am__DEPENDENCIES_2) am_upscode2_OBJECTS = upscode2.$(OBJEXT) upscode2_OBJECTS = $(am_upscode2_OBJECTS) upscode2_DEPENDENCIES = $(am__DEPENDENCIES_3) *************** *** 381,387 **** $(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \ $(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \ $(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \ ! $(tripplitesu_SOURCES) $(upscode2_SOURCES) \ $(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \ $(victronups_SOURCES) DIST_SOURCES = $(libdummy_a_SOURCES) $(libnuthalmain_a_SOURCES) \ --- 385,393 ---- $(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \ $(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \ $(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \ ! $(tripplitesu_SOURCES) \ ! $(trippliteser_SOURCES) \ ! $(upscode2_SOURCES) \ $(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \ $(victronups_SOURCES) DIST_SOURCES = $(libdummy_a_SOURCES) $(libnuthalmain_a_SOURCES) \ *************** *** 403,409 **** $(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \ $(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \ $(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \ ! $(tripplitesu_SOURCES) $(upscode2_SOURCES) \ $(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \ $(victronups_SOURCES) HEADERS = $(dist_noinst_HEADERS) --- 409,417 ---- $(powerpanel_SOURCES) $(rhino_SOURCES) $(richcomm_usb_SOURCES) \ $(safenet_SOURCES) $(skel_SOURCES) $(snmp_ups_SOURCES) \ $(solis_SOURCES) $(tripplite_SOURCES) $(tripplite_usb_SOURCES) \ ! $(tripplitesu_SOURCES) \ ! $(trippliteser_SOURCES) \ ! $(upscode2_SOURCES) \ $(upsdrvctl_SOURCES) $(usbhid_ups_SOURCES) \ $(victronups_SOURCES) HEADERS = $(dist_noinst_HEADERS) *************** *** 580,586 **** bestuferrups bestups cyberpower dummy-ups etapro everups \ gamatronic genericups isbmex liebert masterguard megatec metasys \ mge-shut mge-utalk microdowell newmge-shut oneac optiups powercom rhino \ ! safenet skel solis tripplite tripplitesu upscode2 victronups powerpanel \ blazer_ser SNMP_DRIVERLIST = snmp-ups --- 588,594 ---- bestuferrups bestups cyberpower dummy-ups etapro everups \ gamatronic genericups isbmex liebert masterguard megatec metasys \ mge-shut mge-utalk microdowell newmge-shut oneac optiups powercom rhino \ ! safenet skel solis tripplite tripplitesu trippliteser upscode2 victronups powerpanel \ blazer_ser SNMP_DRIVERLIST = snmp-ups *************** *** 638,643 **** --- 646,652 ---- tripplite_SOURCES = tripplite.c tripplite_LDADD = $(LDADD) -lm tripplitesu_SOURCES = tripplitesu.c + trippliteser_SOURCES = trippliteser.c upscode2_SOURCES = upscode2.c upscode2_LDADD = $(LDADD) -lm victronups_SOURCES = victronups.c *************** *** 964,969 **** --- 973,981 ---- tripplitesu$(EXEEXT): $(tripplitesu_OBJECTS) $(tripplitesu_DEPENDENCIES) @rm -f tripplitesu$(EXEEXT) $(LINK) $(tripplitesu_OBJECTS) $(tripplitesu_LDADD) $(LIBS) + trippliteser$(EXEEXT): $(trippliteser_OBJECTS) $(trippliteser_DEPENDENCIES) + @rm -f trippliteser$(EXEEXT) + $(LINK) $(trippliteser_OBJECTS) $(trippliteser_LDADD) $(LIBS) upscode2$(EXEEXT): $(upscode2_OBJECTS) $(upscode2_DEPENDENCIES) @rm -f upscode2$(EXEEXT) $(LINK) $(upscode2_OBJECTS) $(upscode2_LDADD) $(LIBS) *************** *** 1055,1060 **** --- 1067,1073 ---- @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/tripplite...@am__quote@ @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/tripplite_usb...@am__quote@ @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/tripplitesu...@am__quote@ + @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/trippliteser...@am__quote@ @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/upscode2...@am__quote@ @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/upsdrvctl...@am__quote@ @AMDEP_TRUE@@am__include@ @am__qu...@./$(DEPDIR)/usb-common...@am__quote@ diff -crBN a/drivers/trippliteser.c b/drivers/trippliteser.c *** a/drivers/trippliteser.c 1969-12-31 19:00:00.000000000 -0500 --- b/drivers/trippliteser.c 2009-11-02 16:42:52.000000000 -0500 *************** *** 0 **** --- 1,641 ---- + /* trippliteser.c - model specific routines for + Tripp Lite INTERNET (SER) models running protocol 1004 + + Copyright (C) 2009 Patrick Levesque <patri...@verint.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + /* Notes: + + The following parameters (ups.conf) are supported: + lowbatt + + The following variables are supported (RW = read/write): + ambient.humidity (1) + ambient.temperature (1) + battery.charge + battery.current (1) + battery.temperature + battery.voltage + battery.voltage.nominal + driver.version.internal + input.frequency + input.sensitivity (RW) (1) + input.transfer.high (RW) + input.transfer.low (RW) + input.voltage + input.voltage.nominal + output.current (1) + output.frequency + output.voltage + output.voltage.nominal + ups.firmware + ups.id (RW) (1) + ups.load + ups.mfr + ups.model + ups.status + ups.test.result + ups.contacts (1) + + The following instant commands are supported: + load.off + load.on + shutdown.reboot + shutdown.reboot.graceful + shutdown.return + shutdown.stop + test.battery.start + test.battery.stop + + The following ups.status values are supported: + BOOST (1) + BYPASS + LB + OB + OFF + OL + OVER (2) + RB (2) + TRIM (1) + + (1) these items have not been tested because they are not supported + by my SU1000RT2U. + (2) these items have not been tested because I haven't tested them. + */ + + + #include "main.h" + #include "serial.h" + + #define DRIVER_NAME "Tripp Lite INTERNET SER driver" + #define DRIVER_VERSION "0.01" + + #define ENDCHAR '\r' + #define IGNCHAR 'X' + + /* driver description structure */ + upsdrv_info_t upsdrv_info = { + DRIVER_NAME, + DRIVER_VERSION, + "Patrick Levesque <patri...@verint.com>", + DRV_EXPERIMENTAL, + { NULL } + }; + + #define MAX_RESPONSE_LENGTH 8 + #define MAX_IDNETIFICATION_LENGTH 40 + + #define DEFAULT_OFFDELAY 64 /*!< seconds (max 2^16) */ + + static int battery_voltage_nominal = 0, + input_voltage_nominal = 0, + switchable_load_banks = 0; + + /*! Time in seconds to delay before shutting down. */ + static unsigned int offdelay = DEFAULT_OFFDELAY; + #if 0 + static const char *test_result_names[] = { + "No test performed", + "Passed", + "In progress", + "General test failed", + "Battery failed", + "Deep battery test failed", + "Aborted" + }; + #endif + + # if 0 + static struct { + int code; + const char *name; + } sensitivity[] = { + {0, "Normal"}, + {1, "Reduced"}, + {2, "Low"} + }; + #endif + + static struct { + int outlet_banks; + unsigned long commands_available; + } ups; + + + struct proto { + char command; + size_t req_size; + int csum; + size_t ans_size; + }; + + static struct proto proto_table[] = + { + /* Control value */ + {'C', 4, 1, 2}, + {'G', 4, 1, 2}, + {'N', 6, 1, 2}, + {'I', 5, 1, 2}, + {'W', 5, 1, 3}, + /* Command value */ + {'\0', 4, 1, 8}, + {'F', 4, 1, 8}, + {'L', 4, 1, 6}, + {'P', 4, 1, 8}, + {'S', 4, 1, 5}, + {'V', 4, 1, 8}, + /* Unit identification */ + {'1', 3, 0, 8}, + {'2', 3, 0, 8}, + {'3', 3, 0, 8}, + {'4', 3, 0, 8}, + {'5', 3, 0, 8}, + {'6', 3, 0, 8}, + }; + + + #define DEFAULT_RESPONSE_LENGTH 8 + + /* index of the proto table */ + + enum trippliteser_command + { + /* Controls */ + CANCEL_SHUTDOWN=0, + SHUTDOWN, + SET_PREDELAY, + SET_STATUS_FLAGS, + WATCHDOG, + /* Commands */ + PROTOCOL, + uC_FIRMWARE, + STATUS_FLAGS, + POWER_RATING, + STATUS, + MODEL_VERSION, + /* Unit Identification */ + IDENTIFICATION_1, + IDENTIFICATION_2, + IDENTIFICATION_3, + IDENTIFICATION_4, + IDENTIFICATION_5, + IDENTIFICATION_6 + }; + + /*...@brief Convert N characters from hex to decimal + * + * @param start Beginning of string to convert + * @param len Maximum number of characters to consider (max 32) + * + * @a len characters of @a start are copied to a temporary buffer, then passed + * to strtol() to be converted to decimal. + * + * @return See strtol(3) + */ + static int hex2d(const unsigned char *start, unsigned int len) + { + unsigned char buf[32]; + buf[31] = '\0'; + + strncpy((char *)buf, (char *)start, (len < (sizeof buf) ? len : (sizeof buf - 1))); + if(len < sizeof(buf)) buf[len] = '\0'; + return strtol((char *)buf, NULL, 16); + } + + void decode_v(const unsigned char *value) + { + unsigned char ivn, lb; + int bv = hex2d(value+2, 2); + + ivn = value[1]; + lb = value[4]; + + switch(ivn) { + case '0': input_voltage_nominal = 100; + break; + case '1': input_voltage_nominal = 120; + break; + case '2': input_voltage_nominal = 208; + break; + case '3': input_voltage_nominal = 230; + break; + case '4': input_voltage_nominal = 240; + break; + default: + upslogx(2, "Unknown input voltage range: 0x%02x", (unsigned int)ivn); + break; + } + + battery_voltage_nominal = bv * 6; + + if( (lb >= '0') && (lb <= '9') ) { + switchable_load_banks = lb - '0'; + } else { + if( lb != 'X' ) { + upslogx(2, "Unknown number of switchable load banks: 0x%02x", + (unsigned int)lb); + } + } + } + + static int do_command(enum trippliteser_command command, unsigned char *msg, size_t msg_len, unsigned char *reply, size_t reply_len) + { + unsigned char buffer[MAX_RESPONSE_LENGTH]; + unsigned int i = 0, csum = 0; + int ret; + + ser_flush_io(upsfd); + + if (reply_len < MAX_RESPONSE_LENGTH) { + upsdebugx(3, "do_command: reply do not have minimum size of 8 bytes!"); + return -1; + } + + if (reply) { + memset(reply, 0, reply_len); + } + + upsdebugx(3, "Performing command %c [0x%02x] with request size %d and answer size %d\n", proto_table[command].command, proto_table[command].command, proto_table[command].req_size, proto_table[command].ans_size); + memset(buffer, 0, sizeof(buffer)); + + /* Now fill the buffer */ + buffer[0] = ':'; + + buffer[1] = proto_table[command].command; + + if (proto_table[command].csum) { + csum = proto_table[command].command; + + /* skip : and remove ENDCHAR from the csum computation */ + for(i=0; i<msg_len; i++) { + buffer[i+2] = msg[i]; + csum += msg[i]; + } + buffer[i+2] = 255-csum; + i++; + } + buffer[i+2] = ENDCHAR; + + ret = ser_send_buf_pace(upsfd, 0, buffer, proto_table[command].req_size); + if (ret <= 0) { + upsdebug_with_errno(3, "do_command: send [%s]", buffer); + return -1; + } + + upsdebugx(3, "do_command: %d bytes sent [0x%02x%02x%02x%02x] 0x%02x -> OK", ret, buffer[0], buffer[1], buffer[2], buffer[3], '\r'); + + ret = ser_get_buf_len(upsfd, reply, proto_table[command].ans_size, 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; + } + + upsdebugx(3, "do_command: %d byted read 0x%02x%02x%02x%02x%02x%02x%02x%02x", ret, reply[0], reply[1],reply[2],reply[3],reply[4],reply[5],reply[6],reply[7]); + + if (reply[0] != proto_table[command].command) { + upsdebugx(3, "do_command: response not expected!"); + return -1; + } + return ret; + } + + static int do_productName(char *productName, size_t productName_len) + { + unsigned char response[MAX_RESPONSE_LENGTH]; + unsigned int len = 0; + int i = 0, j = 0; + + if (productName == NULL) { + upsdebugx(3, "%s: input buffer is null!", __FUNCTION__); + return -1; + } + memset(productName, 0, productName_len); + len = 0; + + if (do_command(IDENTIFICATION_2, NULL, 0, response, sizeof(response)) <= 0) { + upsdebugx(3, "IDENTIFICATION_2 failed\n"); + return -1; + } + for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) { + productName[i] = response[j]; + len++; + } + if (do_command(IDENTIFICATION_3, NULL, 0, response, sizeof(response)) <= 0) { + upsdebugx(3, "IDENTIFICATION_3 failed\n"); + return -1; + } + for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) { + productName[i] = response[j]; + len++; + } + if (do_command(IDENTIFICATION_4, NULL, 0, response, sizeof(response)) <= 0) { + upsdebugx(3, "IDENTIFICATION_4 failed\n"); + return -1; + } + for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) { + productName[i] = response[j]; + len++; + } + if (do_command(IDENTIFICATION_5, NULL, 0, response, sizeof(response)) <= 0) { + upsdebugx(3, "IDENTIFICATION_5 failed\n"); + return -1; + } + for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) { + productName[i] = response[j]; + len++; + } + if (do_command(IDENTIFICATION_6, NULL, 0, response, sizeof(response)) <= 0) { + upsdebugx(3, "IDENTIFICATION_6 failed\n"); + return -1; + } + for (j=1;response[j] != '\r' && j < MAX_RESPONSE_LENGTH; i++, j++) { + productName[i] = response[j]; + len++; + } + productName[i] = '\0'; + len++; + + /* Trim trailing spaces */ + for(i--;productName[i] == ' ';i--) { + productName[i] = '\0'; + len--; + } + + upsdebugx(3, "Product Name so far %s of size %d\n", productName, len); + + return len; + } + + #if 0 + static int get_identification(void) { + unsigned char response[MAX_RESPONSE_LENGTH]; + + if (do_command(IDENTIFICATION_2, NULL, 0, response, sizeof(response)) >= 0) { + dstate_setinfo("ups.id", "%s", response); + return 1; + } + + return 0; + } + #endif + #if 0 + static void set_identification(const char *val) { + char response[MAX_RESPONSE_LENGTH]; + + if (do_command(IDENTIFICATION, "", response) < 0) + return; + if (strcmp(val, response)) { + strncpy(response, val, MAX_RESPONSE_LENGTH); + response[MAX_RESPONSE_LENGTH - 1] = '\0'; + do_command(IDENTIFICATION, response, NULL); + } + } + #endif + + #if 0 + static int get_transfer_voltage_low(void) { + char response[MAX_RESPONSE_LENGTH]; + char *ptr; + + if (do_command(TRANSFER_VOLTAGE, "", response) > 0) { + ptr = field(response, 0); + if (ptr) + dstate_setinfo("input.transfer.low", "%d", atoi(ptr)); + return 1; + } + + return 0; + } + #endif + + static int instcmd(const char *cmdname, const char *extra) + { + #if 0 + int i; + + char parm[20]; + + if (!strcasecmp(cmdname, "load.off")) { + for (i = 0; i < ups.outlet_banks; i++) { + snprintf(parm, sizeof(parm), "%d;1", i + 1); + do_command(SET, RELAY_OFF, parm, NULL); + } + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "load.on")) { + for (i = 0; i < ups.outlet_banks; i++) { + snprintf(parm, sizeof(parm), "%d;1", i + 1); + do_command(SET, RELAY_ON, parm, NULL); + } + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "shutdown.reboot")) { + auto_reboot(1); + do_command(SET, SHUTDOWN_RESTART, "1", NULL); + do_command(SET, SHUTDOWN_ACTION, "10", NULL); + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "shutdown.reboot.graceful")) { + auto_reboot(1); + do_command(SET, SHUTDOWN_RESTART, "1", NULL); + do_command(SET, SHUTDOWN_ACTION, "60", NULL); + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "shutdown.return")) { + auto_reboot(1); + do_command(SET, SHUTDOWN_RESTART, "1", NULL); + do_command(SET, SHUTDOWN_ACTION, "10", NULL); + return STAT_INSTCMD_HANDLED; + } + #if 0 /* doesn't seem to work */ + if (!strcasecmp(cmdname, "shutdown.stayoff")) { + auto_reboot(0); + do_command(SET, SHUTDOWN_ACTION, "10", NULL); + return STAT_INSTCMD_HANDLED; + } + #endif + if (!strcasecmp(cmdname, "shutdown.stop")) { + do_command(SET, SHUTDOWN_ACTION, "0", NULL); + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "test.battery.start")) { + do_command(SET, TEST, "3", NULL); + return STAT_INSTCMD_HANDLED; + } + if (!strcasecmp(cmdname, "test.battery.stop")) { + do_command(SET, TEST, "0", NULL); + return STAT_INSTCMD_HANDLED; + } + upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname); + return STAT_INSTCMD_UNKNOWN; + #endif + return STAT_INSTCMD_HANDLED; + } + + + static int setvar(const char *varname, const char *val) + { + #if 0 + if (!strcasecmp(varname, "ups.id")) { + set_identification(val); + get_identification(); + return STAT_SET_HANDLED; + } + upslogx(LOG_NOTICE, "setvar: unknown var [%s]", varname); + #endif + return STAT_SET_UNKNOWN; + } + + + static int init_comm(void) + { + unsigned char response[MAX_RESPONSE_LENGTH]; + + ups.commands_available = 0; + + if (do_command(PROTOCOL, NULL, 0, response, sizeof(response)) <= 0) { + return 0; + } + + /* Make sure the control protocol is 0x1004 */ + if (response[1] != 0x10 || response[2] != 0x04) { + return 0; + } + + return 1; + } + + void upsdrv_initinfo(void) + { + unsigned char response[MAX_RESPONSE_LENGTH]; + char productName[MAX_IDNETIFICATION_LENGTH]; + // unsigned int pre_delay, alarm; + + if (!init_comm()) + fatalx(EXIT_FAILURE, "Unable to detect Tripp Lite SmartOnline UPS on port %s\n", + device_path); + dstate_setinfo("ups.mfr", "%s", "Tripp Lite"); + if (do_productName(productName, sizeof(productName))) + dstate_setinfo("ups.model", "%s", productName); + if (do_command(PROTOCOL, NULL, 0, response, sizeof(response))) + dstate_setinfo("ups.firmware.aux", "%02x%02x", response[1], response[2]); + if (do_command(uC_FIRMWARE, NULL, 0, response, sizeof(response))) + dstate_setinfo("ups.firmware", "69-%c%c%c%c Rev %c%c", response[1], response[2], response[3], response[4], response[5], response[6]); + if (do_command(MODEL_VERSION, NULL, 0, response, sizeof(response))) { + decode_v(response); + dstate_setinfo("input.voltage.nominal", "%d", input_voltage_nominal); + dstate_setinfo("battery.voltage.nominal", "%d", battery_voltage_nominal); + dstate_setinfo("ups.debug.load_banks", "%d", switchable_load_banks); + } + + dstate_setinfo("ups.delay.shutdown", "%d", offdelay); + dstate_setflags("ups.delay.shutdown", ST_FLAG_RW | ST_FLAG_STRING); + dstate_setaux("ups.delay.shutdown", 3); + + /* add all the variables that change regularly */ + upsdrv_updateinfo(); + + upsh.instcmd = instcmd; + upsh.setvar = setvar; + } + + void upsdrv_updateinfo(void) + { + + unsigned char response[MAX_RESPONSE_LENGTH]; + + status_init(); + if (do_command(STATUS, NULL, 0, response, sizeof(response)) <= 0) { + dstate_datastale(); + return; + } + + if (response[1] == '0') { + status_set("LB"); + } + + switch (response[2]) { + case '0': + status_set("OL"); + break; + case '1': + status_set("OB"); + break; + case '2': + status_set("CHRG"); + break; + case '3': + status_set("IDLE"); + break; + default: + break; + } + + dstate_setinfo("battery.charge", "%d", response[3]); + + /* if we are here, status is valid */ + status_commit(); + dstate_dataok(); + + } + + void upsdrv_shutdown(void) + { + unsigned char response[MAX_RESPONSE_LENGTH]; + unsigned char preDelay[2] = {0x00, 0x00}; + upsdebugx(3, "upsdrv_shutdown is CALLED\n"); + /* Make sure the system run on battery because the system will not be brought back in case the system is on line */ + if (do_command(STATUS, NULL, 0, response, sizeof(response)) <= 0) + fatalx(EXIT_FAILURE, "Unable to get the line status!"); + + if (response[2] != '0' ) { + upsdebugx(3, "Performing the shutdown\n"); + if (do_command(SET_PREDELAY, preDelay, sizeof(preDelay), response, sizeof(response)) <= 0) + upslogx(LOG_NOTICE, "SET_PREDELAY failed"); + if (do_command(SHUTDOWN, NULL, 0, response, sizeof(response)) <= 0) + upslogx(LOG_NOTICE, "SHUTDOWN failed"); + } + else + { + upsdebugx(3, "Shutdown bypass because we are on line\n"); + } + } + + void upsdrv_help(void) + { + } + + /* list flags and values that you want to receive via -x or ups.conf */ + void upsdrv_makevartable(void) + { + addvar(VAR_VALUE, "lowbatt", "Set low battery level, in percent"); + } + + void upsdrv_initups(void) + { + upsfd = ser_open(device_path); + ser_set_speed(upsfd, device_path, B2400); + } + + void upsdrv_cleanup(void) + { + ser_close(upsfd, device_path); + }
_______________________________________________ Nut-upsdev mailing list Nut-upsdev@lists.alioth.debian.org http://lists.alioth.debian.org/mailman/listinfo/nut-upsdev