From 571db05b8603c3b8b178216cc3f8602cf36f0737 Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Mon, 25 Nov 2024 20:16:12 -0300 Subject: [PATCH 01/60] First commit of NHS drivers/nhs-nut.c --- drivers/nhs-nut.c | 2033 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2033 insertions(+) create mode 100644 drivers/nhs-nut.c diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c new file mode 100644 index 0000000000..16836fcf8a --- /dev/null +++ b/drivers/nhs-nut.c @@ -0,0 +1,2033 @@ +/* + * nhs-nut.c - NUT support for NHS Nobreaks, senoidal line + * + * + * Copyright (C) 2024 - Lucas Willian Bocchi + * Initial Release + * + * 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 + */ + +#include "config.h" +#include "main.h" +#include "common.h" +#include "nut_stdint.h" +#include "serial.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Instructions to compile + 1) apt update + 2) apt install build-essential autoconf libtool pkg-config libusb-1.0-0-dev libssl-dev git + 3) Download NUT source code OR use apt-source to download source from your distribution (in case of debian/ubuntu). How to do it? apt-get source nut, apt-get build-dep nut, make your alterations in code (follow the steps above), dpkg-buildpackage -us -uc, dpkg -i * ./autogen.sh + 4) ./autogen.sh + 5) ./ci_build.sh + 6) ./configure --with-dev + 7) cd drivers + 8) make (to generate nut_version.h) + + If you can use debian / ubuntu packages to do that: + 1) apt-get source nut + 2) apt-get build-dep nut + 3) extract flags to correct compilation with COMPILEFLAGS=$(make -f debian/rules -pn | grep '^DEB_CONFIGURE_EXTRA_FLAGS' | sed 's/^DEB_CONFIGURE_EXTRA_FLAGS := //') on root source directory + 4) Follow steps 4 to 8 earlier (ignore errors if you can only compile to use the driver with actual nut compiled debian instalation, it's only to generate nut_version.h) + 5) back to root nut source directory, then dpkg-buildpackage -us -uc + 6) dpkg -i + + * gcc -g -O0 -o nhs-nut nhs-nut.c main.c dstate.c upsdrvquery.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm + * copy nhs-nut to nut driver's directory and test + To debug: + * clang --analyze nhs-nut.c + * cppcheck nhs-nut.c + * upsdrvctl -D start + * nhs-nut -a -D + * upsd -D +*/ + +#define DEFAULTBAUD B2400 +#define DEFAULTPORT "/dev/ttyACM0" +#define DEFAULTPF 0.9 +#define DEFAULLTPERC 2 +#define DATAPACKETSIZE 100 +#define DRIVER_NAME "NHS Nobreak Drivers" +#define DRIVER_VERSION "0.1" +#define MANUFACTURER "NHS Sistemas Eletronicos LTDA" + +/* driver description structure */ +upsdrv_info_t upsdrv_info = +{ + DRIVER_NAME, + DRIVER_VERSION, + "Lucas Willian Bocchi ", + DRV_BETA, + { NULL } +}; + + +// Struct to represent serial conventions in termios.h +typedef struct { + speed_t rate; // Constant in termios.h + int speed; // Numeric speed, used on NUT + const char * description; // Description +} baud_rate_t; + +baud_rate_t baud_rates[] = { + { B50, 50, "50 bps" }, + { B75, 75, "75 bps" }, + { B110, 110, "110 bps" }, + { B134, 134, "134.5 bps" }, + { B150, 150, "150 bps" }, + { B200, 200, "200 bps" }, + { B300, 300, "300 bps" }, + { B600, 600, "600 bps" }, + { B1200, 1200, "1200 bps" }, + { B2400, 2400, "2400 bps" }, + { B4800, 4800, "4800 bps" }, + { B9600, 9600, "9600 bps" }, + { B19200, 19200, "19200 bps" }, + { B38400, 38400, "38400 bps" }, + { B57600, 57600, "57600 bps" }, + { B115200, 115200, "115200 bps" }, + { B230400, 230400, "230400 bps" }, + { B460800, 460800, "460800 bps" }, + { B921600, 921600, "921600 bps" }, + { B1500000, 1500000, "1.5 Mbps" }, + { B2000000, 2000000, "2 Mbps" }, + { B2500000, 2500000, "2.5 Mbps" }, + { B3000000, 3000000, "3 Mbps" }, + { B3500000, 3500000, "3.5 Mbps" }, + { B4000000, 4000000, "4 Mbps" }, +}; +#define NUM_BAUD_RATES (sizeof(baud_rates) / sizeof(baud_rates[0])) + +// Struct that contain nobreak info +typedef struct { + unsigned int header; + unsigned int size; + char type; + unsigned int model; + unsigned int hardwareversion; + unsigned int softwareversion; + unsigned int configuration; + int configuration_array[5]; + bool c_oem_mode; + bool c_buzzer_disable; + bool c_potmin_disable; + bool c_rearm_enable; + bool c_bootloader_enable; + unsigned int numbatteries; + unsigned int undervoltagein120V; + unsigned int overvoltagein120V; + unsigned int undervoltagein220V; + unsigned int overvoltagein220V; + unsigned int tensionout120V; + unsigned int tensionout220V; + unsigned int statusval; + int status[6]; + bool s_220V_in; + bool s_220V_out; + bool s_sealed_battery; + bool s_show_out_tension; + bool s_show_temperature; + bool s_show_charger_current; + unsigned int chargercurrent; + unsigned int checksum; + bool checksum_ok; + char serial[17]; + unsigned int year; + unsigned int month; + unsigned int wday; + unsigned int hour; + unsigned int minute; + unsigned int second; + unsigned int alarmyear; + unsigned int alarmmonth; + unsigned int alarmwday; + unsigned int alarmday; + unsigned int alarmhour; + unsigned int alarmminute; + unsigned int alarmsecond; + unsigned int end_marker; +} pkt_hwinfo; + +// Struct that contain the +typedef struct { + unsigned int header; + unsigned int length; + char packet_type; + unsigned int vacinrms_high; + unsigned int vacinrms_low; + float vacinrms; + unsigned int vdcmed_high; + unsigned int vdcmed_low; + float vdcmed; + float vdcmed_real; + unsigned int potrms; + unsigned int vacinrmsmin_high; + unsigned int vacinrmsmin_low; + float vacinrmsmin; + unsigned int vacinrmsmax_high; + unsigned int vacinrmsmax_low; + float vacinrmsmax; + unsigned int vacoutrms_high; + unsigned int vacoutrms_low; + float vacoutrms; + unsigned int tempmed_high; + unsigned int tempmed_low; + float tempmed; + float tempmed_real; + unsigned int icarregrms; + unsigned int icarregrms_real; + float battery_tension; + unsigned int perc_output; + unsigned int statusval; + int status[8]; + unsigned int nominaltension; + float timeremain; + bool s_battery_mode; + bool s_battery_low; + bool s_network_failure; + bool s_fast_network_failure; + bool s_220_in; + bool s_220_out; + bool s_bypass_on; + bool s_charger_on; + unsigned int checksum; + bool checksum_ok; + unsigned int end_marker; +} pkt_data; + + typedef struct { + unsigned int upscode; + char upsdesc[100]; + unsigned int VA; +} upsinfo; + +const unsigned int string_initialization_long[9] = {0xFF, 0x09, 0x53, 0x83, 0x00, 0x00, 0x00, 0xDF, 0xFE}; +const unsigned int string_initialization_short[9] = {0xFF, 0x09, 0x53, 0x03, 0x00, 0x00, 0x00, 0x5F, 0xFE}; + +static int serial_fd = -1; +static unsigned char chr; +static int datapacket_index = 0; +static bool datapacketstart = false; +static time_t lastdp = 0; +static unsigned int checktime = 1000000; // 1 second +static unsigned int max_checktime = 3000000; // max wait time -- 3 seconds +static unsigned int send_extended = 0; +static int bwritten = 0; +static unsigned char datapacket[DATAPACKETSIZE]; +static char porta[1024] = DEFAULTPORT; +static int baudrate = DEFAULTBAUD; +static float minpower = 0; +static float maxpower = 0; +static unsigned int minpowerperc = 0; +static unsigned int maxpowerperc = 0; + +static pkt_hwinfo lastpkthwinfo = { + .header = 0xFF, + .size = 0, + .type = 'S', + .model = 0, + .hardwareversion = 0, + .softwareversion = 0, + .configuration = 0, + .configuration_array = {0, 0, 0, 0, 0}, + .c_oem_mode = false, + .c_buzzer_disable = false, + .c_potmin_disable = false, + .c_rearm_enable = false, + .c_bootloader_enable = false, + .numbatteries = 0, + .undervoltagein120V = 0, + .overvoltagein120V = 0, + .undervoltagein220V = 0, + .overvoltagein220V = 0, + .tensionout120V = 0, + .tensionout220V = 0, + .statusval = 0, + .status = {0, 0, 0, 0, 0, 0}, + .s_220V_in = false, + .s_220V_out = false, + .s_sealed_battery = false, + .s_show_out_tension = false, + .s_show_temperature = false, + .s_show_charger_current = false, + .chargercurrent = 0, + .checksum = 0, + .checksum_ok = false, + .serial = "----------------", + .year = 0, + .month = 0, + .wday = 0, + .hour = 0, + .minute = 0, + .second = 0, + .alarmyear = 0, + .alarmmonth = 0, + .alarmwday = 0, + .alarmday = 0, + .alarmhour = 0, + .alarmminute = 0, + .alarmsecond = 0, + .end_marker = 0xFE + }; + +static pkt_data lastpktdata = { + .header = 0xFF, + .length = 0x21, + .packet_type = 'D', + .vacinrms_high = 0, + .vacinrms_low = 0, + .vacinrms = 0, + .vdcmed_high = 0, + .vdcmed_low = 0, + .vdcmed = 0, + .vdcmed_real = 0, + .potrms = 0, + .vacinrmsmin_high = 0, + .vacinrmsmin_low = 0, + .vacinrmsmin = 0, + .vacinrmsmax_high = 0, + .vacinrmsmax_low = 0, + .vacinrmsmax = 0, + .vacoutrms_high = 0, + .vacoutrms_low = 0, + .vacoutrms = 0, + .tempmed_high = 0, + .tempmed_low = 0, + .tempmed = 0, + .tempmed_real = 0, + .icarregrms = 0, + .icarregrms_real = 0, + .battery_tension = 0, + .perc_output = 0, + .statusval = 0, + .status = {0, 0, 0, 0, 0, 0, 0, 0}, + .nominaltension = 0, + .timeremain = 0.0f, + .s_battery_mode = false, + .s_battery_low = false, + .s_network_failure = false, + .s_fast_network_failure = false, + .s_220_in = false, + .s_220_out = false, + .s_bypass_on = false, + .s_charger_on = false, + .checksum = 0, + .checksum_ok = false, + .end_marker = 0xFE + }; + +int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorder) { + unsigned char *byte_ptr = (unsigned char *)ptr; + int retval = -2; + + if (bit_position >= size * 8) { + return -3; // Invalid Position + } + + size_t byte_index = bit_position / 8; + size_t bit_index = bit_position % 8; + + retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 1 : 0; + if (invertorder == 0) + retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 1 : 0; + else + retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 0 ? 1 : 1; + return retval; +} + + +void print_pkt_hwinfo(pkt_hwinfo data) { + upsdebugx(1,"Header: %u\n", data.header); + upsdebugx(1,"Size: %u\n", data.size); + upsdebugx(1,"Type: %c\n", data.type); + upsdebugx(1,"Model: %u\n", data.model); + upsdebugx(1,"Hardware Version: %u\n", data.hardwareversion); + upsdebugx(1,"Software Version: %u\n", data.softwareversion); + upsdebugx(1,"Configuration: %u\n", data.configuration); + upsdebugx(1,"Configuration Array: "); + for (int i = 0; i < 5; i++) { + int retorno = get_bit_in_position(&data.configuration,sizeof(data.configuration),i,0); + upsdebugx(1,"Binary value is %d",retorno); + upsdebugx(1,"%u ", data.configuration_array[i]); + } + upsdebugx(1,"\n"); + upsdebugx(1,"OEM Mode: %s\n", data.c_oem_mode ? "true" : "false"); + upsdebugx(1,"Buzzer Disable: %s\n", data.c_buzzer_disable ? "true" : "false"); + upsdebugx(1,"Potmin Disable: %s\n", data.c_potmin_disable ? "true" : "false"); + upsdebugx(1,"Rearm Enable: %s\n", data.c_rearm_enable ? "true" : "false"); + upsdebugx(1,"Bootloader Enable: %s\n", data.c_bootloader_enable ? "true" : "false"); + upsdebugx(1,"Number of Batteries: %u\n", data.numbatteries); + upsdebugx(1,"Undervoltage In 120V: %u\n", data.undervoltagein120V); + upsdebugx(1,"Overvoltage In 120V: %u\n", data.overvoltagein120V); + upsdebugx(1,"Undervoltage In 220V: %u\n", data.undervoltagein220V); + upsdebugx(1,"Overvoltage In 220V: %u\n", data.overvoltagein220V); + upsdebugx(1,"Tension Out 120V: %u\n", data.tensionout120V); + upsdebugx(1,"Tension Out 220V: %u\n", data.tensionout220V); + upsdebugx(1,"Status Value: %u\n", data.statusval); + + upsdebugx(1,"Status: "); + for (int i = 0; i < 6; i++) { + upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); + upsdebugx(1,"status %d --> %u ", i, data.status[i]); + } + upsdebugx(1,"\n"); + upsdebugx(1,"220V In: %s\n", data.s_220V_in ? "true" : "false"); + upsdebugx(1,"220V Out: %s\n", data.s_220V_out ? "true" : "false"); + upsdebugx(1,"Sealed Battery: %s\n", data.s_sealed_battery ? "true" : "false"); + upsdebugx(1,"Show Out Tension: %s\n", data.s_show_out_tension ? "true" : "false"); + upsdebugx(1,"Show Temperature: %s\n", data.s_show_temperature ? "true" : "false"); + upsdebugx(1,"Show Charger Current: %s\n", data.s_show_charger_current ? "true" : "false"); + upsdebugx(1,"Charger Current: %u\n", data.chargercurrent); + upsdebugx(1,"Checksum: %u\n", data.checksum); + upsdebugx(1,"Checksum OK: %s\n", data.checksum_ok ? "true" : "false"); + upsdebugx(1,"Serial: %s\n", data.serial); + upsdebugx(1,"Year: %u\n", data.year); + upsdebugx(1,"Month: %u\n", data.month); + upsdebugx(1,"Weekday: %u\n", data.wday); + upsdebugx(1,"Hour: %u\n", data.hour); + upsdebugx(1,"Minute: %u\n", data.minute); + upsdebugx(1,"Second: %u\n", data.second); + upsdebugx(1,"Alarm Year: %u\n", data.alarmyear); + upsdebugx(1,"Alarm Month: %u\n", data.alarmmonth); + upsdebugx(1,"Alarm Weekday: %u\n", data.alarmwday); + upsdebugx(1,"Alarm Day: %u\n", data.alarmday); + upsdebugx(1,"Alarm Hour: %u\n", data.alarmhour); + upsdebugx(1,"Alarm Minute: %u\n", data.alarmminute); + upsdebugx(1,"Alarm Second: %u\n", data.alarmsecond); + upsdebugx(1,"End Marker: %u\n", data.end_marker); +} + +void print_pkt_data(pkt_data data) { + upsdebugx(1,"Header: %u\n", data.header); + upsdebugx(1,"Length: %u\n", data.length); + upsdebugx(1,"Packet Type: %c\n", data.packet_type); + upsdebugx(1,"Vacin RMS High: %u\n", data.vacinrms_high); + upsdebugx(1,"Vacin RMS Low: %u\n", data.vacinrms_low); + upsdebugx(1,"Vacin RMS: %f\n", data.vacinrms); + upsdebugx(1,"VDC Med High: %u\n", data.vdcmed_high); + upsdebugx(1,"VDC Med Low: %u\n", data.vdcmed_low); + upsdebugx(1,"VDC Med: %f\n", data.vdcmed); + upsdebugx(1,"VDC Med Real: %f\n", data.vdcmed_real); + upsdebugx(1,"Pot RMS: %u\n", data.potrms); + upsdebugx(1,"Vacin RMS Min High: %u\n", data.vacinrmsmin_high); + upsdebugx(1,"Vacin RMS Min Low: %u\n", data.vacinrmsmin_low); + upsdebugx(1,"Vacin RMS Min: %f\n", data.vacinrmsmin); + upsdebugx(1,"Vacin RMS Max High: %u\n", data.vacinrmsmax_high); + upsdebugx(1,"Vacin RMS Max Low: %u\n", data.vacinrmsmax_low); + upsdebugx(1,"Vacin RMS Max: %f\n", data.vacinrmsmax); + upsdebugx(1,"Vac Out RMS High: %u\n", data.vacoutrms_high); + upsdebugx(1,"Vac Out RMS Low: %u\n", data.vacoutrms_low); + upsdebugx(1,"Vac Out RMS: %f\n", data.vacoutrms); + upsdebugx(1,"Temp Med High: %u\n", data.tempmed_high); + upsdebugx(1,"Temp Med Low: %u\n", data.tempmed_low); + upsdebugx(1,"Temp Med: %f\n", data.tempmed); + upsdebugx(1,"Temp Med Real: %f\n", data.tempmed_real); + upsdebugx(1,"Icar Reg RMS: %u\n", data.icarregrms); + upsdebugx(1,"Icar Reg RMS Real: %u\n", data.icarregrms_real); + upsdebugx(1,"Battery Tension: %f\n", data.battery_tension); + upsdebugx(1,"Perc Output: %u\n", data.perc_output); + upsdebugx(1,"Status Value: %u\n", data.statusval); + upsdebugx(1,"Status: "); + for (int i = 0; i < 8; i++) { + upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); + upsdebugx(1,"status %d --> %u ", i, data.status[i]); + } + upsdebugx(1,"\n"); + upsdebugx(1,"Nominal Tension: %u\n", data.nominaltension); + upsdebugx(1,"Time Remain: %f\n", data.timeremain); + upsdebugx(1,"Battery Mode: %s\n", data.s_battery_mode ? "true" : "false"); + upsdebugx(1,"Battery Low: %s\n", data.s_battery_low ? "true" : "false"); + upsdebugx(1,"Network Failure: %s\n", data.s_network_failure ? "true" : "false"); + upsdebugx(1,"Fast Network Failure: %s\n", data.s_fast_network_failure ? "true" : "false"); + upsdebugx(1,"220 In: %s\n", data.s_220_in ? "true" : "false"); + upsdebugx(1,"220 Out: %s\n", data.s_220_out ? "true" : "false"); + upsdebugx(1,"Bypass On: %s\n", data.s_bypass_on ? "true" : "false"); + upsdebugx(1,"Charger On: %s\n", data.s_charger_on ? "true" : "false"); + upsdebugx(1,"Checksum: %u\n", data.checksum); + upsdebugx(1,"Checksum OK: %s\n", data.checksum_ok ? "true" : "false"); + upsdebugx(1,"End Marker: %u\n", data.end_marker); +} + +int openfd(const char * porta, int BAUDRATE) { + long unsigned int i = 0; + int done = 0; + struct termios tty; + struct serial_struct serial; + + + //int fd = ser_open(porta); + int fd = open(porta, O_RDWR | O_NOCTTY | O_SYNC); + if (fd < 0) { + upsdebugx(1, "Erro on open %s", porta); + return -1; + } + if (tcflush(fd, TCIOFLUSH) != 0) { + upsdebugx(1, "Error on flush data on %s", porta); + return -1; + } + + + if (tcgetattr(fd, &tty) != 0) { + upsdebugx(1, "Erro on set termios values to %s", porta); + close(fd); + return -1; + } + + serial.xmit_fifo_size = 1; + ioctl(fd, TIOCSSERIAL, &serial); + + + // select speed based on baud + while ((i < NUM_BAUD_RATES) && (done == 0)) { + if (baud_rates[i].speed == BAUDRATE) { + done = baud_rates[i].rate; + upsdebugx(1,"Baud selecionado: %d -- %s\r\n",baud_rates[i].speed,baud_rates[i].description); + } + i++; + } + // if done is 0, no one speed has selected, then use default + done = DEFAULTBAUD; + + tty.c_cflag &= ~PARENB; // Disable Parity + tty.c_cflag &= ~CSTOPB; // 1 stop bit + tty.c_cflag &= ~CSIZE; // Clear Bit Set + tty.c_cflag |= CS8; // 8 bits per byte + + // CTS / RTS + tty.c_cflag |= CRTSCTS; // Enable hardware flow control + + // Enable Read and disable modem control + //tty.c_cflag |= (CLOCAL | CREAD); + tty.c_cflag |= CREAD; + + + tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable Software Control + tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); + + tty.c_oflag &= ~OPOST; // Disable output post-processing + tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); // Modo raw + // To enable block read: VTIME = 1 and VMIN = 0 + // To disable block read: VTIME = 0 and VMIN = 1 + tty.c_cc[VTIME] = 1; + tty.c_cc[VMIN] = 0; + + + cfsetispeed(&tty, done); + cfsetospeed(&tty, done); + + if (tcsetattr(fd, TCSANOW, &tty) != 0) { + upsdebugx(1, "Error on tcsetattr on port %s", porta); + close(fd); + return -1; + } + return fd; +} + +unsigned char calcular_checksum(unsigned char *pacote, int inicio, int fim) { + int soma = 0; + for (int i = inicio; i <= fim; i++) { + soma += pacote[i]; + } + return soma & 0xFF; +} + +void pdatapacket(unsigned char * datapacket,int size) { + int i = 0; + if (datapacket != NULL) { + upsdebugx(1,"\r\nReceived Datapacket: \r\n"); + for (i = 0; i < size; i++) { + upsdebugx(1,"\tPosition %d -- 0x%02X -- Decimal %d -- Char %c\r\n", i, datapacket[i], datapacket[i], datapacket[i]); + } + } +} + +float createfloat(int integer, int decimal) { + char flt[1024]; + sprintf(flt,"%d.%d",integer,decimal); + return atof(flt); +} + +pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { + int i = 0; + unsigned char checksum = 0x00; + pkt_data pktdata = { + 0xFF, // header + 0x21, // length + 'D', // packet_type + 0, // vacinrms_high + 0, // vacinrms_low + 0, // vacinrms + 0, // vdcmed_high + 0, // vdcmed_low + 0, // vdcmed + 0, // vdcmed_real + 0, // potrms + 0, // vacinrmsmin_high + 0, // vacinrmsmin_low + 0, // vacinrmsmin + 0, // vacinrmsmax_high + 0, // vacinrmsmax_low + 0, // vacinrmsmax + 0, // vacoutrms_high + 0, // vacoutrms_low + 0, // vacoutrms + 0, // tempmed_high + 0, // tempmed_low + 0, // tempmed + 0, // tempmed_real + 0, // icarregrms + 0, // icarregrms_real + 0, // battery_tension + 0, // perc_output + 0, // statusval + {0, 0, 0, 0, 0, 0, 0, 0}, // status + 0, // nominaltension + 0.0f, // timeremain + false, // s_battery_mode + false, // s_battery_low + false, // s_network_failure + false, // s_fast_network_failure + false, // s_220_in + false, // s_220_out + false, // s_bypass_on + false, // s_charger_on + 0, // checksum + false, // checksum_ok + 0xFE // end_marker + }; + + pktdata.length = (int)datapacket[1]; + pktdata.packet_type = datapacket[2]; + pktdata.vacinrms_high = (int)datapacket[3]; + pktdata.vacinrms_low = (int)datapacket[4]; + pktdata.vacinrms = createfloat(pktdata.vacinrms_high,pktdata.vacinrms_low); + pktdata.vdcmed_high = (int)datapacket[5]; + pktdata.vdcmed_low = (int)datapacket[6]; + pktdata.vdcmed = createfloat(pktdata.vdcmed_high,pktdata.vdcmed_low); + pktdata.vdcmed_real = pktdata.vdcmed; + if (pktdata.vdcmed_low == 0) + pktdata.vdcmed_real = pktdata.vdcmed / 10; + pktdata.potrms = (int)datapacket[7]; + pktdata.vacinrmsmin_high = (int)datapacket[8]; + pktdata.vacinrmsmin_low = (int)datapacket[9]; + pktdata.vacinrmsmin = createfloat(pktdata.vacinrmsmin_high,pktdata.vacinrmsmin_low); + pktdata.vacinrmsmax_high = (int)datapacket[10]; + pktdata.vacinrmsmax_low = (int)datapacket[11]; + pktdata.vacinrmsmax = createfloat(pktdata.vacinrmsmax_high,pktdata.vacinrmsmax_low); + pktdata.vacoutrms_high = (int)datapacket[12]; + pktdata.vacoutrms_low = (int)datapacket[13]; + pktdata.vacoutrms = createfloat(pktdata.vacoutrms_high,pktdata.vacoutrms_low); + pktdata.tempmed_high = (int)datapacket[14]; + pktdata.tempmed_low = (int)datapacket[15]; + pktdata.tempmed = createfloat(pktdata.tempmed_high,pktdata.tempmed_low); + pktdata.tempmed_real = pktdata.tempmed; + pktdata.icarregrms = (int)datapacket[16]; + // 25 units = 750mA, then 1 unit = 30mA + pktdata.icarregrms_real = pktdata.icarregrms_real = pktdata.icarregrms * 30; + pktdata.statusval = datapacket[17]; + for (i = 0; i < 8; i++) + pktdata.status[i] = get_bit_in_position(&datapacket[17],sizeof(datapacket[17]),i,0); + // I don't know WHY, but bit order is INVERTED here. Discovered on clyra's github python implementation + // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more + pktdata.s_battery_mode = (bool)pktdata.status[7]; + pktdata.s_battery_low = (bool)pktdata.status[6]; + pktdata.s_network_failure = (bool)pktdata.status[5]; + pktdata.s_fast_network_failure = (bool)pktdata.status[4]; + pktdata.s_220_in = (bool)pktdata.status[3]; + pktdata.s_220_out = (bool)pktdata.status[2]; + pktdata.s_bypass_on = (bool)pktdata.status[1]; + pktdata.s_charger_on = (bool)pktdata.status[0]; + // Position 18 mean status, but I won't discover what's it + pktdata.checksum = datapacket[19]; + checksum = calcular_checksum(datapacket,1,18); + if (pktdata.checksum == checksum) + pktdata.checksum_ok = true; + // Then, the calculations to obtain some useful information + if (pkt_upsinfo.size > 0) { + pktdata.battery_tension = pkt_upsinfo.numbatteries * pktdata.vdcmed_real; + // Calculate battery percent utilization + // if one battery cell have 12v, then the maximum out tension is numbatteries * 12v + // This is the watermark to low battery + // TODO: test with external battery bank to see if calculation is valid. Can generate false positive + pktdata.nominaltension = 12 * pkt_upsinfo.numbatteries; + if (pktdata.nominaltension > 0) { + pktdata.perc_output = (pktdata.battery_tension * 100) / pktdata.nominaltension; + if (pktdata.perc_output > 100); + pktdata.perc_output = 100; + } // end if + } // end if + //pdatapacket(datapacket,size); + //print_pkt_data(pktdata); + return pktdata; +} + +pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { + int i = 0; + unsigned char checksum = 0x00; + pkt_hwinfo pkthwinfo = { + 0xFF, // header + 0, // size + 'S', // type + 0, // model + 0, // hardwareversion + 0, // softwareversion + 0, // configuration + {0, 0, 0, 0, 0}, // configuration_array + false, // c_oem_mode + false, // c_buzzer_disable + false, // c_potmin_disable + false, // c_rearm_enable + false, // c_bootloader_enable + 0, // numbatteries + 0, // undervoltagein120V + 0, // overvoltagein120V + 0, // undervoltagein220V + 0, // overvoltagein220V + 0, // tensionout120V + 0, // tensionout220V + 0, // statusval + {0, 0, 0, 0, 0, 0}, // status + false, // s_220V_in + false, // s_220V_out + false, // s_sealed_battery + false, // s_show_out_tension + false, // s_show_temperature + false, // s_show_charger_current + 0, // chargercurrent + 0, // checksum + false, // checksum_ok + "----------------", // serial + 0, // year + 0, // month + 0, // wday + 0, // hour + 0, // minute + 0, // second + 0, // alarmyear + 0, // alarmmonth + 0, // alarmday + 0, // alarmhour + 0, // alarmminute + 0, // alarmsecond + 0xFE // end_marker + }; + + pkthwinfo.size = (int)datapacket[1]; + pkthwinfo.type = datapacket[2]; + pkthwinfo.model = (int)datapacket[3]; + pkthwinfo.hardwareversion = (int)datapacket[4]; + pkthwinfo.softwareversion = (int)datapacket[5]; + pkthwinfo.configuration = datapacket[6]; + for (i = 0; i < 5; i++) + pkthwinfo.configuration_array[i] = get_bit_in_position(&datapacket[6],sizeof(datapacket[6]),i,0); + // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more + pkthwinfo.c_oem_mode = (bool)pkthwinfo.configuration_array[0]; + pkthwinfo.c_buzzer_disable = (bool)pkthwinfo.configuration_array[1]; + pkthwinfo.c_potmin_disable = (bool)pkthwinfo.configuration_array[2]; + pkthwinfo.c_rearm_enable = (bool)pkthwinfo.configuration_array[3]; + pkthwinfo.c_bootloader_enable = (bool)pkthwinfo.configuration_array[4]; + pkthwinfo.numbatteries = (int)datapacket[7]; + pkthwinfo.undervoltagein120V = (int)datapacket[8]; + pkthwinfo.overvoltagein120V = (int)datapacket[9]; + pkthwinfo.undervoltagein220V = (int)datapacket[10]; + pkthwinfo.overvoltagein220V = (int)datapacket[11]; + pkthwinfo.tensionout120V = (int)datapacket[12]; + pkthwinfo.tensionout220V = (int)datapacket[13]; + pkthwinfo.statusval = datapacket[14]; + for (i = 0; i < 8; i++) + pkthwinfo.status[i] = get_bit_in_position(&datapacket[14],sizeof(datapacket[14]),i,0); + // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more + pkthwinfo.s_220V_in = (bool)pkthwinfo.status[0]; + pkthwinfo.s_220V_out = (bool)pkthwinfo.status[1]; + pkthwinfo.s_sealed_battery = (bool)pkthwinfo.status[2]; + pkthwinfo.s_show_out_tension = (bool)pkthwinfo.status[3]; + pkthwinfo.s_show_temperature = (bool)pkthwinfo.status[4]; + pkthwinfo.s_show_charger_current = (bool)pkthwinfo.status[5]; + pkthwinfo.chargercurrent = (int)datapacket[15]; + if (pkthwinfo.size > 17) { + for (i = 0; i < 16; i++) + pkthwinfo.serial[i] = datapacket[16 + i]; + pkthwinfo.year = datapacket[32]; + pkthwinfo.month = datapacket[33]; + pkthwinfo.wday = datapacket[34]; + pkthwinfo.hour = datapacket[35]; + pkthwinfo.minute = datapacket[36]; + pkthwinfo.second = datapacket[37]; + pkthwinfo.alarmyear = datapacket[38]; + pkthwinfo.alarmmonth = datapacket[39]; + pkthwinfo.alarmday = datapacket[40]; + pkthwinfo.alarmhour = datapacket[41]; + pkthwinfo.alarmminute = datapacket[42]; + pkthwinfo.alarmsecond = datapacket[43]; + pkthwinfo.checksum = datapacket[48]; + checksum = calcular_checksum(datapacket,1,47); + } // end if + else { + pkthwinfo.checksum = datapacket[16]; + checksum = calcular_checksum(datapacket,1,15); + } + if (pkthwinfo.checksum == checksum) + pkthwinfo.checksum_ok = true; + + print_pkt_hwinfo(pkthwinfo); + //pdatapacket(datapacket,size); + return pkthwinfo; +} + +int write_serial(int serial_fd, const char * dados, int size) { + if (serial_fd > 0) { + ssize_t bytes_written = write(serial_fd, dados, size); + if (bytes_written < 0) + return -1; + if (tcdrain(serial_fd) != 0) + return -2; + return size; + } + else + return serial_fd; +} + +int write_serial_int(int serial_fd, const unsigned int * data, int size) { + uint8_t message[size]; + int i = 0; + if (serial_fd > 0) { + for (i = 0; i < size; i++) { + message[i] = (uint8_t)data[i]; + //upsdebugx(1,"%d %c %u %d %c %u\r\n",message[i],message[i],data[i],data[i]); + } + ssize_t bytes_written = write(serial_fd, message,size); + if (bytes_written < 0) + return -1; + if (tcdrain(serial_fd) != 0) + return -2; + return i; + } + else + return serial_fd; +} + +char * strtolow(char* s) { + for(char *p=s; *p; p++) *p=tolower(*p); + return s; +} + +upsinfo getupsinfo(unsigned int upscode) { + upsinfo data; + switch(upscode) { + case 1: + data.upscode = 1; + strcpy(data.upsdesc,"NHS COMPACT PLUS"); + data.VA = 1000; + break; + + case 2: + data.upscode = 2; + strcpy(data.upsdesc,"NHS COMPACT PLUS SENOIDAL"); + data.VA = 1000; + break; + + case 3: + data.upscode = 3; + strcpy(data.upsdesc,"NHS COMPACT PLUS RACK"); + data.VA = 1000; + break; + + case 4: + data.upscode = 4; + strcpy(data.upsdesc,"NHS PREMIUM PDV"); + data.VA = 1500; + break; + + case 5: + data.upscode = 5; + strcpy(data.upsdesc,"NHS PREMIUM PDV SENOIDAL"); + data.VA = 1500; + break; + + case 6: + data.upscode = 6; + strcpy(data.upsdesc,"NHS PREMIUM 1500VA"); + data.VA = 1500; + break; + + case 7: + data.upscode = 7; + strcpy(data.upsdesc,"NHS PREMIUM 2200VA"); + data.VA = 2200; + break; + + case 8: + data.upscode = 8; + strcpy(data.upsdesc,"NHS PREMIUM SENOIDAL"); + data.VA = 1500; + break; + + case 9: + data.upscode = 9; + strcpy(data.upsdesc,"NHS LASER 2600VA"); + data.VA = 2600; + break; + + case 10: + data.upscode = 10; + strcpy(data.upsdesc,"NHS LASER 3300VA"); + data.VA = 3300; + break; + + case 11: + data.upscode = 11; + strcpy(data.upsdesc,"NHS LASER 2600VA ISOLADOR"); + data.VA = 2600; + break; + + case 12: + data.upscode = 12; + strcpy(data.upsdesc,"NHS LASER SENOIDAL"); + data.VA = 2600; + break; + + case 13: + data.upscode = 13; + strcpy(data.upsdesc,"NHS LASER ON-LINE"); + data.VA = 2600; + break; + + case 15: + data.upscode = 15; + strcpy(data.upsdesc,"NHS COMPACT PLUS 2003"); + data.VA = 1000; + break; + + case 16: + data.upscode = 16; + strcpy(data.upsdesc,"COMPACT PLUS SENOIDAL 2003"); + data.VA = 1000; + break; + + case 17: + data.upscode = 17; + strcpy(data.upsdesc,"COMPACT PLUS RACK 2003"); + data.VA = 1000; + break; + + case 18: + data.upscode = 18; + strcpy(data.upsdesc,"PREMIUM PDV 2003"); + data.VA = 1500; + break; + + case 19: + data.upscode = 19; + strcpy(data.upsdesc,"PREMIUM PDV SENOIDAL 2003"); + data.VA = 1500; + break; + + case 20: + data.upscode = 20; + strcpy(data.upsdesc,"PREMIUM 1500VA 2003"); + data.VA = 1500; + break; + + case 21: + data.upscode = 21; + strcpy(data.upsdesc,"PREMIUM 2200VA 2003"); + data.VA = 2200; + break; + + case 22: + data.upscode = 22; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 2003"); + data.VA = 1500; + break; + + case 23: + data.upscode = 23; + strcpy(data.upsdesc,"LASER 2600VA 2003"); + data.VA = 2600; + break; + + case 24: + data.upscode = 24; + strcpy(data.upsdesc,"LASER 3300VA 2003"); + data.VA = 3300; + break; + + case 25: + data.upscode = 25; + strcpy(data.upsdesc,"LASER 2600VA ISOLADOR 2003"); + data.VA = 2600; + break; + + case 26: + data.upscode = 26; + strcpy(data.upsdesc,"LASER SENOIDAL 2003"); + data.VA = 2600; + break; + + case 27: + data.upscode = 27; + strcpy(data.upsdesc,"PDV ONLINE 2003"); + data.VA = 1500; + break; + + case 28: + data.upscode = 28; + strcpy(data.upsdesc,"LASER ONLINE 2003"); + data.VA = 3300; + break; + + case 29: + data.upscode = 29; + strcpy(data.upsdesc,"EXPERT ONLINE 2003"); + data.VA = 5000; + break; + + case 30: + data.upscode = 30; + strcpy(data.upsdesc,"MINI 2"); + data.VA = 500; + break; + + case 31: + data.upscode = 31; + strcpy(data.upsdesc,"COMPACT PLUS 2"); + data.VA = 1000; + break; + + case 32: + data.upscode = 32; + strcpy(data.upsdesc,"LASER ON-LINE"); + data.VA = 2600; + break; + + case 33: + data.upscode = 33; + strcpy(data.upsdesc,"PDV SENOIDAL 1500VA"); + data.VA = 1500; + break; + + case 34: + data.upscode = 34; + strcpy(data.upsdesc,"PDV SENOIDAL 1000VA"); + data.VA = 1000; + break; + + case 36: + data.upscode = 36; + strcpy(data.upsdesc,"LASER ONLINE 3750VA"); + data.VA = 3750; + break; + + case 37: + data.upscode = 37; + strcpy(data.upsdesc,"LASER ONLINE 5000VA"); + data.VA = 5000; + break; + + case 38: + data.upscode = 38; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 2000VA"); + data.VA = 2000; + break; + + case 39: + data.upscode = 39; + strcpy(data.upsdesc,"LASER SENOIDAL 3500VA"); + data.VA = 3500; + break; + + case 40: + data.upscode = 40; + strcpy(data.upsdesc,"PREMIUM PDV 1200VA"); + data.VA = 1200; + break; + + case 41: + data.upscode = 41; + strcpy(data.upsdesc,"PREMIUM 1500VA"); + data.VA = 1500; + break; + + case 42: + data.upscode = 42; + strcpy(data.upsdesc,"PREMIUM 2200VA"); + data.VA = 2200; + break; + + case 43: + data.upscode = 43; + strcpy(data.upsdesc,"LASER 2600VA"); + data.VA = 2600; + break; + + case 44: + data.upscode = 44; + strcpy(data.upsdesc,"LASER 3300VA"); + data.VA = 3300; + break; + + case 45: + data.upscode = 45; + strcpy(data.upsdesc,"COMPACT PLUS SENOIDAL 700VA"); + data.VA = 700; + break; + + case 46: + data.upscode = 46; + strcpy(data.upsdesc,"PREMIUM ONLINE 2000VA"); + data.VA = 2000; + break; + + case 47: + data.upscode = 47; + strcpy(data.upsdesc,"EXPERT ONLINE 10000VA"); + data.VA = 10000; + break; + + case 48: + data.upscode = 48; + strcpy(data.upsdesc,"LASER SENOIDAL 4200VA"); + data.VA = 4200; + break; + + case 49: + data.upscode = 49; + strcpy(data.upsdesc,"NHS COMPACT PLUS EXTENDIDO 1500VA"); + data.VA = 1500; + break; + + case 50: + data.upscode = 50; + strcpy(data.upsdesc,"LASER ONLINE 6000VA"); + data.VA = 6000; + break; + + case 51: + data.upscode = 51; + strcpy(data.upsdesc,"LASER EXT 3300VA"); + data.VA = 3300; + break; + + case 52: + data.upscode = 52; + strcpy(data.upsdesc,"NHS COMPACT PLUS 1200VA"); + data.VA = 1200; + break; + + case 53: + data.upscode = 53; + strcpy(data.upsdesc,"LASER SENOIDAL 3000VA GII"); + data.VA = 3000; + break; + + case 54: + data.upscode = 54; + strcpy(data.upsdesc,"LASER SENOIDAL 3500VA GII"); + data.VA = 3500; + break; + + case 55: + data.upscode = 55; + strcpy(data.upsdesc,"LASER SENOIDAL 4200VA GII"); + data.VA = 4200; + break; + + case 56: + data.upscode = 56; + strcpy(data.upsdesc,"LASER ONLINE 3000VA"); + data.VA = 3000; + break; + + case 57: + data.upscode = 57; + strcpy(data.upsdesc,"LASER ONLINE 3750VA"); + data.VA = 3750; + break; + + case 58: + data.upscode = 58; + strcpy(data.upsdesc,"LASER ONLINE 5000VA"); + data.VA = 5000; + break; + + case 59: + data.upscode = 59; + strcpy(data.upsdesc,"LASER ONLINE 6000VA"); + data.VA = 6000; + break; + + case 60: + data.upscode = 60; + strcpy(data.upsdesc,"PREMIUM ONLINE 2000VA"); + data.VA = 2000; + break; + + case 61: + data.upscode = 61; + strcpy(data.upsdesc,"PREMIUM ONLINE 1500VA"); + data.VA = 1500; + break; + + case 62: + data.upscode = 62; + strcpy(data.upsdesc,"PREMIUM ONLINE 1200VA"); + data.VA = 1200; + break; + + case 63: + data.upscode = 63; + strcpy(data.upsdesc,"COMPACT PLUS II MAX 1400VA"); + data.VA = 1400; + break; + + case 64: + data.upscode = 64; + strcpy(data.upsdesc,"PREMIUM PDV MAX 2200VA"); + data.VA = 2200; + break; + + case 65: + data.upscode = 65; + strcpy(data.upsdesc,"PREMIUM PDV 3000VA"); + data.VA = 3000; + break; + + case 66: + data.upscode = 66; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 2200VA GII"); + data.VA = 2200; + break; + + case 67: + data.upscode = 67; + strcpy(data.upsdesc,"LASER PRIME SENOIDAL 3200VA GII"); + data.VA = 3200; + break; + + case 68: + data.upscode = 68; + strcpy(data.upsdesc,"PREMIUM RACK ONLINE 3000VA"); + data.VA = 3000; + break; + + case 69: + data.upscode = 69; + strcpy(data.upsdesc,"PREMIUM ONLINE 3000VA"); + data.VA = 3000; + break; + + case 70: + data.upscode = 70; + strcpy(data.upsdesc,"LASER ONLINE 4000VA"); + data.VA = 4000; + break; + + case 71: + data.upscode = 71; + strcpy(data.upsdesc,"LASER ONLINE 7500VA"); + data.VA = 7500; + break; + + case 72: + data.upscode = 72; + strcpy(data.upsdesc,"LASER ONLINE BIFASICO 5000VA"); + data.VA = 5000; + break; + + case 73: + data.upscode = 73; + strcpy(data.upsdesc,"LASER ONLINE BIFASICO 6000VA"); + data.VA = 6000; + break; + + case 74: + data.upscode = 74; + strcpy(data.upsdesc,"LASER ONLINE BIFASICO 7500VA"); + data.VA = 7500; + break; + + case 75: + data.upscode = 75; + strcpy(data.upsdesc,"NHS MINI ST"); + data.VA = 500; + break; + + case 76: + data.upscode = 76; + strcpy(data.upsdesc,"NHS MINI 120"); + data.VA = 120; + break; + + case 77: + data.upscode = 77; + strcpy(data.upsdesc,"NHS MINI BIVOLT"); + data.VA = 500; + break; + + case 78: + data.upscode = 78; + strcpy(data.upsdesc,"PDV 600"); + data.VA = 600; + break; + + case 79: + data.upscode = 79; + strcpy(data.upsdesc,"NHS MINI MAX"); + data.VA = 500; + break; + + case 80: + data.upscode = 80; + strcpy(data.upsdesc,"NHS MINI EXT"); + data.VA = 500; + break; + + case 81: + data.upscode = 81; + strcpy(data.upsdesc,"NHS AUTONOMY PDV 4T"); + data.VA = 4000; + break; + + case 82: + data.upscode = 82; + strcpy(data.upsdesc,"NHS AUTONOMY PDV 8T"); + data.VA = 8000; + break; + + case 83: + data.upscode = 83; + strcpy(data.upsdesc,"NHS COMPACT PLUS RACK 1200VA"); + data.VA = 1200; + break; + + case 84: + data.upscode = 84; + strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 1500VA"); + data.VA = 1500; + break; + + case 85: + data.upscode = 85; + strcpy(data.upsdesc,"NHS PDV RACK 1500VA"); + data.VA = 1500; + break; + + case 86: + data.upscode = 86; + strcpy(data.upsdesc,"NHS PDV 1400VA S GII"); + data.VA = 1400; + break; + + case 87: + data.upscode = 87; + strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 1500VA"); + data.VA = 1500; + break; + + case 88: + data.upscode = 88; + strcpy(data.upsdesc,"LASER PRIME SENOIDAL ISOLADOR 2000VA"); + data.VA = 2000; + break; + + case 89: + data.upscode = 89; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 2400VA GII"); + data.VA = 2400; + break; + + case 90: + data.upscode = 90; + strcpy(data.upsdesc,"NHS PDV 1400VA S 8T GII"); + data.VA = 1400; + break; + + case 91: + data.upscode = 91; + strcpy(data.upsdesc,"PREMIUM ONLINE 2000VA"); + data.VA = 2000; + break; + + case 92: + data.upscode = 92; + strcpy(data.upsdesc,"LASER PRIME ONLINE 2200VA"); + data.VA = 2200; + break; + + case 93: + data.upscode = 93; + strcpy(data.upsdesc,"PREMIUM RACK ONLINE 2200VA"); + data.VA = 2200; + break; + + case 94: + data.upscode = 94; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 2400VA GII"); + data.VA = 2400; + break; + + case 95: + data.upscode = 95; + strcpy(data.upsdesc,"LASER ONLINE 10000VA"); + data.VA = 10000; + break; + + case 96: + data.upscode = 96; + strcpy(data.upsdesc,"LASER ONLINE BIFASICO 10000VA"); + data.VA = 10000; + break; + + case 97: + data.upscode = 97; + strcpy(data.upsdesc,"LASER SENOIDAL 3300VA GII"); + data.VA = 3300; + break; + + case 98: + data.upscode = 98; + strcpy(data.upsdesc,"LASER SENOIDAL 2600VA GII"); + data.VA = 2600; + break; + + case 99: + data.upscode = 99; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 3000VA GII"); + data.VA = 3000; + break; + + case 100: + data.upscode = 100; + strcpy(data.upsdesc,"PREMIUM SENOIDAL 2200VA GII"); + data.VA = 2200; + break; + + case 101: + data.upscode = 101; + strcpy(data.upsdesc,"LASER ONLINE BIFASICO 4000VA"); + data.VA = 4000; + break; + + case 102: + data.upscode = 102; + strcpy(data.upsdesc,"LASER ONLINE 12000VA"); + data.VA = 12000; + break; + + case 103: + data.upscode = 103; + strcpy(data.upsdesc,"LASER ONLINE 8000VA"); + data.VA = 8000; + break; + + case 104: + data.upscode = 104; + strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 1000VA"); + data.VA = 1000; + break; + + case 105: + data.upscode = 105; + strcpy(data.upsdesc,"MINI SENOIDAL 500VA"); + data.VA = 500; + break; + + case 106: + data.upscode = 106; + strcpy(data.upsdesc,"LASER SENOIDAL 5000VA GII"); + data.VA = 5000; + break; + + case 107: + data.upscode = 107; + strcpy(data.upsdesc,"COMPACT PLUS SENOIDAL 1000VA"); + data.VA = 1000; + break; + + case 108: + data.upscode = 108; + strcpy(data.upsdesc,"QUAD_COM 80A"); + data.VA = 0; + break; + + case 109: + data.upscode = 109; + strcpy(data.upsdesc,"LASER ONLINE 5000VA"); + data.VA = 5000; + break; + + case 113: + data.upscode = 113; + strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 700VA"); + data.VA = 700; + break; + + default: + data.upscode = -1; + strcpy(data.upsdesc,"NHS UNKNOWN"); + data.VA = 0; + break; + } + return data; +} + +unsigned int get_va(int equipment) { + upsinfo ups; + char * va = getval("va"); + ups = getupsinfo(equipment); + if (ups.VA > 0) + return ups.VA; + else { + if (va) + return atoi(va); + else + fatalx(EXIT_FAILURE,"Please set VA (Volt Ampere) nominal capacity value to your equipment in ups.conf."); + } +} + +float get_pf() { + char * pf = getval("pf"); + if (pf) + return atof(pf); + else + return DEFAULTPF; +} + +unsigned int get_ah() { + char * ah = getval("ah"); + if (ah) + return (unsigned int)atoi(ah); + else + fatalx(EXIT_FAILURE,"Please set AH (Ampere Hour) value to your battery's equipment in ups.conf."); +} + +float get_vin_perc(char * var) { + char * perc = getval(var); + if (perc) + return atof(perc); + else + return DEFAULLTPERC; +} + +void upsdrv_initinfo(void) { + char * b = getval("baud"); + upsdebugx(1,"Port is %s and baud_rate is %s",device_path,b); + baudrate = DEFAULTBAUD; + upsdebugx(1,"Start initinfo()"); + if (b) + baudrate = atoi(b); + if (device_path) { + if (strcasecmp(device_path,"auto") == 0) + strcpy(porta,DEFAULTPORT); + else + strcpy(porta,device_path); + serial_fd = openfd(porta,baudrate); + if (serial_fd == -1) + fatalx(EXIT_FAILURE,"Unable to open port %s with baud %d",porta,baudrate); + else { + upsdebugx(1,"Communication started on port %s, baud rate %d. Calling updateinfo()",porta,baudrate); + } + } + else + fatalx(EXIT_FAILURE,"Unable to define port and baud"); + upsdebugx(1,"End initinfo()"); +} + +float calculate_efficiency(float vacoutrms, float vacinrms) { + return (vacoutrms * vacinrms) / 100.0; +} + +void upsdrv_updateinfo(void) { + // retries to open port + unsigned int retries = 3; + unsigned int i = 0; + char alarm[1024]; + unsigned int va = 0; + unsigned int ah = 0; + unsigned int vin_underv = 0; + unsigned int vin_overv = 0; + unsigned int perc = 0; + unsigned int vin = 0; + unsigned int vout = 0; + unsigned int autonomy_secs = 0; + float vin_low_warn = 0; + float vin_low_crit = 0; + float vin_high_warn = 0; + float vin_high_crit = 0; + float calculated = 0; + float vpower = 0; + float pf = 0; + int bcharge = 0; + int min_input_power = 0; + + upsinfo ups; + + upsdebugx(1,"Start updateinfo()"); + if ((serial_fd <= 0) && (i < retries)) { + upsdebugx(1,"Serial problem..\r\n"); + while (serial_fd <= 0) { + serial_fd = openfd(DEFAULTPORT,2400); + upsdebugx(1,"Trying to reopen serial...\r\n"); + usleep(checktime); + retries++; + } + } + else { + // Clean all read buffers to avoid errors + // To clean OUTPUT buffer is TCOFLUSH. To both is TCIOFLUSH. + //tcflush(serial_fd, TCIFLUSH); + chr = '\0'; + while (read(serial_fd, &chr,1) > 0) { + if (chr == 0xFF) { // DataPacket start + datapacketstart = true; + } // end for + if (datapacketstart) { + datapacket[datapacket_index] = chr; + datapacket_index++; + if (chr == 0xFE) { // DataPacket + upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); + double tempodecorrido = 0.0; + time_t now = time(NULL); + if (lastdp != 0) { + tempodecorrido = difftime(now, lastdp); + } + lastdp = now; + // if size is 18 or 50, maybe a answer packet. Then check if doesn't have already a packet processed. We don't need to read all times these information. Can be a corrupted packet too. + if (((datapacket_index == 18) || (datapacket_index == 50)) && (!lastpkthwinfo.checksum_ok)) { + lastpkthwinfo = mount_hwinfo(datapacket, datapacket_index); + } // end if + else { + if (datapacket_index == 21) + lastpktdata = mount_datapacket(datapacket, datapacket_index, tempodecorrido,lastpkthwinfo); + } // end else + // Clean datapacket structure to avoid problems + datapacket_index = 0; + memset(datapacket,0,sizeof(datapacket)); + datapacketstart = false; + if (lastpktdata.checksum_ok) { + // checksum is OK, then use it to set values + upsdebugx(1,"Data Packet seems be OK"); + if (lastpkthwinfo.size == 0) + upsdebugx(1,"Pkt HWINFO is not OK. See if will be requested next time!"); + else { + if (lastpkthwinfo.checksum_ok) { + upsdebugx(1,"Pkt HWINFO is OK. Model is %d, hwversion is %d and swversion is %d",lastpkthwinfo.model,lastpkthwinfo.hardwareversion,lastpkthwinfo.softwareversion); + // We need to set data on NUT with data that I believe that I can calculate. Now setting data on NUT + ups = getupsinfo(lastpkthwinfo.model); + upsdebugx(1,"UPS Struct data: Code %d Model %s VA %d",ups.upscode,ups.upsdesc,ups.VA); + dstate_setinfo("device.model", "%s",ups.upsdesc); + dstate_setinfo("device.mfr","%s",MANUFACTURER); + dstate_setinfo("device.serial","%s",lastpkthwinfo.serial); + dstate_setinfo("device.type","%s","ups"); + /* Setting UPS Status + OL -- On line (mains is present): Code below + OB -- On battery (mains is not present) : Code below + LB -- Low battery: Code below + HB -- High battery: NHS doesn't have any variable with that information. Feel free to discover a way to set it + RB -- The battery needs to be replaced: Well, as mentioned, we can write some infos on nobreak fw, on structures like pkt_hwinfo.year, pkt_hwinfo.month, etc. I never found any equipment with these values. + CHRG -- The battery is charging: Code below + DISCHRG -- The battery is discharging (inverter is providing load power): Code Below + BYPASS -- UPS bypass circuit is active -- no battery protection is available: It's another PROBLEM, because NHS can work in bypass mode in some models, even if you have sealed batteries on it (without any external battery device). On the moment, i'll won't work with that. Feel free to discover how it work correctly. + CAL -- UPS is currently performing runtime calibration (on battery) + OFF -- UPS is offline and is not supplying power to the load + OVER -- UPS is overloaded + TRIM -- UPS is trimming incoming voltage (called "buck" in some hardware) + BOOST -- UPS is boosting incoming voltage + FSD -- Forced Shutdown (restricted use, see the note below) */ + + // Decision Chain + // First we check if system is on battery or not + upsdebugx(1,"Set UPS status as OFF and start checking. s_battery_mode is %d",lastpktdata.s_battery_mode); + if (lastpkthwinfo.s_220V_in) { + upsdebugx(1,"I'm on 220v IN!. My overvoltage is %d",lastpkthwinfo.undervoltagein220V); + min_input_power = lastpkthwinfo.undervoltagein220V; + } + else { + upsdebugx(1,"I'm on 120v IN!. My overvoltage is %d",lastpkthwinfo.undervoltagein120V); + min_input_power = lastpkthwinfo.undervoltagein120V; + } + if (lastpktdata.s_battery_mode) { + // ON BATTERY + upsdebugx(1,"UPS is on Battery Mode"); + dstate_setinfo("ups.status","%s","OB"); + if (lastpktdata.s_battery_low) { + // If battery is LOW, warn user! + upsdebugx(1,"UPS is on Battery Mode and in Low Battery State"); + dstate_setinfo("ups.status","%s","LB"); + } // end if + } // end if + else { + // Check if MAINS (power) is not preset. Well, we can check pkt_data.s_network_failure too... + if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { + sprintf(alarm,"UPS have power in %f value and min_input_power is %d or network is in failure. Network failure is %d",lastpktdata.vacinrms,min_input_power,lastpktdata.s_network_failure); + upsdebugx(1,alarm); + dstate_setinfo("ups.status","%s","DISCHRG"); + } // end if + else { + // MAINS is present. We need to check some situations. NHS only charge if have more than min_input_power. If MAINS is less or equal min_input_power then ups goes to BATTERY + if (lastpktdata.vacinrms > min_input_power) { + upsdebugx(1,"UPS is on MAINS"); + if (lastpktdata.s_charger_on) { + upsdebugx(1,"UPS Charging..."); + dstate_setinfo("ups.status","%s","CHRG"); + } + else { + if ((lastpktdata.s_network_failure) || (lastpktdata.s_fast_network_failure)) { + upsdebugx(1,"UPS is on battery mode because network failure or fast network failure"); + dstate_setinfo("ups.status","%s","OB"); + } // end if + else { + upsdebugx(1,"All is OK. UPS is on ONLINE!"); + dstate_setinfo("ups.status","%s","OL"); + } // end else + } // end else + } // end if + else { + // Energy is below limit. Nobreak problably in battery mode + if (lastpktdata.s_battery_low) + dstate_setinfo("ups.status","%s","LB"); + else { + // or network failure + dstate_setinfo("ups.status","%s","OB"); + } // end else + } // end else + } // end else + } // end else + + alarm[0] = '\0'; + // Set all alarms possible + if (lastpktdata.s_battery_mode) + sprintf(alarm,"%s","|UPS IN BATTERY MODE|"); + if (lastpktdata.s_battery_low) + sprintf(alarm,"%s %s",alarm,"|UPS IN BATTERY MODE|"); + if (lastpktdata.s_network_failure) + sprintf(alarm,"%s %s",alarm,"|NETWORK FAILURE|"); + if (lastpktdata.s_fast_network_failure) + sprintf(alarm,"%s %s",alarm,"|FAST NETWORK FAILURE|"); + if (lastpktdata.s_fast_network_failure) + sprintf(alarm,"%s %s",alarm,"|220v IN|"); + if (lastpktdata.s_fast_network_failure) + sprintf(alarm,"%s %s",alarm,"|220v OUT|"); + if (lastpktdata.s_bypass_on) + sprintf(alarm,"%s %s",alarm,"|BYPASS ON|"); + if (lastpktdata.s_charger_on) + sprintf(alarm,"%s %s",alarm,"|CHARGER ON|"); + dstate_setinfo("ups.alarm","%s",alarm); + dstate_setinfo("ups.model","%s",ups.upsdesc); + dstate_setinfo("ups.mfr","%s",MANUFACTURER); + dstate_setinfo("ups.serial","%s",lastpkthwinfo.serial); + dstate_setinfo("ups.firmware","%u",lastpkthwinfo.softwareversion); + // Setting hardware version here. Not found another place to do. Feel free to correct it + dstate_setinfo("ups.firmware.aux","%u",lastpkthwinfo.hardwareversion); + dstate_setinfo("ups.temperature","%f",lastpktdata.tempmed_real); + dstate_setinfo("ups.load","%u",lastpktdata.potrms); + dstate_setinfo("ups.efficiency","%f", calculate_efficiency(lastpktdata.vacoutrms, lastpktdata.vacinrms)); + va = get_va(lastpkthwinfo.model); + pf = get_pf(); + vpower = ((va * pf) * (lastpktdata.potrms / 100.0)); + if (vpower > maxpower) + maxpower = vpower; + if (vpower < minpower) + minpower = vpower; + dstate_setinfo("ups.power","%f",vpower); + dstate_setinfo("ups.power.nominal","%u",va); + dstate_setinfo("ups.realpower","%d",(int)round((va * pf) * (lastpktdata.potrms / 100.0))); + dstate_setinfo("ups.realpower.nominal","%d",(int)round(va * pf)); + dstate_setinfo("ups.beeper.status","%d",!lastpkthwinfo.c_buzzer_disable); + dstate_setinfo("input.voltage","%f",lastpktdata.vacinrms); + dstate_setinfo("input.voltage.maximum","%f",lastpktdata.vacinrmsmin); + dstate_setinfo("input.voltage.minimum","%f",lastpktdata.vacinrmsmax); + vin_underv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V; + vin_overv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V; + perc = get_vin_perc("vin_low_warn_perc") == get_vin_perc("vin_low_crit_perc") ? 2 : 1; + vin_low_warn = vin_underv + (vin_underv * ((get_vin_perc("vin_low_warn_perc") * perc) / 100.0)); + dstate_setinfo("input.voltage.low.warning","%f",calculated); + vin_low_crit = vin_underv + (vin_underv * (get_vin_perc("vin_low_crit_perc") / 100.0)); + dstate_setinfo("input.voltage.low.critical","%f",calculated); + vin_high_warn = vin_overv + (vin_overv * ((get_vin_perc("vin_high_warn_perc") * perc) / 100.0)); + dstate_setinfo("input.voltage.high.warning","%f",calculated); + vin_high_crit = vin_overv + (vin_overv * (get_vin_perc("vin_high_crit_perc") / 100.0)); + dstate_setinfo("input.voltage.high.critical","%f",calculated); + vin = lastpkthwinfo.s_220V_in ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; + dstate_setinfo("input.voltage.nominal","%u",vin); + dstate_setinfo("input.transfer.low","%u",lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V); + dstate_setinfo("input.transfer.high","%u",lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V); + dstate_setinfo("output.voltage","%f",lastpktdata.vacoutrms); + vout = lastpkthwinfo.s_220V_out ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; + dstate_setinfo("output.voltage.nominal","%u",vout); + dstate_setinfo("voltage","%f",lastpktdata.vacoutrms); + dstate_setinfo("voltage.nominal","%u",vout); + dstate_setinfo("voltage.maximum","%f",lastpktdata.vacinrmsmax); + dstate_setinfo("voltage.minimum","%f",lastpktdata.vacinrmsmin); + dstate_setinfo("voltage.low.warning","%f",vin_low_warn); + dstate_setinfo("voltage.low.critical","%f",vin_low_crit); + dstate_setinfo("voltage.high.warning","%f",vin_high_warn); + dstate_setinfo("voltage.high.critical","%f",vin_high_crit); + dstate_setinfo("power","%f",vpower); + dstate_setinfo("power.maximum","%f",maxpower); + dstate_setinfo("power.minimum","%f",minpower); + dstate_setinfo("power.percent","%u",lastpktdata.potrms); + if (lastpktdata.potrms > maxpowerperc) + maxpowerperc = lastpktdata.potrms; + if (lastpktdata.potrms < minpowerperc) + minpowerperc = lastpktdata.potrms; + dstate_setinfo("power.maximum.percent","%u",maxpowerperc); + dstate_setinfo("power.minimum.percent","%u",minpowerperc); + dstate_setinfo("realpower","%u",(unsigned int)round((va * pf) * (lastpktdata.potrms / 100.0))); + dstate_setinfo("power","%u",(unsigned int)round(va * (lastpktdata.potrms / 100.0))); + bcharge = (int)round((lastpktdata.vdcmed_real * 100) / 12.0); + if (bcharge > 100) + bcharge = 100; + dstate_setinfo("battery.charge","%d",bcharge); + dstate_setinfo("battery.voltage","%f",lastpktdata.vdcmed_real * lastpkthwinfo.numbatteries); + dstate_setinfo("battery.voltage.nominal","%u",12); + ah = get_ah(); + dstate_setinfo("battery.capacity","%u",ah); + dstate_setinfo("battery.capacity.nominal","%f",(float)ah * pf); + dstate_setinfo("battery.current","%f",lastpktdata.vdcmed_real); + dstate_setinfo("battery.current.total","%f",(float)12 * lastpkthwinfo.numbatteries); + dstate_setinfo("battery.temperature","%u",(unsigned int)round(lastpktdata.tempmed_real)); + dstate_setinfo("battery.packs","%u",lastpkthwinfo.numbatteries); + // We will calculate autonomy in seconds + autonomy_secs = (lastpkthwinfo.numbatteries * lastpktdata.vdcmed_real * va * pf) / ((lastpktdata.potrms * va * pf) / 100.0) * 3600; + dstate_setinfo("battery.runtime","%u",autonomy_secs); + dstate_setinfo("battery.runtime.low","%u",30); + if (lastpktdata.s_charger_on) + dstate_setinfo("battery.charger.status","%s","CHARGING"); + else { + if (lastpktdata.s_battery_mode) + dstate_setinfo("battery.charger.status","%s","DISCHARGING"); + else + dstate_setinfo("battery.charger.status","%s","RESTING"); + } + // Now, creating a structure called NHS, + dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); + dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); + dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); + dstate_setinfo("nhs.hw.model", "%u", lastpkthwinfo.model); + dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); + dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); + dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); + for (int i = 0; i < 5; i++) { + // Reusing variable + sprintf(alarm,"nhs.hw.configuration_array_p%d",i); + dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); + } + dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); + dstate_setinfo("nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); + dstate_setinfo("nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); + dstate_setinfo("nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); + dstate_setinfo("nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); + dstate_setinfo("nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); + dstate_setinfo("nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); + dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); + dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); + dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); + for (int i = 0; i < 6; i++) { + // Reusing variable + sprintf(alarm,"nhs.hw.status_p%d",i); + dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); + } + dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); + dstate_setinfo("nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); + dstate_setinfo("nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); + dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); + dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); + dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); + dstate_setinfo("nhs.hw.month", "%u", lastpkthwinfo.month); + dstate_setinfo("nhs.hw.wday", "%u", lastpkthwinfo.wday); + dstate_setinfo("nhs.hw.hour", "%u", lastpkthwinfo.hour); + dstate_setinfo("nhs.hw.minute", "%u", lastpkthwinfo.minute); + dstate_setinfo("nhs.hw.second", "%u", lastpkthwinfo.second); + dstate_setinfo("nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); + dstate_setinfo("nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); + dstate_setinfo("nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); + dstate_setinfo("nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); + dstate_setinfo("nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); + dstate_setinfo("nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); + dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); + dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); + + // Data packet + dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); + dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); + dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); + dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); + dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); + dstate_setinfo("nhs.data.vacinrms", "%.2f", lastpktdata.vacinrms); + dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); + dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); + dstate_setinfo("nhs.data.vdcmed", "%.2f", lastpktdata.vdcmed); + dstate_setinfo("nhs.data.vdcmed_real", "%.2f", lastpktdata.vdcmed_real); + dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); + dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); + dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); + dstate_setinfo("nhs.data.vacinrmsmin", "%.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); + dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); + dstate_setinfo("nhs.data.vacinrmsmax", "%.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); + dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); + dstate_setinfo("nhs.data.vacoutrms", "%.2f", lastpktdata.vacoutrms); + dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); + dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); + dstate_setinfo("nhs.data.tempmed", "%.2f", lastpktdata.tempmed); + dstate_setinfo("nhs.data.tempmed_real", "%.2f", lastpktdata.tempmed_real); + dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); + dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); + dstate_setinfo("nhs.data.battery_tension", "%.2f", lastpktdata.battery_tension); + dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); + dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); + for (int i = 0; i < 8; i++) { + // Reusing variable + sprintf(alarm,"nhs.data.status_p%d",i); + dstate_setinfo(alarm, "%u", lastpktdata.status[i]); + } + dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); + dstate_setinfo("nhs.data.timeremain", "%.2f", lastpktdata.timeremain); + dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); + dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); + dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); + dstate_setinfo("nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); + dstate_setinfo("nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); + dstate_setinfo("nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); + dstate_setinfo("nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); + dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); + dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); + dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); + dstate_setinfo("nhs.param.va", "%u", va); + dstate_setinfo("nhs.param.pf", "%f", pf); + dstate_setinfo("nhs.param.ah", "%u", ah); + dstate_setinfo("nhs.param.vin_low_warn_perc", "%f", get_vin_perc("vin_low_warn_perc")); + dstate_setinfo("nhs.param.vin_low_crit_perc", "%f", get_vin_perc("vin_low_crit_perc")); + dstate_setinfo("nhs.param.vin_high_warn_perc", "%f", get_vin_perc("vin_high_warn_perc")); + dstate_setinfo("nhs.param.vin_high_crit_perc", "%f", get_vin_perc("vin_high_crit_perc")); + + dstate_dataok(); + } // end if + else + upsdebugx(1,"Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request...\r\n"); + } // end else + } // end if + } // end if + } // end if + } // end if + // Now the nobreak read buffer is empty. We need a hw info packet to discover several variables, like number of batteries, to calculate some data + if (!lastpkthwinfo.checksum_ok) { + upsdebugx(1,"pkt_hwinfo loss -- Requesting\r\n"); + // if size == 0, packet maybe not initizated, then send a initialization packet to obtain data + // Send two times the extended initialization string, but, on fail, try randomly send extended or normal + if (send_extended < 2) { + bwritten = write_serial_int(serial_fd,string_initialization_long,9); + send_extended++; + } // end if + else { + // randomly send + if (rand() % 2 == 0) + bwritten = write_serial_int(serial_fd,string_initialization_long,9); + else + bwritten = write_serial_int(serial_fd,string_initialization_short,9); + } // end else + if (bwritten < 0) { + if (bwritten == -1) { + upsdebugx(1,"Problem to write data to %s",DEFAULTPORT); + upsdebugx(1,"\r\nData problem\r\n"); + } + if (bwritten == -2) { + upsdebugx(1,"\r\nFlush problem\r\n"); + } + close(serial_fd); + serial_fd = -1; + } // end if + else + // some sleep to help + usleep(checktime); + } // end if + } // end else + upsdebugx(1,"End updateinfo()"); +} + +void upsdrv_shutdown(void) { + upsdebugx(1,"Start shutdown()"); + if (serial_fd != -1) { + close(serial_fd); + serial_fd = -1; + } + upsdebugx(1,"Driver shutdown"); +} + +void upsdrv_cleanup(void) { + upsdebugx(1,"Start cleanup()"); + if (serial_fd != -1) { + close(serial_fd); + serial_fd = -1; + } + upsdebugx(1,"End cleanup()"); +} + +void upsdrv_initups(void) { + upsdebugx(1,"Start initups()"); + upsdrv_initinfo(); + upsdebugx(1,"End initups()"); +} + +void upsdrv_makevartable(void) { + char help[4096]; + addvar(VAR_VALUE, "port", "Port to communication"); + addvar(VAR_VALUE, "baud", "Baud Rate from port"); + addvar(VAR_VALUE,"ah","Battery discharge capacity in Ampere/hour"); + addvar(VAR_VALUE,"va","Nobreak NOMINAL POWER in VA"); + sprintf(help,"Power Factor, default is %0.2f",DEFAULTPF); + addvar(VAR_VALUE,"pf",help); + sprintf(help,"Voltage In Percentage to calculate warning low level. Default is %0.2f",DEFAULLTPERC); + addvar(VAR_VALUE,"vin_low_warn_perc",help); + sprintf(help,"Voltage In Percentage to calculate critical low level. Default is %0.2f",DEFAULLTPERC); + addvar(VAR_VALUE,"vin_low_crit_perc",help); + sprintf(help,"Voltage In Percentage to calculate warning high level. Default is %0.2f",DEFAULLTPERC); + addvar(VAR_VALUE,"vin_high_warn_perc",help); + sprintf(help,"Voltage In Percentage to calculate critical high level. Default is %0.2f",DEFAULLTPERC); + addvar(VAR_VALUE,"vin_high_crit_perc",help); +} + +void upsdrv_help(void) { +} + +//int main(int argc, char **argv) { +// upsdrv_info.version = "1.0"; +// upsdrv_initinfo(); +//} + From 020f12add2e59392fc00e779de2b6a9e691bde5d Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Tue, 26 Nov 2024 00:29:46 -0300 Subject: [PATCH 02/60] Some minor alterations Signed-off-by: Lucas Willian Bocchi lucas@lucas.inf.br --- drivers/nhs-nut.c | 617 ++++++++++++++++++++++++---------------------- 1 file changed, 327 insertions(+), 290 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 16836fcf8a..4b5d1cca1a 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -45,7 +45,7 @@ 3) Download NUT source code OR use apt-source to download source from your distribution (in case of debian/ubuntu). How to do it? apt-get source nut, apt-get build-dep nut, make your alterations in code (follow the steps above), dpkg-buildpackage -us -uc, dpkg -i * ./autogen.sh 4) ./autogen.sh 5) ./ci_build.sh - 6) ./configure --with-dev + 6) ./configure $COMPILEFLAGS --with-dev 7) cd drivers 8) make (to generate nut_version.h) @@ -57,7 +57,8 @@ 5) back to root nut source directory, then dpkg-buildpackage -us -uc 6) dpkg -i - * gcc -g -O0 -o nhs-nut nhs-nut.c main.c dstate.c upsdrvquery.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm + * gcc -g -O0 -o nhs-nut nhs-nut.c main.c dstate.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm + * upsdrvquery.c (optional) * copy nhs-nut to nut driver's directory and test To debug: * clang --analyze nhs-nut.c @@ -67,7 +68,7 @@ * upsd -D */ -#define DEFAULTBAUD B2400 +#define DEFAULTBAUD 2400 #define DEFAULTPORT "/dev/ttyACM0" #define DEFAULTPF 0.9 #define DEFAULLTPERC 2 @@ -154,7 +155,8 @@ typedef struct { bool s_show_temperature; bool s_show_charger_current; unsigned int chargercurrent; - unsigned int checksum; + unsigned char checksum; + unsigned char checksum_calc; bool checksum_ok; char serial[17]; unsigned int year; @@ -215,7 +217,8 @@ typedef struct { bool s_220_out; bool s_bypass_on; bool s_charger_on; - unsigned int checksum; + unsigned char checksum; + unsigned char checksum_calc; bool checksum_ok; unsigned int end_marker; } pkt_data; @@ -234,8 +237,8 @@ static unsigned char chr; static int datapacket_index = 0; static bool datapacketstart = false; static time_t lastdp = 0; -static unsigned int checktime = 1000000; // 1 second -static unsigned int max_checktime = 3000000; // max wait time -- 3 seconds +static unsigned int checktime = 2000000; // 2 second +static unsigned int max_checktime = 6000000; // max wait time -- 6 seconds static unsigned int send_extended = 0; static int bwritten = 0; static unsigned char datapacket[DATAPACKETSIZE]; @@ -247,99 +250,101 @@ static unsigned int minpowerperc = 0; static unsigned int maxpowerperc = 0; static pkt_hwinfo lastpkthwinfo = { - .header = 0xFF, - .size = 0, - .type = 'S', - .model = 0, - .hardwareversion = 0, - .softwareversion = 0, - .configuration = 0, - .configuration_array = {0, 0, 0, 0, 0}, - .c_oem_mode = false, - .c_buzzer_disable = false, - .c_potmin_disable = false, - .c_rearm_enable = false, - .c_bootloader_enable = false, - .numbatteries = 0, - .undervoltagein120V = 0, - .overvoltagein120V = 0, - .undervoltagein220V = 0, - .overvoltagein220V = 0, - .tensionout120V = 0, - .tensionout220V = 0, - .statusval = 0, - .status = {0, 0, 0, 0, 0, 0}, - .s_220V_in = false, - .s_220V_out = false, - .s_sealed_battery = false, - .s_show_out_tension = false, - .s_show_temperature = false, - .s_show_charger_current = false, - .chargercurrent = 0, - .checksum = 0, - .checksum_ok = false, - .serial = "----------------", - .year = 0, - .month = 0, - .wday = 0, - .hour = 0, - .minute = 0, - .second = 0, - .alarmyear = 0, - .alarmmonth = 0, - .alarmwday = 0, - .alarmday = 0, - .alarmhour = 0, - .alarmminute = 0, - .alarmsecond = 0, - .end_marker = 0xFE - }; + 0xFF, // header + 0, // size + 'S', // type + 0, // model + 0, // hardwareversion + 0, // softwareversion + 0, // configuration + {0, 0, 0, 0, 0}, // configuration_array + false, // c_oem_mode + false, // c_buzzer_disable + false, // c_potmin_disable + false, // c_rearm_enable + false, // c_bootloader_enable + 0, // numbatteries + 0, // undervoltagein120V + 0, // overvoltagein120V + 0, // undervoltagein220V + 0, // overvoltagein220V + 0, // tensionout120V + 0, // tensionout220V + 0, // statusval + {0, 0, 0, 0, 0, 0}, // status + false, // s_220V_in + false, // s_220V_out + false, // s_sealed_battery + false, // s_show_out_tension + false, // s_show_temperature + false, // s_show_charger_current + 0, // chargercurrent + 0, // checksum + 0, // checksum_calc + false, // checksum_ok + "----------------", // serial + 0, // year + 0, // month + 0, // wday + 0, // hour + 0, // minute + 0, // second + 0, // alarmyear + 0, // alarmmonth + 0, // alarmwday + 0, // alarmday + 0, // alarmhour + 0, // alarmminute + 0, // alarmsecond + 0xFE // end_marker +}; static pkt_data lastpktdata = { - .header = 0xFF, - .length = 0x21, - .packet_type = 'D', - .vacinrms_high = 0, - .vacinrms_low = 0, - .vacinrms = 0, - .vdcmed_high = 0, - .vdcmed_low = 0, - .vdcmed = 0, - .vdcmed_real = 0, - .potrms = 0, - .vacinrmsmin_high = 0, - .vacinrmsmin_low = 0, - .vacinrmsmin = 0, - .vacinrmsmax_high = 0, - .vacinrmsmax_low = 0, - .vacinrmsmax = 0, - .vacoutrms_high = 0, - .vacoutrms_low = 0, - .vacoutrms = 0, - .tempmed_high = 0, - .tempmed_low = 0, - .tempmed = 0, - .tempmed_real = 0, - .icarregrms = 0, - .icarregrms_real = 0, - .battery_tension = 0, - .perc_output = 0, - .statusval = 0, - .status = {0, 0, 0, 0, 0, 0, 0, 0}, - .nominaltension = 0, - .timeremain = 0.0f, - .s_battery_mode = false, - .s_battery_low = false, - .s_network_failure = false, - .s_fast_network_failure = false, - .s_220_in = false, - .s_220_out = false, - .s_bypass_on = false, - .s_charger_on = false, - .checksum = 0, - .checksum_ok = false, - .end_marker = 0xFE - }; + 0xFF, // header + 0x21, // length + 'D', // packet_type + 0, // vacinrms_high + 0, // vacinrms_low + 0, // vacinrms + 0, // vdcmed_high + 0, // vdcmed_low + 0, // vdcmed + 0, // vdcmed_real + 0, // potrms + 0, // vacinrmsmin_high + 0, // vacinrmsmin_low + 0, // vacinrmsmin + 0, // vacinrmsmax_high + 0, // vacinrmsmax_low + 0, // vacinrmsmax + 0, // vacoutrms_high + 0, // vacoutrms_low + 0, // vacoutrms + 0, // tempmed_high + 0, // tempmed_low + 0, // tempmed + 0, // tempmed_real + 0, // icarregrms + 0, // icarregrms_real + 0, // battery_tension + 0, // perc_output + 0, // statusval + {0, 0, 0, 0, 0, 0, 0, 0}, // status + 0, // nominaltension + 0.0f, // timeremain + false, // s_battery_mode + false, // s_battery_low + false, // s_network_failure + false, // s_fast_network_failure + false, // s_220_in + false, // s_220_out + false, // s_bypass_on + false, // s_charger_on + 0, // checksum + 0, // checksum_calc + false, // checksum_ok + 0xFE // end_marker +}; int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorder) { unsigned char *byte_ptr = (unsigned char *)ptr; @@ -360,117 +365,118 @@ int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorde return retval; } - void print_pkt_hwinfo(pkt_hwinfo data) { - upsdebugx(1,"Header: %u\n", data.header); - upsdebugx(1,"Size: %u\n", data.size); - upsdebugx(1,"Type: %c\n", data.type); - upsdebugx(1,"Model: %u\n", data.model); - upsdebugx(1,"Hardware Version: %u\n", data.hardwareversion); - upsdebugx(1,"Software Version: %u\n", data.softwareversion); - upsdebugx(1,"Configuration: %u\n", data.configuration); + upsdebugx(1,"Header: %u", data.header); + upsdebugx(1,"Size: %u", data.size); + upsdebugx(1,"Type: %c", data.type); + upsdebugx(1,"Model: %u", data.model); + upsdebugx(1,"Hardware Version: %u", data.hardwareversion); + upsdebugx(1,"Software Version: %u", data.softwareversion); + upsdebugx(1,"Configuration: %u", data.configuration); upsdebugx(1,"Configuration Array: "); for (int i = 0; i < 5; i++) { int retorno = get_bit_in_position(&data.configuration,sizeof(data.configuration),i,0); upsdebugx(1,"Binary value is %d",retorno); upsdebugx(1,"%u ", data.configuration_array[i]); } - upsdebugx(1,"\n"); - upsdebugx(1,"OEM Mode: %s\n", data.c_oem_mode ? "true" : "false"); - upsdebugx(1,"Buzzer Disable: %s\n", data.c_buzzer_disable ? "true" : "false"); - upsdebugx(1,"Potmin Disable: %s\n", data.c_potmin_disable ? "true" : "false"); - upsdebugx(1,"Rearm Enable: %s\n", data.c_rearm_enable ? "true" : "false"); - upsdebugx(1,"Bootloader Enable: %s\n", data.c_bootloader_enable ? "true" : "false"); - upsdebugx(1,"Number of Batteries: %u\n", data.numbatteries); - upsdebugx(1,"Undervoltage In 120V: %u\n", data.undervoltagein120V); - upsdebugx(1,"Overvoltage In 120V: %u\n", data.overvoltagein120V); - upsdebugx(1,"Undervoltage In 220V: %u\n", data.undervoltagein220V); - upsdebugx(1,"Overvoltage In 220V: %u\n", data.overvoltagein220V); - upsdebugx(1,"Tension Out 120V: %u\n", data.tensionout120V); - upsdebugx(1,"Tension Out 220V: %u\n", data.tensionout220V); - upsdebugx(1,"Status Value: %u\n", data.statusval); + upsdebugx(1,""); + upsdebugx(1,"OEM Mode: %s", data.c_oem_mode ? "true" : "false"); + upsdebugx(1,"Buzzer Disable: %s", data.c_buzzer_disable ? "true" : "false"); + upsdebugx(1,"Potmin Disable: %s", data.c_potmin_disable ? "true" : "false"); + upsdebugx(1,"Rearm Enable: %s", data.c_rearm_enable ? "true" : "false"); + upsdebugx(1,"Bootloader Enable: %s", data.c_bootloader_enable ? "true" : "false"); + upsdebugx(1,"Number of Batteries: %u", data.numbatteries); + upsdebugx(1,"Undervoltage In 120V: %u", data.undervoltagein120V); + upsdebugx(1,"Overvoltage In 120V: %u", data.overvoltagein120V); + upsdebugx(1,"Undervoltage In 220V: %u", data.undervoltagein220V); + upsdebugx(1,"Overvoltage In 220V: %u", data.overvoltagein220V); + upsdebugx(1,"Tension Out 120V: %u", data.tensionout120V); + upsdebugx(1,"Tension Out 220V: %u", data.tensionout220V); + upsdebugx(1,"Status Value: %u", data.statusval); upsdebugx(1,"Status: "); for (int i = 0; i < 6; i++) { upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); upsdebugx(1,"status %d --> %u ", i, data.status[i]); } - upsdebugx(1,"\n"); - upsdebugx(1,"220V In: %s\n", data.s_220V_in ? "true" : "false"); - upsdebugx(1,"220V Out: %s\n", data.s_220V_out ? "true" : "false"); - upsdebugx(1,"Sealed Battery: %s\n", data.s_sealed_battery ? "true" : "false"); - upsdebugx(1,"Show Out Tension: %s\n", data.s_show_out_tension ? "true" : "false"); - upsdebugx(1,"Show Temperature: %s\n", data.s_show_temperature ? "true" : "false"); - upsdebugx(1,"Show Charger Current: %s\n", data.s_show_charger_current ? "true" : "false"); - upsdebugx(1,"Charger Current: %u\n", data.chargercurrent); - upsdebugx(1,"Checksum: %u\n", data.checksum); - upsdebugx(1,"Checksum OK: %s\n", data.checksum_ok ? "true" : "false"); - upsdebugx(1,"Serial: %s\n", data.serial); - upsdebugx(1,"Year: %u\n", data.year); - upsdebugx(1,"Month: %u\n", data.month); - upsdebugx(1,"Weekday: %u\n", data.wday); - upsdebugx(1,"Hour: %u\n", data.hour); - upsdebugx(1,"Minute: %u\n", data.minute); - upsdebugx(1,"Second: %u\n", data.second); - upsdebugx(1,"Alarm Year: %u\n", data.alarmyear); - upsdebugx(1,"Alarm Month: %u\n", data.alarmmonth); - upsdebugx(1,"Alarm Weekday: %u\n", data.alarmwday); - upsdebugx(1,"Alarm Day: %u\n", data.alarmday); - upsdebugx(1,"Alarm Hour: %u\n", data.alarmhour); - upsdebugx(1,"Alarm Minute: %u\n", data.alarmminute); - upsdebugx(1,"Alarm Second: %u\n", data.alarmsecond); - upsdebugx(1,"End Marker: %u\n", data.end_marker); + upsdebugx(1,""); + upsdebugx(1,"220V In: %s", data.s_220V_in ? "true" : "false"); + upsdebugx(1,"220V Out: %s", data.s_220V_out ? "true" : "false"); + upsdebugx(1,"Sealed Battery: %s", data.s_sealed_battery ? "true" : "false"); + upsdebugx(1,"Show Out Tension: %s", data.s_show_out_tension ? "true" : "false"); + upsdebugx(1,"Show Temperature: %s", data.s_show_temperature ? "true" : "false"); + upsdebugx(1,"Show Charger Current: %s", data.s_show_charger_current ? "true" : "false"); + upsdebugx(1,"Charger Current: %u", data.chargercurrent); + upsdebugx(1,"Checksum: %u", data.checksum); + upsdebugx(1,"Checksum Calc: %u", data.checksum_calc); + upsdebugx(1,"Checksum OK: %s", data.checksum_ok ? "true" : "false"); + upsdebugx(1,"Serial: %s", data.serial); + upsdebugx(1,"Year: %u", data.year); + upsdebugx(1,"Month: %u", data.month); + upsdebugx(1,"Weekday: %u", data.wday); + upsdebugx(1,"Hour: %u", data.hour); + upsdebugx(1,"Minute: %u", data.minute); + upsdebugx(1,"Second: %u", data.second); + upsdebugx(1,"Alarm Year: %u", data.alarmyear); + upsdebugx(1,"Alarm Month: %u", data.alarmmonth); + upsdebugx(1,"Alarm Weekday: %u", data.alarmwday); + upsdebugx(1,"Alarm Day: %u", data.alarmday); + upsdebugx(1,"Alarm Hour: %u", data.alarmhour); + upsdebugx(1,"Alarm Minute: %u", data.alarmminute); + upsdebugx(1,"Alarm Second: %u", data.alarmsecond); + upsdebugx(1,"End Marker: %u", data.end_marker); } void print_pkt_data(pkt_data data) { - upsdebugx(1,"Header: %u\n", data.header); - upsdebugx(1,"Length: %u\n", data.length); - upsdebugx(1,"Packet Type: %c\n", data.packet_type); - upsdebugx(1,"Vacin RMS High: %u\n", data.vacinrms_high); - upsdebugx(1,"Vacin RMS Low: %u\n", data.vacinrms_low); - upsdebugx(1,"Vacin RMS: %f\n", data.vacinrms); - upsdebugx(1,"VDC Med High: %u\n", data.vdcmed_high); - upsdebugx(1,"VDC Med Low: %u\n", data.vdcmed_low); - upsdebugx(1,"VDC Med: %f\n", data.vdcmed); - upsdebugx(1,"VDC Med Real: %f\n", data.vdcmed_real); - upsdebugx(1,"Pot RMS: %u\n", data.potrms); - upsdebugx(1,"Vacin RMS Min High: %u\n", data.vacinrmsmin_high); - upsdebugx(1,"Vacin RMS Min Low: %u\n", data.vacinrmsmin_low); - upsdebugx(1,"Vacin RMS Min: %f\n", data.vacinrmsmin); - upsdebugx(1,"Vacin RMS Max High: %u\n", data.vacinrmsmax_high); - upsdebugx(1,"Vacin RMS Max Low: %u\n", data.vacinrmsmax_low); - upsdebugx(1,"Vacin RMS Max: %f\n", data.vacinrmsmax); - upsdebugx(1,"Vac Out RMS High: %u\n", data.vacoutrms_high); - upsdebugx(1,"Vac Out RMS Low: %u\n", data.vacoutrms_low); - upsdebugx(1,"Vac Out RMS: %f\n", data.vacoutrms); - upsdebugx(1,"Temp Med High: %u\n", data.tempmed_high); - upsdebugx(1,"Temp Med Low: %u\n", data.tempmed_low); - upsdebugx(1,"Temp Med: %f\n", data.tempmed); - upsdebugx(1,"Temp Med Real: %f\n", data.tempmed_real); - upsdebugx(1,"Icar Reg RMS: %u\n", data.icarregrms); - upsdebugx(1,"Icar Reg RMS Real: %u\n", data.icarregrms_real); - upsdebugx(1,"Battery Tension: %f\n", data.battery_tension); - upsdebugx(1,"Perc Output: %u\n", data.perc_output); - upsdebugx(1,"Status Value: %u\n", data.statusval); + upsdebugx(1,"Header: %u", data.header); + upsdebugx(1,"Length: %u", data.length); + upsdebugx(1,"Packet Type: %c", data.packet_type); + upsdebugx(1,"Vacin RMS High: %u", data.vacinrms_high); + upsdebugx(1,"Vacin RMS Low: %u", data.vacinrms_low); + upsdebugx(1,"Vacin RMS: %f", data.vacinrms); + upsdebugx(1,"VDC Med High: %u", data.vdcmed_high); + upsdebugx(1,"VDC Med Low: %u", data.vdcmed_low); + upsdebugx(1,"VDC Med: %f", data.vdcmed); + upsdebugx(1,"VDC Med Real: %f", data.vdcmed_real); + upsdebugx(1,"Pot RMS: %u", data.potrms); + upsdebugx(1,"Vacin RMS Min High: %u", data.vacinrmsmin_high); + upsdebugx(1,"Vacin RMS Min Low: %u", data.vacinrmsmin_low); + upsdebugx(1,"Vacin RMS Min: %f", data.vacinrmsmin); + upsdebugx(1,"Vacin RMS Max High: %u", data.vacinrmsmax_high); + upsdebugx(1,"Vacin RMS Max Low: %u", data.vacinrmsmax_low); + upsdebugx(1,"Vacin RMS Max: %f", data.vacinrmsmax); + upsdebugx(1,"Vac Out RMS High: %u", data.vacoutrms_high); + upsdebugx(1,"Vac Out RMS Low: %u", data.vacoutrms_low); + upsdebugx(1,"Vac Out RMS: %f", data.vacoutrms); + upsdebugx(1,"Temp Med High: %u", data.tempmed_high); + upsdebugx(1,"Temp Med Low: %u", data.tempmed_low); + upsdebugx(1,"Temp Med: %f", data.tempmed); + upsdebugx(1,"Temp Med Real: %f", data.tempmed_real); + upsdebugx(1,"Icar Reg RMS: %u", data.icarregrms); + upsdebugx(1,"Icar Reg RMS Real: %u", data.icarregrms_real); + upsdebugx(1,"Battery Tension: %f", data.battery_tension); + upsdebugx(1,"Perc Output: %u", data.perc_output); + upsdebugx(1,"Status Value: %u", data.statusval); upsdebugx(1,"Status: "); for (int i = 0; i < 8; i++) { upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); upsdebugx(1,"status %d --> %u ", i, data.status[i]); } - upsdebugx(1,"\n"); - upsdebugx(1,"Nominal Tension: %u\n", data.nominaltension); - upsdebugx(1,"Time Remain: %f\n", data.timeremain); - upsdebugx(1,"Battery Mode: %s\n", data.s_battery_mode ? "true" : "false"); - upsdebugx(1,"Battery Low: %s\n", data.s_battery_low ? "true" : "false"); - upsdebugx(1,"Network Failure: %s\n", data.s_network_failure ? "true" : "false"); - upsdebugx(1,"Fast Network Failure: %s\n", data.s_fast_network_failure ? "true" : "false"); - upsdebugx(1,"220 In: %s\n", data.s_220_in ? "true" : "false"); - upsdebugx(1,"220 Out: %s\n", data.s_220_out ? "true" : "false"); - upsdebugx(1,"Bypass On: %s\n", data.s_bypass_on ? "true" : "false"); - upsdebugx(1,"Charger On: %s\n", data.s_charger_on ? "true" : "false"); - upsdebugx(1,"Checksum: %u\n", data.checksum); - upsdebugx(1,"Checksum OK: %s\n", data.checksum_ok ? "true" : "false"); - upsdebugx(1,"End Marker: %u\n", data.end_marker); + upsdebugx(1,""); + upsdebugx(1,"Nominal Tension: %u", data.nominaltension); + upsdebugx(1,"Time Remain: %f", data.timeremain); + upsdebugx(1,"Battery Mode: %s", data.s_battery_mode ? "true" : "false"); + upsdebugx(1,"Battery Low: %s", data.s_battery_low ? "true" : "false"); + upsdebugx(1,"Network Failure: %s", data.s_network_failure ? "true" : "false"); + upsdebugx(1,"Fast Network Failure: %s", data.s_fast_network_failure ? "true" : "false"); + upsdebugx(1,"220 In: %s", data.s_220_in ? "true" : "false"); + upsdebugx(1,"220 Out: %s", data.s_220_out ? "true" : "false"); + upsdebugx(1,"Bypass On: %s", data.s_bypass_on ? "true" : "false"); + upsdebugx(1,"Charger On: %s", data.s_charger_on ? "true" : "false"); + upsdebugx(1,"Checksum: %u", data.checksum); + upsdebugx(1,"Checksum Calc: %u", data.checksum_calc); + upsdebugx(1,"Checksum OK: %s", data.checksum_ok ? "true" : "false"); + upsdebugx(1,"End Marker: %u", data.end_marker); } int openfd(const char * porta, int BAUDRATE) { @@ -511,7 +517,21 @@ int openfd(const char * porta, int BAUDRATE) { i++; } // if done is 0, no one speed has selected, then use default - done = DEFAULTBAUD; + if (done == 0) { + while ((i < NUM_BAUD_RATES) && (done == 0)) { + if (baud_rates[i].speed == DEFAULTBAUD) { + done = baud_rates[i].rate; + upsdebugx(1,"Baud selecionado: %d -- %s\r\n",baud_rates[i].speed,baud_rates[i].description); + } + i++; + } + } + if (done == 0) { + upsdebugx(1,"Baud rate not found, using default %d",DEFAULTBAUD); + done = B2400; + } + + tty.c_cflag &= ~PARENB; // Disable Parity tty.c_cflag &= ~CSTOPB; // 1 stop bit @@ -548,7 +568,7 @@ int openfd(const char * porta, int BAUDRATE) { return fd; } -unsigned char calcular_checksum(unsigned char *pacote, int inicio, int fim) { +unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { int soma = 0; for (int i = inicio; i <= fim; i++) { soma += pacote[i]; @@ -617,6 +637,7 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco false, // s_bypass_on false, // s_charger_on 0, // checksum + 0, // checksum_calc false, // checksum_ok 0xFE // end_marker }; @@ -664,7 +685,8 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco pktdata.s_charger_on = (bool)pktdata.status[0]; // Position 18 mean status, but I won't discover what's it pktdata.checksum = datapacket[19]; - checksum = calcular_checksum(datapacket,1,18); + checksum = calculate_checksum(datapacket,1,18); + pktdata.checksum_calc = checksum; if (pktdata.checksum == checksum) pktdata.checksum_ok = true; // Then, the calculations to obtain some useful information @@ -720,6 +742,7 @@ pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { false, // s_show_charger_current 0, // chargercurrent 0, // checksum + 0, // checksum_calc false, // checksum_ok "----------------", // serial 0, // year @@ -769,7 +792,7 @@ pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { pkthwinfo.s_show_temperature = (bool)pkthwinfo.status[4]; pkthwinfo.s_show_charger_current = (bool)pkthwinfo.status[5]; pkthwinfo.chargercurrent = (int)datapacket[15]; - if (pkthwinfo.size > 17) { + if (pkthwinfo.size > 18) { for (i = 0; i < 16; i++) pkthwinfo.serial[i] = datapacket[16 + i]; pkthwinfo.year = datapacket[32]; @@ -785,17 +808,18 @@ pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { pkthwinfo.alarmminute = datapacket[42]; pkthwinfo.alarmsecond = datapacket[43]; pkthwinfo.checksum = datapacket[48]; - checksum = calcular_checksum(datapacket,1,47); + checksum = calculate_checksum(datapacket,1,47); } // end if else { pkthwinfo.checksum = datapacket[16]; - checksum = calcular_checksum(datapacket,1,15); + checksum = calculate_checksum(datapacket,1,15); } + pkthwinfo.checksum_calc = checksum; if (pkthwinfo.checksum == checksum) pkthwinfo.checksum_ok = true; print_pkt_hwinfo(pkthwinfo); - //pdatapacket(datapacket,size); + pdatapacket(datapacket,size); return pkthwinfo; } @@ -1826,109 +1850,111 @@ void upsdrv_updateinfo(void) { dstate_setinfo("battery.charger.status","%s","RESTING"); } // Now, creating a structure called NHS, - dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); - dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); - dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); - dstate_setinfo("nhs.hw.model", "%u", lastpkthwinfo.model); - dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); - dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); - dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); + dstate_setinfo("nhs.lastpkthw.header", "%u", lastpkthwinfo.header); + dstate_setinfo("nhs.lastpkthw.size", "%u", lastpkthwinfo.size); + dstate_setinfo("nhs.lastpkthw.type", "%c", lastpkthwinfo.type); + dstate_setinfo("nhs.lastpkthw.model", "%u", lastpkthwinfo.model); + dstate_setinfo("nhs.lastpkthw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); + dstate_setinfo("nhs.lastpkthw.softwareversion", "%u", lastpkthwinfo.softwareversion); + dstate_setinfo("nhs.lastpkthw.configuration", "%u", lastpkthwinfo.configuration); for (int i = 0; i < 5; i++) { // Reusing variable - sprintf(alarm,"nhs.hw.configuration_array_p%d",i); + sprintf(alarm,"nhs.lastpkthw.configuration_array_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); } - dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); - dstate_setinfo("nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); - dstate_setinfo("nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); - dstate_setinfo("nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); - dstate_setinfo("nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); - dstate_setinfo("nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); - dstate_setinfo("nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); - dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); - dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); - dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); + dstate_setinfo("nhs.lastpkthw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.numbatteries", "%u", lastpkthwinfo.numbatteries); + dstate_setinfo("nhs.lastpkthw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); + dstate_setinfo("nhs.lastpkthw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); + dstate_setinfo("nhs.lastpkthw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); + dstate_setinfo("nhs.lastpkthw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); + dstate_setinfo("nhs.lastpkthw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); + dstate_setinfo("nhs.lastpkthw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); + dstate_setinfo("nhs.lastpkthw.statusval", "%u", lastpkthwinfo.statusval); for (int i = 0; i < 6; i++) { // Reusing variable - sprintf(alarm,"nhs.hw.status_p%d",i); + sprintf(alarm,"nhs.lastpkthw.status_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); } - dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); - dstate_setinfo("nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); - dstate_setinfo("nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); - dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); - dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); - dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); - dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); - dstate_setinfo("nhs.hw.month", "%u", lastpkthwinfo.month); - dstate_setinfo("nhs.hw.wday", "%u", lastpkthwinfo.wday); - dstate_setinfo("nhs.hw.hour", "%u", lastpkthwinfo.hour); - dstate_setinfo("nhs.hw.minute", "%u", lastpkthwinfo.minute); - dstate_setinfo("nhs.hw.second", "%u", lastpkthwinfo.second); - dstate_setinfo("nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); - dstate_setinfo("nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); - dstate_setinfo("nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); - dstate_setinfo("nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); - dstate_setinfo("nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); - dstate_setinfo("nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); - dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); - dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); + dstate_setinfo("nhs.lastpkthw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); + dstate_setinfo("nhs.lastpkthw.checksum", "%u", lastpkthwinfo.checksum); + dstate_setinfo("nhs.lastpkthw.checksum_calculated", "%u", lastpkthwinfo.checksum_calc); + dstate_setinfo("nhs.lastpkthw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.lastpkthw.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("nhs.lastpkthw.year", "%u", lastpkthwinfo.year); + dstate_setinfo("nhs.lastpkthw.month", "%u", lastpkthwinfo.month); + dstate_setinfo("nhs.lastpkthw.wday", "%u", lastpkthwinfo.wday); + dstate_setinfo("nhs.lastpkthw.hour", "%u", lastpkthwinfo.hour); + dstate_setinfo("nhs.lastpkthw.minute", "%u", lastpkthwinfo.minute); + dstate_setinfo("nhs.lastpkthw.second", "%u", lastpkthwinfo.second); + dstate_setinfo("nhs.lastpkthw.alarmyear", "%u", lastpkthwinfo.alarmyear); + dstate_setinfo("nhs.lastpkthw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); + dstate_setinfo("nhs.lastpkthw.alarmwday", "%u", lastpkthwinfo.alarmwday); + dstate_setinfo("nhs.lastpkthw.alarmday", "%u", lastpkthwinfo.alarmday); + dstate_setinfo("nhs.lastpkthw.alarmhour", "%u", lastpkthwinfo.alarmhour); + dstate_setinfo("nhs.lastpkthw.alarmminute", "%u", lastpkthwinfo.alarmminute); + dstate_setinfo("nhs.lastpkthw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); + dstate_setinfo("nhs.lastpkthw.end_marker", "%u", lastpkthwinfo.end_marker); // Data packet - dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); - dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); - dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); - dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); - dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); - dstate_setinfo("nhs.data.vacinrms", "%.2f", lastpktdata.vacinrms); - dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); - dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); - dstate_setinfo("nhs.data.vdcmed", "%.2f", lastpktdata.vdcmed); - dstate_setinfo("nhs.data.vdcmed_real", "%.2f", lastpktdata.vdcmed_real); - dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); - dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); - dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); - dstate_setinfo("nhs.data.vacinrmsmin", "%.2f", lastpktdata.vacinrmsmin); - dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); - dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); - dstate_setinfo("nhs.data.vacinrmsmax", "%.2f", lastpktdata.vacinrmsmax); - dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); - dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); - dstate_setinfo("nhs.data.vacoutrms", "%.2f", lastpktdata.vacoutrms); - dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); - dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); - dstate_setinfo("nhs.data.tempmed", "%.2f", lastpktdata.tempmed); - dstate_setinfo("nhs.data.tempmed_real", "%.2f", lastpktdata.tempmed_real); - dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); - dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); - dstate_setinfo("nhs.data.battery_tension", "%.2f", lastpktdata.battery_tension); - dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); - dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); + dstate_setinfo("nhs.lastpktdata.header", "%u", lastpktdata.header); + dstate_setinfo("nhs.lastpktdata.length", "%u", lastpktdata.length); + dstate_setinfo("nhs.lastpktdata.packet_type", "%c", lastpktdata.packet_type); + dstate_setinfo("nhs.lastpktdata.vacinrms_high", "%u", lastpktdata.vacinrms_high); + dstate_setinfo("nhs.lastpktdata.vacinrms_low", "%u", lastpktdata.vacinrms_low); + dstate_setinfo("nhs.lastpktdata.vacinrms", "%.2f", lastpktdata.vacinrms); + dstate_setinfo("nhs.lastpktdata.vdcmed_high", "%u", lastpktdata.vdcmed_high); + dstate_setinfo("nhs.lastpktdata.vdcmed_low", "%u", lastpktdata.vdcmed_low); + dstate_setinfo("nhs.lastpktdata.vdcmed", "%.2f", lastpktdata.vdcmed); + dstate_setinfo("nhs.lastpktdata.vdcmed_real", "%.2f", lastpktdata.vdcmed_real); + dstate_setinfo("nhs.lastpktdata.potrms", "%u", lastpktdata.potrms); + dstate_setinfo("nhs.lastpktdata.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); + dstate_setinfo("nhs.lastpktdata.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); + dstate_setinfo("nhs.lastpktdata.vacinrmsmin", "%.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("nhs.lastpktdata.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); + dstate_setinfo("nhs.lastpktdata.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); + dstate_setinfo("nhs.lastpktdata.vacinrmsmax", "%.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("nhs.lastpktdata.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); + dstate_setinfo("nhs.lastpktdata.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); + dstate_setinfo("nhs.lastpktdata.vacoutrms", "%.2f", lastpktdata.vacoutrms); + dstate_setinfo("nhs.lastpktdata.tempmed_high", "%u", lastpktdata.tempmed_high); + dstate_setinfo("nhs.lastpktdata.tempmed_low", "%u", lastpktdata.tempmed_low); + dstate_setinfo("nhs.lastpktdata.tempmed", "%.2f", lastpktdata.tempmed); + dstate_setinfo("nhs.lastpktdata.tempmed_real", "%.2f", lastpktdata.tempmed_real); + dstate_setinfo("nhs.lastpktdata.icarregrms", "%u", lastpktdata.icarregrms); + dstate_setinfo("nhs.lastpktdata.icarregrms_real", "%u", lastpktdata.icarregrms_real); + dstate_setinfo("nhs.lastpktdata.battery_tension", "%.2f", lastpktdata.battery_tension); + dstate_setinfo("nhs.lastpktdata.perc_output", "%u", lastpktdata.perc_output); + dstate_setinfo("nhs.lastpktdata.statusval", "%u", lastpktdata.statusval); for (int i = 0; i < 8; i++) { // Reusing variable - sprintf(alarm,"nhs.data.status_p%d",i); + sprintf(alarm,"nhs.lastpktdata.status_p%d",i); dstate_setinfo(alarm, "%u", lastpktdata.status[i]); } - dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); - dstate_setinfo("nhs.data.timeremain", "%.2f", lastpktdata.timeremain); - dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); - dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); - dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); - dstate_setinfo("nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); - dstate_setinfo("nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); - dstate_setinfo("nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); - dstate_setinfo("nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); - dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); - dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); - dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); + dstate_setinfo("nhs.lastpktdata.nominaltension", "%u", lastpktdata.nominaltension); + dstate_setinfo("nhs.lastpktdata.timeremain", "%.2f", lastpktdata.timeremain); + dstate_setinfo("nhs.lastpktdata.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.checksum", "%u", lastpktdata.checksum); + dstate_setinfo("nhs.lastpktdata.checksum_calculated", "%u", lastpktdata.checksum_calc); + dstate_setinfo("nhs.lastpktdata.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.lastpktdata.end_marker", "%u", lastpktdata.end_marker); dstate_setinfo("nhs.param.va", "%u", va); dstate_setinfo("nhs.param.pf", "%f", pf); dstate_setinfo("nhs.param.ah", "%u", ah); @@ -1951,20 +1977,25 @@ void upsdrv_updateinfo(void) { upsdebugx(1,"pkt_hwinfo loss -- Requesting\r\n"); // if size == 0, packet maybe not initizated, then send a initialization packet to obtain data // Send two times the extended initialization string, but, on fail, try randomly send extended or normal - if (send_extended < 2) { + if (send_extended < 6) { + upsdebugx(1,"Sending extended initialization packet. Try %d",send_extended+1); bwritten = write_serial_int(serial_fd,string_initialization_long,9); send_extended++; } // end if else { // randomly send - if (rand() % 2 == 0) + if (rand() % 2 == 0) { + upsdebugx(1,"Sending long initialization packet"); bwritten = write_serial_int(serial_fd,string_initialization_long,9); - else + } // end if + else { + upsdebugx(1,"Sending short initialization packet"); bwritten = write_serial_int(serial_fd,string_initialization_short,9); + } // end else } // end else if (bwritten < 0) { + upsdebugx(1,"Problem to write data to %s",porta); if (bwritten == -1) { - upsdebugx(1,"Problem to write data to %s",DEFAULTPORT); upsdebugx(1,"\r\nData problem\r\n"); } if (bwritten == -2) { @@ -1973,9 +2004,15 @@ void upsdrv_updateinfo(void) { close(serial_fd); serial_fd = -1; } // end if - else - // some sleep to help + else { + if (checktime > max_checktime) + checktime = max_checktime; + else { + upsdebugx(1,"Increase checktime to %d",checktime + 10000); + checktime = checktime + 10000; + } usleep(checktime); + } // end else } // end if } // end else upsdebugx(1,"End updateinfo()"); From f609782d5e2db3b8c4d4e5665fc5c2d727172895 Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Tue, 26 Nov 2024 11:44:12 -0300 Subject: [PATCH 03/60] Some small fixes in get_bit_in_position() --- drivers/nhs-nut.c | 190 +++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 97 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 4b5d1cca1a..f07e4e0be2 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -346,22 +346,20 @@ static pkt_data lastpktdata = { 0xFE // end_marker }; -int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorder) { +int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorder) { unsigned char *byte_ptr = (unsigned char *)ptr; int retval = -2; + size_t byte_index; + size_t bit_index; if (bit_position >= size * 8) { return -3; // Invalid Position } - size_t byte_index = bit_position / 8; - size_t bit_index = bit_position % 8; - - retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 1 : 0; if (invertorder == 0) retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 1 : 0; else - retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 0 ? 1 : 1; + retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 0 : 1; return retval; } @@ -1850,111 +1848,109 @@ void upsdrv_updateinfo(void) { dstate_setinfo("battery.charger.status","%s","RESTING"); } // Now, creating a structure called NHS, - dstate_setinfo("nhs.lastpkthw.header", "%u", lastpkthwinfo.header); - dstate_setinfo("nhs.lastpkthw.size", "%u", lastpkthwinfo.size); - dstate_setinfo("nhs.lastpkthw.type", "%c", lastpkthwinfo.type); - dstate_setinfo("nhs.lastpkthw.model", "%u", lastpkthwinfo.model); - dstate_setinfo("nhs.lastpkthw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); - dstate_setinfo("nhs.lastpkthw.softwareversion", "%u", lastpkthwinfo.softwareversion); - dstate_setinfo("nhs.lastpkthw.configuration", "%u", lastpkthwinfo.configuration); + dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); + dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); + dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); + dstate_setinfo("nhs.hw.model", "%u", lastpkthwinfo.model); + dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); + dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); + dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); for (int i = 0; i < 5; i++) { // Reusing variable - sprintf(alarm,"nhs.lastpkthw.configuration_array_p%d",i); + sprintf(alarm,"nhs.hw.configuration_array_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); } - dstate_setinfo("nhs.lastpkthw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.numbatteries", "%u", lastpkthwinfo.numbatteries); - dstate_setinfo("nhs.lastpkthw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); - dstate_setinfo("nhs.lastpkthw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); - dstate_setinfo("nhs.lastpkthw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); - dstate_setinfo("nhs.lastpkthw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); - dstate_setinfo("nhs.lastpkthw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); - dstate_setinfo("nhs.lastpkthw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); - dstate_setinfo("nhs.lastpkthw.statusval", "%u", lastpkthwinfo.statusval); + dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); + dstate_setinfo("nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); + dstate_setinfo("nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); + dstate_setinfo("nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); + dstate_setinfo("nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); + dstate_setinfo("nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); + dstate_setinfo("nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); + dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); + dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); + dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); for (int i = 0; i < 6; i++) { // Reusing variable - sprintf(alarm,"nhs.lastpkthw.status_p%d",i); + sprintf(alarm,"nhs.hw.status_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); } - dstate_setinfo("nhs.lastpkthw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); - dstate_setinfo("nhs.lastpkthw.checksum", "%u", lastpkthwinfo.checksum); - dstate_setinfo("nhs.lastpkthw.checksum_calculated", "%u", lastpkthwinfo.checksum_calc); - dstate_setinfo("nhs.lastpkthw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.lastpkthw.serial", "%s", lastpkthwinfo.serial); - dstate_setinfo("nhs.lastpkthw.year", "%u", lastpkthwinfo.year); - dstate_setinfo("nhs.lastpkthw.month", "%u", lastpkthwinfo.month); - dstate_setinfo("nhs.lastpkthw.wday", "%u", lastpkthwinfo.wday); - dstate_setinfo("nhs.lastpkthw.hour", "%u", lastpkthwinfo.hour); - dstate_setinfo("nhs.lastpkthw.minute", "%u", lastpkthwinfo.minute); - dstate_setinfo("nhs.lastpkthw.second", "%u", lastpkthwinfo.second); - dstate_setinfo("nhs.lastpkthw.alarmyear", "%u", lastpkthwinfo.alarmyear); - dstate_setinfo("nhs.lastpkthw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); - dstate_setinfo("nhs.lastpkthw.alarmwday", "%u", lastpkthwinfo.alarmwday); - dstate_setinfo("nhs.lastpkthw.alarmday", "%u", lastpkthwinfo.alarmday); - dstate_setinfo("nhs.lastpkthw.alarmhour", "%u", lastpkthwinfo.alarmhour); - dstate_setinfo("nhs.lastpkthw.alarmminute", "%u", lastpkthwinfo.alarmminute); - dstate_setinfo("nhs.lastpkthw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); - dstate_setinfo("nhs.lastpkthw.end_marker", "%u", lastpkthwinfo.end_marker); + dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); + dstate_setinfo("nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); + dstate_setinfo("nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); + dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); + dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); + dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); + dstate_setinfo("nhs.hw.month", "%u", lastpkthwinfo.month); + dstate_setinfo("nhs.hw.wday", "%u", lastpkthwinfo.wday); + dstate_setinfo("nhs.hw.hour", "%u", lastpkthwinfo.hour); + dstate_setinfo("nhs.hw.minute", "%u", lastpkthwinfo.minute); + dstate_setinfo("nhs.hw.second", "%u", lastpkthwinfo.second); + dstate_setinfo("nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); + dstate_setinfo("nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); + dstate_setinfo("nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); + dstate_setinfo("nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); + dstate_setinfo("nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); + dstate_setinfo("nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); + dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); + dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); // Data packet - dstate_setinfo("nhs.lastpktdata.header", "%u", lastpktdata.header); - dstate_setinfo("nhs.lastpktdata.length", "%u", lastpktdata.length); - dstate_setinfo("nhs.lastpktdata.packet_type", "%c", lastpktdata.packet_type); - dstate_setinfo("nhs.lastpktdata.vacinrms_high", "%u", lastpktdata.vacinrms_high); - dstate_setinfo("nhs.lastpktdata.vacinrms_low", "%u", lastpktdata.vacinrms_low); - dstate_setinfo("nhs.lastpktdata.vacinrms", "%.2f", lastpktdata.vacinrms); - dstate_setinfo("nhs.lastpktdata.vdcmed_high", "%u", lastpktdata.vdcmed_high); - dstate_setinfo("nhs.lastpktdata.vdcmed_low", "%u", lastpktdata.vdcmed_low); - dstate_setinfo("nhs.lastpktdata.vdcmed", "%.2f", lastpktdata.vdcmed); - dstate_setinfo("nhs.lastpktdata.vdcmed_real", "%.2f", lastpktdata.vdcmed_real); - dstate_setinfo("nhs.lastpktdata.potrms", "%u", lastpktdata.potrms); - dstate_setinfo("nhs.lastpktdata.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); - dstate_setinfo("nhs.lastpktdata.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); - dstate_setinfo("nhs.lastpktdata.vacinrmsmin", "%.2f", lastpktdata.vacinrmsmin); - dstate_setinfo("nhs.lastpktdata.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); - dstate_setinfo("nhs.lastpktdata.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); - dstate_setinfo("nhs.lastpktdata.vacinrmsmax", "%.2f", lastpktdata.vacinrmsmax); - dstate_setinfo("nhs.lastpktdata.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); - dstate_setinfo("nhs.lastpktdata.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); - dstate_setinfo("nhs.lastpktdata.vacoutrms", "%.2f", lastpktdata.vacoutrms); - dstate_setinfo("nhs.lastpktdata.tempmed_high", "%u", lastpktdata.tempmed_high); - dstate_setinfo("nhs.lastpktdata.tempmed_low", "%u", lastpktdata.tempmed_low); - dstate_setinfo("nhs.lastpktdata.tempmed", "%.2f", lastpktdata.tempmed); - dstate_setinfo("nhs.lastpktdata.tempmed_real", "%.2f", lastpktdata.tempmed_real); - dstate_setinfo("nhs.lastpktdata.icarregrms", "%u", lastpktdata.icarregrms); - dstate_setinfo("nhs.lastpktdata.icarregrms_real", "%u", lastpktdata.icarregrms_real); - dstate_setinfo("nhs.lastpktdata.battery_tension", "%.2f", lastpktdata.battery_tension); - dstate_setinfo("nhs.lastpktdata.perc_output", "%u", lastpktdata.perc_output); - dstate_setinfo("nhs.lastpktdata.statusval", "%u", lastpktdata.statusval); + dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); + dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); + dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); + dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); + dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); + dstate_setinfo("nhs.data.vacinrms", "%.2f", lastpktdata.vacinrms); + dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); + dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); + dstate_setinfo("nhs.data.vdcmed", "%.2f", lastpktdata.vdcmed); + dstate_setinfo("nhs.data.vdcmed_real", "%.2f", lastpktdata.vdcmed_real); + dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); + dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); + dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); + dstate_setinfo("nhs.data.vacinrmsmin", "%.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); + dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); + dstate_setinfo("nhs.data.vacinrmsmax", "%.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); + dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); + dstate_setinfo("nhs.data.vacoutrms", "%.2f", lastpktdata.vacoutrms); + dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); + dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); + dstate_setinfo("nhs.data.tempmed", "%.2f", lastpktdata.tempmed); + dstate_setinfo("nhs.data.tempmed_real", "%.2f", lastpktdata.tempmed_real); + dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); + dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); + dstate_setinfo("nhs.data.battery_tension", "%.2f", lastpktdata.battery_tension); + dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); + dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); for (int i = 0; i < 8; i++) { // Reusing variable - sprintf(alarm,"nhs.lastpktdata.status_p%d",i); + sprintf(alarm,"nhs.data.status_p%d",i); dstate_setinfo(alarm, "%u", lastpktdata.status[i]); } - dstate_setinfo("nhs.lastpktdata.nominaltension", "%u", lastpktdata.nominaltension); - dstate_setinfo("nhs.lastpktdata.timeremain", "%.2f", lastpktdata.timeremain); - dstate_setinfo("nhs.lastpktdata.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.checksum", "%u", lastpktdata.checksum); - dstate_setinfo("nhs.lastpktdata.checksum_calculated", "%u", lastpktdata.checksum_calc); - dstate_setinfo("nhs.lastpktdata.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.lastpktdata.end_marker", "%u", lastpktdata.end_marker); + dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); + dstate_setinfo("nhs.data.timeremain", "%.2f", lastpktdata.timeremain); + dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); + dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); + dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); + dstate_setinfo("nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); + dstate_setinfo("nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); + dstate_setinfo("nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); + dstate_setinfo("nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); + dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); + dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); + dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); dstate_setinfo("nhs.param.va", "%u", va); dstate_setinfo("nhs.param.pf", "%f", pf); dstate_setinfo("nhs.param.ah", "%u", ah); From a46b4a1236ca196941c28da9ef2a4a6f16985f08 Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Tue, 26 Nov 2024 12:55:36 -0300 Subject: [PATCH 04/60] Function have some errors and again need to re-commit code. Signed-off-by: Lucas Willian Bocchi lucas@lucas.inf.br --- drivers/nhs-nut.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index f07e4e0be2..66646cfe6f 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -349,8 +349,8 @@ static pkt_data lastpktdata = { int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorder) { unsigned char *byte_ptr = (unsigned char *)ptr; int retval = -2; - size_t byte_index; - size_t bit_index; + size_t byte_index = bit_position / 8; + size_t bit_index = bit_position % 8; if (bit_position >= size * 8) { return -3; // Invalid Position @@ -1606,7 +1606,7 @@ void upsdrv_updateinfo(void) { float pf = 0; int bcharge = 0; int min_input_power = 0; - + double tempodecorrido = 0.0; upsinfo ups; upsdebugx(1,"Start updateinfo()"); @@ -1633,7 +1633,6 @@ void upsdrv_updateinfo(void) { datapacket_index++; if (chr == 0xFE) { // DataPacket upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); - double tempodecorrido = 0.0; time_t now = time(NULL); if (lastdp != 0) { tempodecorrido = difftime(now, lastdp); @@ -2004,8 +2003,8 @@ void upsdrv_updateinfo(void) { if (checktime > max_checktime) checktime = max_checktime; else { - upsdebugx(1,"Increase checktime to %d",checktime + 10000); - checktime = checktime + 10000; + upsdebugx(1,"Increase checktime to %d",checktime + 100000); + checktime = checktime + 100000; } usleep(checktime); } // end else From 18049ec5bbdc89b847487e674c0786505c48d1b1 Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Tue, 26 Nov 2024 20:16:57 -0300 Subject: [PATCH 05/60] Some fixes in 1) Miscalculations of battery voltage and amps 2) Miscalculations in battery capacity 3) Miscalculations in time remaining Signed-off-by: Lucas Willian Bocchi lucas@lucas.inf.br --- drivers/nhs-nut.c | 186 +++++++++++++++++++++++++++++----------------- 1 file changed, 116 insertions(+), 70 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 66646cfe6f..e827f4fc4a 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -73,6 +73,7 @@ #define DEFAULTPF 0.9 #define DEFAULLTPERC 2 #define DATAPACKETSIZE 100 +#define DEFAULTBATV 12 #define DRIVER_NAME "NHS Nobreak Drivers" #define DRIVER_VERSION "0.1" #define MANUFACTURER "NHS Sistemas Eletronicos LTDA" @@ -431,28 +432,28 @@ void print_pkt_data(pkt_data data) { upsdebugx(1,"Packet Type: %c", data.packet_type); upsdebugx(1,"Vacin RMS High: %u", data.vacinrms_high); upsdebugx(1,"Vacin RMS Low: %u", data.vacinrms_low); - upsdebugx(1,"Vacin RMS: %f", data.vacinrms); + upsdebugx(1,"Vacin RMS: %0.2f", data.vacinrms); upsdebugx(1,"VDC Med High: %u", data.vdcmed_high); upsdebugx(1,"VDC Med Low: %u", data.vdcmed_low); - upsdebugx(1,"VDC Med: %f", data.vdcmed); - upsdebugx(1,"VDC Med Real: %f", data.vdcmed_real); + upsdebugx(1,"VDC Med: %0.2f", data.vdcmed); + upsdebugx(1,"VDC Med Real: %0.2f", data.vdcmed_real); upsdebugx(1,"Pot RMS: %u", data.potrms); upsdebugx(1,"Vacin RMS Min High: %u", data.vacinrmsmin_high); upsdebugx(1,"Vacin RMS Min Low: %u", data.vacinrmsmin_low); - upsdebugx(1,"Vacin RMS Min: %f", data.vacinrmsmin); + upsdebugx(1,"Vacin RMS Min: %0.2f", data.vacinrmsmin); upsdebugx(1,"Vacin RMS Max High: %u", data.vacinrmsmax_high); upsdebugx(1,"Vacin RMS Max Low: %u", data.vacinrmsmax_low); - upsdebugx(1,"Vacin RMS Max: %f", data.vacinrmsmax); + upsdebugx(1,"Vacin RMS Max: %0.2f", data.vacinrmsmax); upsdebugx(1,"Vac Out RMS High: %u", data.vacoutrms_high); upsdebugx(1,"Vac Out RMS Low: %u", data.vacoutrms_low); - upsdebugx(1,"Vac Out RMS: %f", data.vacoutrms); + upsdebugx(1,"Vac Out RMS: %0.2f", data.vacoutrms); upsdebugx(1,"Temp Med High: %u", data.tempmed_high); upsdebugx(1,"Temp Med Low: %u", data.tempmed_low); - upsdebugx(1,"Temp Med: %f", data.tempmed); - upsdebugx(1,"Temp Med Real: %f", data.tempmed_real); + upsdebugx(1,"Temp Med: %0.2f", data.tempmed); + upsdebugx(1,"Temp Med Real: %0.2f", data.tempmed_real); upsdebugx(1,"Icar Reg RMS: %u", data.icarregrms); upsdebugx(1,"Icar Reg RMS Real: %u", data.icarregrms_real); - upsdebugx(1,"Battery Tension: %f", data.battery_tension); + upsdebugx(1,"Battery Tension: %0.2f", data.battery_tension); upsdebugx(1,"Perc Output: %u", data.perc_output); upsdebugx(1,"Status Value: %u", data.statusval); upsdebugx(1,"Status: "); @@ -462,7 +463,7 @@ void print_pkt_data(pkt_data data) { } upsdebugx(1,""); upsdebugx(1,"Nominal Tension: %u", data.nominaltension); - upsdebugx(1,"Time Remain: %f", data.timeremain); + upsdebugx(1,"Time Remain: %0.2f", data.timeremain); upsdebugx(1,"Battery Mode: %s", data.s_battery_mode ? "true" : "false"); upsdebugx(1,"Battery Low: %s", data.s_battery_low ? "true" : "false"); upsdebugx(1,"Network Failure: %s", data.s_network_failure ? "true" : "false"); @@ -510,7 +511,7 @@ int openfd(const char * porta, int BAUDRATE) { while ((i < NUM_BAUD_RATES) && (done == 0)) { if (baud_rates[i].speed == BAUDRATE) { done = baud_rates[i].rate; - upsdebugx(1,"Baud selecionado: %d -- %s\r\n",baud_rates[i].speed,baud_rates[i].description); + upsdebugx(1,"Baud selecionado: %d -- %s",baud_rates[i].speed,baud_rates[i].description); } i++; } @@ -519,7 +520,7 @@ int openfd(const char * porta, int BAUDRATE) { while ((i < NUM_BAUD_RATES) && (done == 0)) { if (baud_rates[i].speed == DEFAULTBAUD) { done = baud_rates[i].rate; - upsdebugx(1,"Baud selecionado: %d -- %s\r\n",baud_rates[i].speed,baud_rates[i].description); + upsdebugx(1,"Baud selecionado: %d -- %s",baud_rates[i].speed,baud_rates[i].description); } i++; } @@ -577,9 +578,9 @@ unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { void pdatapacket(unsigned char * datapacket,int size) { int i = 0; if (datapacket != NULL) { - upsdebugx(1,"\r\nReceived Datapacket: \r\n"); + upsdebugx(1,"Received Datapacket: "); for (i = 0; i < size; i++) { - upsdebugx(1,"\tPosition %d -- 0x%02X -- Decimal %d -- Char %c\r\n", i, datapacket[i], datapacket[i], datapacket[i]); + upsdebugx(1,"\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapacket[i], datapacket[i], datapacket[i]); } } } @@ -590,8 +591,19 @@ float createfloat(int integer, int decimal) { return atof(flt); } +unsigned int get_vbat() { + char * v = getval("vbat"); + if (v) { + return atoi(v); + } + else { + return DEFAULTBATV; + } +} + pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { int i = 0; + unsigned int vbat = 0; unsigned char checksum = 0x00; pkt_data pktdata = { 0xFF, // header @@ -694,7 +706,8 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco // if one battery cell have 12v, then the maximum out tension is numbatteries * 12v // This is the watermark to low battery // TODO: test with external battery bank to see if calculation is valid. Can generate false positive - pktdata.nominaltension = 12 * pkt_upsinfo.numbatteries; + vbat = get_vbat(); + pktdata.nominaltension = vbat * pkt_upsinfo.numbatteries; if (pktdata.nominaltension > 0) { pktdata.perc_output = (pktdata.battery_tension * 100) / pktdata.nominaltension; if (pktdata.perc_output > 100); @@ -840,7 +853,7 @@ int write_serial_int(int serial_fd, const unsigned int * data, int size) { if (serial_fd > 0) { for (i = 0; i < size; i++) { message[i] = (uint8_t)data[i]; - //upsdebugx(1,"%d %c %u %d %c %u\r\n",message[i],message[i],data[i],data[i]); + //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); } ssize_t bytes_written = write(serial_fd, message,size); if (bytes_written < 0) @@ -1584,6 +1597,14 @@ float calculate_efficiency(float vacoutrms, float vacinrms) { return (vacoutrms * vacinrms) / 100.0; } +unsigned int get_numbat() { + char * nb = getval("numbat"); + unsigned int retval = 0; + if (nb) + retval = atoi(nb); + return retval; +} + void upsdrv_updateinfo(void) { // retries to open port unsigned int retries = 3; @@ -1607,14 +1628,17 @@ void upsdrv_updateinfo(void) { int bcharge = 0; int min_input_power = 0; double tempodecorrido = 0.0; + unsigned int numbat = 0; + unsigned int vbat = 0; + float abat = 0; upsinfo ups; upsdebugx(1,"Start updateinfo()"); if ((serial_fd <= 0) && (i < retries)) { - upsdebugx(1,"Serial problem..\r\n"); + upsdebugx(1,"Serial problem.."); while (serial_fd <= 0) { serial_fd = openfd(DEFAULTPORT,2400); - upsdebugx(1,"Trying to reopen serial...\r\n"); + upsdebugx(1,"Trying to reopen serial..."); usleep(checktime); retries++; } @@ -1705,7 +1729,7 @@ void upsdrv_updateinfo(void) { else { // Check if MAINS (power) is not preset. Well, we can check pkt_data.s_network_failure too... if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { - sprintf(alarm,"UPS have power in %f value and min_input_power is %d or network is in failure. Network failure is %d",lastpktdata.vacinrms,min_input_power,lastpktdata.s_network_failure); + sprintf(alarm,"UPS have power in %0.2f value and min_input_power is %d or network is in failure. Network failure is %d",lastpktdata.vacinrms,min_input_power,lastpktdata.s_network_failure); upsdebugx(1,alarm); dstate_setinfo("ups.status","%s","DISCHRG"); } // end if @@ -1741,6 +1765,13 @@ void upsdrv_updateinfo(void) { } // end else alarm[0] = '\0'; + numbat = get_numbat(); + if (numbat == 0) + numbat = lastpkthwinfo.numbatteries; + else + upsdebugx(1,"Number of batteries is set to %d",numbat); + vbat = get_vbat(); + ah = get_ah(); // Set all alarms possible if (lastpktdata.s_battery_mode) sprintf(alarm,"%s","|UPS IN BATTERY MODE|"); @@ -1765,53 +1796,56 @@ void upsdrv_updateinfo(void) { dstate_setinfo("ups.firmware","%u",lastpkthwinfo.softwareversion); // Setting hardware version here. Not found another place to do. Feel free to correct it dstate_setinfo("ups.firmware.aux","%u",lastpkthwinfo.hardwareversion); - dstate_setinfo("ups.temperature","%f",lastpktdata.tempmed_real); + dstate_setinfo("ups.temperature","%0.2f",lastpktdata.tempmed_real); dstate_setinfo("ups.load","%u",lastpktdata.potrms); - dstate_setinfo("ups.efficiency","%f", calculate_efficiency(lastpktdata.vacoutrms, lastpktdata.vacinrms)); + dstate_setinfo("ups.efficiency","%0.2f", calculate_efficiency(lastpktdata.vacoutrms, lastpktdata.vacinrms)); va = get_va(lastpkthwinfo.model); pf = get_pf(); + // vpower is the power in Watts vpower = ((va * pf) * (lastpktdata.potrms / 100.0)); + // abat is the battery's consumption in Amperes + abat = ((vpower / lastpktdata.vdcmed_real) / numbat); if (vpower > maxpower) maxpower = vpower; if (vpower < minpower) minpower = vpower; - dstate_setinfo("ups.power","%f",vpower); + dstate_setinfo("ups.power","%0.2f",vpower); dstate_setinfo("ups.power.nominal","%u",va); - dstate_setinfo("ups.realpower","%d",(int)round((va * pf) * (lastpktdata.potrms / 100.0))); + dstate_setinfo("ups.realpower","%d",(int)round(vpower)); dstate_setinfo("ups.realpower.nominal","%d",(int)round(va * pf)); dstate_setinfo("ups.beeper.status","%d",!lastpkthwinfo.c_buzzer_disable); - dstate_setinfo("input.voltage","%f",lastpktdata.vacinrms); - dstate_setinfo("input.voltage.maximum","%f",lastpktdata.vacinrmsmin); - dstate_setinfo("input.voltage.minimum","%f",lastpktdata.vacinrmsmax); + dstate_setinfo("input.voltage","%0.2f",lastpktdata.vacinrms); + dstate_setinfo("input.voltage.maximum","%0.2f",lastpktdata.vacinrmsmin); + dstate_setinfo("input.voltage.minimum","%0.2f",lastpktdata.vacinrmsmax); vin_underv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V; vin_overv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V; perc = get_vin_perc("vin_low_warn_perc") == get_vin_perc("vin_low_crit_perc") ? 2 : 1; vin_low_warn = vin_underv + (vin_underv * ((get_vin_perc("vin_low_warn_perc") * perc) / 100.0)); - dstate_setinfo("input.voltage.low.warning","%f",calculated); + dstate_setinfo("input.voltage.low.warning","%0.2f",calculated); vin_low_crit = vin_underv + (vin_underv * (get_vin_perc("vin_low_crit_perc") / 100.0)); - dstate_setinfo("input.voltage.low.critical","%f",calculated); + dstate_setinfo("input.voltage.low.critical","%0.2f",calculated); vin_high_warn = vin_overv + (vin_overv * ((get_vin_perc("vin_high_warn_perc") * perc) / 100.0)); - dstate_setinfo("input.voltage.high.warning","%f",calculated); + dstate_setinfo("input.voltage.high.warning","%0.2f",calculated); vin_high_crit = vin_overv + (vin_overv * (get_vin_perc("vin_high_crit_perc") / 100.0)); - dstate_setinfo("input.voltage.high.critical","%f",calculated); + dstate_setinfo("input.voltage.high.critical","%0.2f",calculated); vin = lastpkthwinfo.s_220V_in ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; dstate_setinfo("input.voltage.nominal","%u",vin); dstate_setinfo("input.transfer.low","%u",lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V); dstate_setinfo("input.transfer.high","%u",lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V); - dstate_setinfo("output.voltage","%f",lastpktdata.vacoutrms); + dstate_setinfo("output.voltage","%0.2f",lastpktdata.vacoutrms); vout = lastpkthwinfo.s_220V_out ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; dstate_setinfo("output.voltage.nominal","%u",vout); - dstate_setinfo("voltage","%f",lastpktdata.vacoutrms); + dstate_setinfo("voltage","%0.2f",lastpktdata.vacoutrms); dstate_setinfo("voltage.nominal","%u",vout); - dstate_setinfo("voltage.maximum","%f",lastpktdata.vacinrmsmax); - dstate_setinfo("voltage.minimum","%f",lastpktdata.vacinrmsmin); - dstate_setinfo("voltage.low.warning","%f",vin_low_warn); - dstate_setinfo("voltage.low.critical","%f",vin_low_crit); - dstate_setinfo("voltage.high.warning","%f",vin_high_warn); - dstate_setinfo("voltage.high.critical","%f",vin_high_crit); - dstate_setinfo("power","%f",vpower); - dstate_setinfo("power.maximum","%f",maxpower); - dstate_setinfo("power.minimum","%f",minpower); + dstate_setinfo("voltage.maximum","%0.2f",lastpktdata.vacinrmsmax); + dstate_setinfo("voltage.minimum","%0.2f",lastpktdata.vacinrmsmin); + dstate_setinfo("voltage.low.warning","%0.2f",vin_low_warn); + dstate_setinfo("voltage.low.critical","%0.2f",vin_low_crit); + dstate_setinfo("voltage.high.warning","%0.2f",vin_high_warn); + dstate_setinfo("voltage.high.critical","%0.2f",vin_high_crit); + dstate_setinfo("power","%0.2f",vpower); + dstate_setinfo("power.maximum","%0.2f",maxpower); + dstate_setinfo("power.minimum","%0.2f",minpower); dstate_setinfo("power.percent","%u",lastpktdata.potrms); if (lastpktdata.potrms > maxpowerperc) maxpowerperc = lastpktdata.potrms; @@ -1819,23 +1853,29 @@ void upsdrv_updateinfo(void) { minpowerperc = lastpktdata.potrms; dstate_setinfo("power.maximum.percent","%u",maxpowerperc); dstate_setinfo("power.minimum.percent","%u",minpowerperc); - dstate_setinfo("realpower","%u",(unsigned int)round((va * pf) * (lastpktdata.potrms / 100.0))); + dstate_setinfo("realpower","%u",(unsigned int)round(vpower)); dstate_setinfo("power","%u",(unsigned int)round(va * (lastpktdata.potrms / 100.0))); bcharge = (int)round((lastpktdata.vdcmed_real * 100) / 12.0); if (bcharge > 100) bcharge = 100; dstate_setinfo("battery.charge","%d",bcharge); - dstate_setinfo("battery.voltage","%f",lastpktdata.vdcmed_real * lastpkthwinfo.numbatteries); - dstate_setinfo("battery.voltage.nominal","%u",12); - ah = get_ah(); + dstate_setinfo("battery.voltage","%0.2f",lastpktdata.vdcmed_real); + dstate_setinfo("battery.voltage.nominal","%u",vbat); dstate_setinfo("battery.capacity","%u",ah); - dstate_setinfo("battery.capacity.nominal","%f",(float)ah * pf); - dstate_setinfo("battery.current","%f",lastpktdata.vdcmed_real); - dstate_setinfo("battery.current.total","%f",(float)12 * lastpkthwinfo.numbatteries); + dstate_setinfo("battery.capacity.nominal","%0.2f",(float)ah * pf); + dstate_setinfo("battery.current","%0.2f",abat); + dstate_setinfo("battery.current.total","%0.2f",(float)abat * numbat); dstate_setinfo("battery.temperature","%u",(unsigned int)round(lastpktdata.tempmed_real)); - dstate_setinfo("battery.packs","%u",lastpkthwinfo.numbatteries); + dstate_setinfo("battery.packs","%u",numbat); // We will calculate autonomy in seconds - autonomy_secs = (lastpkthwinfo.numbatteries * lastpktdata.vdcmed_real * va * pf) / ((lastpktdata.potrms * va * pf) / 100.0) * 3600; + + // Autonomy calculation in NHS nobreaks is a rocket science. Some are one, some are other. I'll do my best to put one that works in 4 models that I have here. + // That result is IN HOURS. We need to convert it on seconds + //autonomy_secs = (int)round((ah / (vpower / lastpktdata.vdcmed_real)) * 3600); + autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; + //upsdebugx(1,"(numbat * lastpktdata.vdcmed_real * va * pf) / ((lastpktdata.potrms * va * pf) / 100.0) = (%d * %0.2f * %d * %0.2f) / ((%d * %d * %0.2f) / 100.0) --> %0.2f",numbat,lastpktdata.vdcmed_real,va,pf,lastpktdata.potrms,va,pf,autonomy_secs); + // That result is IN HOURS. We need to convert it on seconds + dstate_setinfo("battery.runtime","%u",autonomy_secs); dstate_setinfo("battery.runtime.low","%u",30); if (lastpktdata.s_charger_on) @@ -1885,6 +1925,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); + dstate_setinfo("nhs.hw.checksum_calc", "%u", lastpkthwinfo.checksum_calc); dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); @@ -1908,28 +1949,28 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); - dstate_setinfo("nhs.data.vacinrms", "%.2f", lastpktdata.vacinrms); + dstate_setinfo("nhs.data.vacinrms", "%0.2f", lastpktdata.vacinrms); dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); - dstate_setinfo("nhs.data.vdcmed", "%.2f", lastpktdata.vdcmed); - dstate_setinfo("nhs.data.vdcmed_real", "%.2f", lastpktdata.vdcmed_real); + dstate_setinfo("nhs.data.vdcmed", "%0.2f", lastpktdata.vdcmed); + dstate_setinfo("nhs.data.vdcmed_real", "%0.2f", lastpktdata.vdcmed_real); dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); - dstate_setinfo("nhs.data.vacinrmsmin", "%.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("nhs.data.vacinrmsmin", "%0.2f", lastpktdata.vacinrmsmin); dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); - dstate_setinfo("nhs.data.vacinrmsmax", "%.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("nhs.data.vacinrmsmax", "%0.2f", lastpktdata.vacinrmsmax); dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); - dstate_setinfo("nhs.data.vacoutrms", "%.2f", lastpktdata.vacoutrms); + dstate_setinfo("nhs.data.vacoutrms", "%0.2f", lastpktdata.vacoutrms); dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); - dstate_setinfo("nhs.data.tempmed", "%.2f", lastpktdata.tempmed); - dstate_setinfo("nhs.data.tempmed_real", "%.2f", lastpktdata.tempmed_real); + dstate_setinfo("nhs.data.tempmed", "%0.2f", lastpktdata.tempmed); + dstate_setinfo("nhs.data.tempmed_real", "%0.2f", lastpktdata.tempmed_real); dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); - dstate_setinfo("nhs.data.battery_tension", "%.2f", lastpktdata.battery_tension); + dstate_setinfo("nhs.data.battery_tension", "%0.2f", lastpktdata.battery_tension); dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); for (int i = 0; i < 8; i++) { @@ -1938,7 +1979,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo(alarm, "%u", lastpktdata.status[i]); } dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); - dstate_setinfo("nhs.data.timeremain", "%.2f", lastpktdata.timeremain); + dstate_setinfo("nhs.data.timeremain", "%0.2f", lastpktdata.timeremain); dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); @@ -1949,19 +1990,20 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.data.checksum_calc", "%u", lastpktdata.checksum_calc); dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); dstate_setinfo("nhs.param.va", "%u", va); - dstate_setinfo("nhs.param.pf", "%f", pf); + dstate_setinfo("nhs.param.pf", "%0.2f", pf); dstate_setinfo("nhs.param.ah", "%u", ah); - dstate_setinfo("nhs.param.vin_low_warn_perc", "%f", get_vin_perc("vin_low_warn_perc")); - dstate_setinfo("nhs.param.vin_low_crit_perc", "%f", get_vin_perc("vin_low_crit_perc")); - dstate_setinfo("nhs.param.vin_high_warn_perc", "%f", get_vin_perc("vin_high_warn_perc")); - dstate_setinfo("nhs.param.vin_high_crit_perc", "%f", get_vin_perc("vin_high_crit_perc")); + dstate_setinfo("nhs.param.vin_low_warn_perc", "%0.2f", get_vin_perc("vin_low_warn_perc")); + dstate_setinfo("nhs.param.vin_low_crit_perc", "%0.2f", get_vin_perc("vin_low_crit_perc")); + dstate_setinfo("nhs.param.vin_high_warn_perc", "%0.2f", get_vin_perc("vin_high_warn_perc")); + dstate_setinfo("nhs.param.vin_high_crit_perc", "%0.2f", get_vin_perc("vin_high_crit_perc")); dstate_dataok(); } // end if else - upsdebugx(1,"Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request...\r\n"); + upsdebugx(1,"Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request..."); } // end else } // end if } // end if @@ -1969,7 +2011,7 @@ void upsdrv_updateinfo(void) { } // end if // Now the nobreak read buffer is empty. We need a hw info packet to discover several variables, like number of batteries, to calculate some data if (!lastpkthwinfo.checksum_ok) { - upsdebugx(1,"pkt_hwinfo loss -- Requesting\r\n"); + upsdebugx(1,"pkt_hwinfo loss -- Requesting"); // if size == 0, packet maybe not initizated, then send a initialization packet to obtain data // Send two times the extended initialization string, but, on fail, try randomly send extended or normal if (send_extended < 6) { @@ -1991,10 +2033,10 @@ void upsdrv_updateinfo(void) { if (bwritten < 0) { upsdebugx(1,"Problem to write data to %s",porta); if (bwritten == -1) { - upsdebugx(1,"\r\nData problem\r\n"); + upsdebugx(1,"Data problem"); } if (bwritten == -2) { - upsdebugx(1,"\r\nFlush problem\r\n"); + upsdebugx(1,"Flush problem"); } close(serial_fd); serial_fd = -1; @@ -2043,7 +2085,7 @@ void upsdrv_makevartable(void) { addvar(VAR_VALUE, "baud", "Baud Rate from port"); addvar(VAR_VALUE,"ah","Battery discharge capacity in Ampere/hour"); addvar(VAR_VALUE,"va","Nobreak NOMINAL POWER in VA"); - sprintf(help,"Power Factor, default is %0.2f",DEFAULTPF); + sprintf(help,"Power Factor to use in calculations of battery time, default is %0.2f",DEFAULTPF); addvar(VAR_VALUE,"pf",help); sprintf(help,"Voltage In Percentage to calculate warning low level. Default is %0.2f",DEFAULLTPERC); addvar(VAR_VALUE,"vin_low_warn_perc",help); @@ -2053,6 +2095,10 @@ void upsdrv_makevartable(void) { addvar(VAR_VALUE,"vin_high_warn_perc",help); sprintf(help,"Voltage In Percentage to calculate critical high level. Default is %0.2f",DEFAULLTPERC); addvar(VAR_VALUE,"vin_high_crit_perc",help); + sprintf(help,"Num Batteries (override value from nobreak)"); + addvar(VAR_VALUE,"numbatteries",help); + sprintf(help,"Battery Voltage (override default value. Default is %0.2f",DEFAULTBATV); + addvar(VAR_VALUE,"vbat",help); } void upsdrv_help(void) { From adfbaa617404b1827753881eb88d063774834213 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:00:06 +0100 Subject: [PATCH 06/60] drivers/Makefile.am: add nhs-nut to SERIAL_DRIVERLIST [#2692] Signed-off-by: Jim Klimov --- drivers/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index f12f20f162..7cbf4883b5 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -55,7 +55,7 @@ NUTSW_DRIVERLIST = dummy-ups clone clone-outlet apcupsd-ups skel SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \ bestfortress bestuferrups bestups etapro everups \ gamatronic genericups isbmex liebert liebert-esp2 liebert-gxe masterguard metasys \ - mge-utalk microdowell microsol-apc mge-shut oneac optiups powercom rhino \ + mge-utalk microdowell microsol-apc mge-shut nhs-nut oneac optiups powercom rhino \ safenet nutdrv_siemens-sitop solis tripplite tripplitesu upscode2 victronups powerpanel \ blazer_ser ivtscd apcsmart apcsmart-old riello_ser sms_ser bicker_ser SNMP_DRIVERLIST = snmp-ups @@ -165,6 +165,8 @@ mge_utalk_SOURCES = mge-utalk.c microdowell_SOURCES = microdowell.c microsol_apc_SOURCES = microsol-apc.c microsol-common.c microsol_apc_LDADD = $(LDADD) -lm +nhs_nut_SOURCES = nhs-nut.c +nhs_nut_LDADD = $(LDADD) -lm oneac_SOURCES = oneac.c optiups_SOURCES = optiups.c powercom_SOURCES = powercom.c From 723e062e4d92918b1eb62246182fb44944f27c56 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:11:01 +0100 Subject: [PATCH 07/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c: In function ‘print_pkt_data’: nhs-nut.c:464:17: error: zero-length gnu_printf format string [-Werror=format-zero-length] 464 | upsdebugx(1,""); | ^~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index e827f4fc4a..499b0d31ad 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -372,13 +372,16 @@ void print_pkt_hwinfo(pkt_hwinfo data) { upsdebugx(1,"Hardware Version: %u", data.hardwareversion); upsdebugx(1,"Software Version: %u", data.softwareversion); upsdebugx(1,"Configuration: %u", data.configuration); + upsdebugx(1,"Configuration Array: "); + upsdebugx(1,"-----"); for (int i = 0; i < 5; i++) { int retorno = get_bit_in_position(&data.configuration,sizeof(data.configuration),i,0); upsdebugx(1,"Binary value is %d",retorno); upsdebugx(1,"%u ", data.configuration_array[i]); } - upsdebugx(1,""); + upsdebugx(1,"-----"); + upsdebugx(1,"OEM Mode: %s", data.c_oem_mode ? "true" : "false"); upsdebugx(1,"Buzzer Disable: %s", data.c_buzzer_disable ? "true" : "false"); upsdebugx(1,"Potmin Disable: %s", data.c_potmin_disable ? "true" : "false"); @@ -394,11 +397,13 @@ void print_pkt_hwinfo(pkt_hwinfo data) { upsdebugx(1,"Status Value: %u", data.statusval); upsdebugx(1,"Status: "); + upsdebugx(1,"-----"); for (int i = 0; i < 6; i++) { upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); upsdebugx(1,"status %d --> %u ", i, data.status[i]); } - upsdebugx(1,""); + upsdebugx(1,"-----"); + upsdebugx(1,"220V In: %s", data.s_220V_in ? "true" : "false"); upsdebugx(1,"220V Out: %s", data.s_220V_out ? "true" : "false"); upsdebugx(1,"Sealed Battery: %s", data.s_sealed_battery ? "true" : "false"); @@ -456,12 +461,15 @@ void print_pkt_data(pkt_data data) { upsdebugx(1,"Battery Tension: %0.2f", data.battery_tension); upsdebugx(1,"Perc Output: %u", data.perc_output); upsdebugx(1,"Status Value: %u", data.statusval); + upsdebugx(1,"Status: "); + upsdebugx(1,"-----"); for (int i = 0; i < 8; i++) { upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); upsdebugx(1,"status %d --> %u ", i, data.status[i]); } - upsdebugx(1,""); + upsdebugx(1,"-----"); + upsdebugx(1,"Nominal Tension: %u", data.nominaltension); upsdebugx(1,"Time Remain: %0.2f", data.timeremain); upsdebugx(1,"Battery Mode: %s", data.s_battery_mode ? "true" : "false"); From e44c05eafc7e4baa94dad2494097301c8e5af8cd Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:11:47 +0100 Subject: [PATCH 08/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c:604:59: error: unused parameter ‘size’ [-Werror=unused-parameter] 604 | pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { | ~~~~^~~~ nhs-nut.c:604:72: error: unused parameter ‘tempodecorrido’ [-Werror=unused-parameter] 604 | pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { | ~~~~~~~^~~~~~~~~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 499b0d31ad..29df218b7e 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -660,6 +660,8 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco 0xFE // end_marker }; + NUT_UNUSED_VARIABLE(tempodecorrido); + pktdata.length = (int)datapacket[1]; pktdata.packet_type = datapacket[2]; pktdata.vacinrms_high = (int)datapacket[3]; @@ -722,8 +724,11 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco pktdata.perc_output = 100; } // end if } // end if + + NUT_UNUSED_VARIABLE(size); //pdatapacket(datapacket,size); //print_pkt_data(pktdata); + return pktdata; } From d09214e0f532fe5135e277d1f6b8968e0fd3fed1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:12:35 +0100 Subject: [PATCH 09/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c:713:43: error: suggest braces around empty body in an ‘if’ statement [-Werror=empty-body] 713 | if (pktdata.perc_output > 100); | ^ nhs-nut.c:713:13: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation] 713 | if (pktdata.perc_output > 100); | ^~ nhs-nut.c:714:17: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’ 714 | pktdata.perc_output = 100; | ^~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 29df218b7e..a9517db3f6 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -720,7 +720,7 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco pktdata.nominaltension = vbat * pkt_upsinfo.numbatteries; if (pktdata.nominaltension > 0) { pktdata.perc_output = (pktdata.battery_tension * 100) / pktdata.nominaltension; - if (pktdata.perc_output > 100); + if (pktdata.perc_output > 100) pktdata.perc_output = 100; } // end if } // end if From 8fd15cd848b9853996167a94d2636315efd06044 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:13:24 +0100 Subject: [PATCH 10/60] drivers/nhs-nut.c: fix compiler complaints [#2692] nhs-nut.c:797:29: error: iteration 6 invokes undefined behavior [-Werror=aggressive-loop-optimizations] 797 | pkthwinfo.status[i] = get_bit_in_position(&datapacket[14],sizeof(datapacket[14]),i,0); | ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index a9517db3f6..85c9eba8d8 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -806,7 +806,7 @@ pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { pkthwinfo.tensionout120V = (int)datapacket[12]; pkthwinfo.tensionout220V = (int)datapacket[13]; pkthwinfo.statusval = datapacket[14]; - for (i = 0; i < 8; i++) + for (i = 0; i < 6; i++) pkthwinfo.status[i] = get_bit_in_position(&datapacket[14],sizeof(datapacket[14]),i,0); // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more pkthwinfo.s_220V_in = (bool)pkthwinfo.status[0]; From cd8677e4e17fad8892df71907d75900e138478cc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:14:03 +0100 Subject: [PATCH 11/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c: In function ‘upsdrv_updateinfo’: nhs-nut.c:1733:53: error: format not a string literal and no format arguments [-Werror=format-security] 1733 | upsdebugx(1,alarm); | ^~~~~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 85c9eba8d8..d1445308aa 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -1743,7 +1743,7 @@ void upsdrv_updateinfo(void) { // Check if MAINS (power) is not preset. Well, we can check pkt_data.s_network_failure too... if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { sprintf(alarm,"UPS have power in %0.2f value and min_input_power is %d or network is in failure. Network failure is %d",lastpktdata.vacinrms,min_input_power,lastpktdata.s_network_failure); - upsdebugx(1,alarm); + upsdebugx(1,"%s",alarm); dstate_setinfo("ups.status","%s","DISCHRG"); } // end if else { From 98b3d7494ced14ef8da311a70c920a9035affe27 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:14:37 +0100 Subject: [PATCH 12/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c: In function ‘upsdrv_makevartable’: nhs-nut.c:2090:88: error: format ‘%f’ expects argument of type ‘double’, but argument 3 has type ‘int’ [-Werror=format=] 2090 | sprintf(help,"Voltage In Percentage to calculate warning low level. Default is %0.2f",DEFAULLTPERC); | ~~~~^ | | | double | %0.2d etc. for other default macros Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index d1445308aa..ee5e3ac214 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -71,9 +71,10 @@ #define DEFAULTBAUD 2400 #define DEFAULTPORT "/dev/ttyACM0" #define DEFAULTPF 0.9 -#define DEFAULLTPERC 2 +#define DEFAULLTPERC 2.0 #define DATAPACKETSIZE 100 -#define DEFAULTBATV 12 +#define DEFAULTBATV 12.0 + #define DRIVER_NAME "NHS Nobreak Drivers" #define DRIVER_VERSION "0.1" #define MANUFACTURER "NHS Sistemas Eletronicos LTDA" From e5b5b0fc495b91610d0209d3787607f83f1112ea Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:17:40 +0100 Subject: [PATCH 13/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c: In function ‘get_bit_in_position’: nhs-nut.c:357:22: error: comparison of integer expressions of different signedness: ‘int’ and ‘size_t’ {aka ‘long unsigned int’} [-Werror=sign-compare] 357 | if (bit_position >= size * 8) { | ^~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index ee5e3ac214..651c1cebbe 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -348,7 +348,7 @@ static pkt_data lastpktdata = { 0xFE // end_marker }; -int get_bit_in_position(void *ptr, size_t size, int bit_position,int invertorder) { +int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int invertorder) { unsigned char *byte_ptr = (unsigned char *)ptr; int retval = -2; size_t byte_index = bit_position / 8; From bb3d57fc8a235c421cbb949483683cdfc73886fb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:19:00 +0100 Subject: [PATCH 14/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copy-paste typo? nhs-nut.c: In function ‘mount_datapacket’: nhs-nut.c:693:29: error: operation on ‘pktdata.icarregrms_real’ may be undefined [-Werror=sequence-point] 693 | pktdata.icarregrms_real = pktdata.icarregrms_real = pktdata.icarregrms * 30; | ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 651c1cebbe..172fba164e 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -690,7 +690,7 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco pktdata.tempmed_real = pktdata.tempmed; pktdata.icarregrms = (int)datapacket[16]; // 25 units = 750mA, then 1 unit = 30mA - pktdata.icarregrms_real = pktdata.icarregrms_real = pktdata.icarregrms * 30; + pktdata.icarregrms_real = pktdata.icarregrms * 30; pktdata.statusval = datapacket[17]; for (i = 0; i < 8; i++) pktdata.status[i] = get_bit_in_position(&datapacket[17],sizeof(datapacket[17]),i,0); From 0e70a00195b2c2f7a46bd431b25009eac0ae5ae8 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:24:34 +0100 Subject: [PATCH 15/60] drivers/nhs-nut.c: fix compiler complaints [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs-nut.c: In function ‘mount_hwinfo’: nhs-nut.c:786:5: error: missing initializer for field ‘end_marker’ of ‘pkt_hwinfo’ [-Werror=missing-field-initializers] 786 | }; | ^ nhs-nut.c:177:18: note: ‘end_marker’ declared here 177 | unsigned int end_marker; | ^~~~~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 172fba164e..0d9eca1401 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -778,6 +778,7 @@ pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { 0, // second 0, // alarmyear 0, // alarmmonth + 0, // alarmwday 0, // alarmday 0, // alarmhour 0, // alarmminute From 5143fcef8b1040c085026076bc6c65581a181df9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:27:00 +0100 Subject: [PATCH 16/60] drivers/nhs-nut.c: fix trailing whitespace [#2692] Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 0d9eca1401..204fe40ddc 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -45,21 +45,21 @@ 3) Download NUT source code OR use apt-source to download source from your distribution (in case of debian/ubuntu). How to do it? apt-get source nut, apt-get build-dep nut, make your alterations in code (follow the steps above), dpkg-buildpackage -us -uc, dpkg -i * ./autogen.sh 4) ./autogen.sh 5) ./ci_build.sh - 6) ./configure $COMPILEFLAGS --with-dev + 6) ./configure $COMPILEFLAGS --with-dev 7) cd drivers 8) make (to generate nut_version.h) - + If you can use debian / ubuntu packages to do that: 1) apt-get source nut 2) apt-get build-dep nut 3) extract flags to correct compilation with COMPILEFLAGS=$(make -f debian/rules -pn | grep '^DEB_CONFIGURE_EXTRA_FLAGS' | sed 's/^DEB_CONFIGURE_EXTRA_FLAGS := //') on root source directory 4) Follow steps 4 to 8 earlier (ignore errors if you can only compile to use the driver with actual nut compiled debian instalation, it's only to generate nut_version.h) 5) back to root nut source directory, then dpkg-buildpackage -us -uc - 6) dpkg -i + 6) dpkg -i * gcc -g -O0 -o nhs-nut nhs-nut.c main.c dstate.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm * upsdrvquery.c (optional) - * copy nhs-nut to nut driver's directory and test + * copy nhs-nut to nut driver's directory and test To debug: * clang --analyze nhs-nut.c * cppcheck nhs-nut.c @@ -177,7 +177,7 @@ typedef struct { unsigned int end_marker; } pkt_hwinfo; -// Struct that contain the +// Struct that contain the typedef struct { unsigned int header; unsigned int length; @@ -353,7 +353,7 @@ int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int inverto int retval = -2; size_t byte_index = bit_position / 8; size_t bit_index = bit_position % 8; - + if (bit_position >= size * 8) { return -3; // Invalid Position } @@ -539,7 +539,7 @@ int openfd(const char * porta, int BAUDRATE) { done = B2400; } - + tty.c_cflag &= ~PARENB; // Disable Parity tty.c_cflag &= ~CSTOPB; // 1 stop bit @@ -692,7 +692,7 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco // 25 units = 750mA, then 1 unit = 30mA pktdata.icarregrms_real = pktdata.icarregrms * 30; pktdata.statusval = datapacket[17]; - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) pktdata.status[i] = get_bit_in_position(&datapacket[17],sizeof(datapacket[17]),i,0); // I don't know WHY, but bit order is INVERTED here. Discovered on clyra's github python implementation // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more @@ -1670,7 +1670,7 @@ void upsdrv_updateinfo(void) { if (datapacketstart) { datapacket[datapacket_index] = chr; datapacket_index++; - if (chr == 0xFE) { // DataPacket + if (chr == 0xFE) { // DataPacket upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); time_t now = time(NULL); if (lastdp != 0) { @@ -1678,7 +1678,7 @@ void upsdrv_updateinfo(void) { } lastdp = now; // if size is 18 or 50, maybe a answer packet. Then check if doesn't have already a packet processed. We don't need to read all times these information. Can be a corrupted packet too. - if (((datapacket_index == 18) || (datapacket_index == 50)) && (!lastpkthwinfo.checksum_ok)) { + if (((datapacket_index == 18) || (datapacket_index == 50)) && (!lastpkthwinfo.checksum_ok)) { lastpkthwinfo = mount_hwinfo(datapacket, datapacket_index); } // end if else { @@ -1721,7 +1721,7 @@ void upsdrv_updateinfo(void) { FSD -- Forced Shutdown (restricted use, see the note below) */ // Decision Chain - // First we check if system is on battery or not + // First we check if system is on battery or not upsdebugx(1,"Set UPS status as OFF and start checking. s_battery_mode is %d",lastpktdata.s_battery_mode); if (lastpkthwinfo.s_220V_in) { upsdebugx(1,"I'm on 220v IN!. My overvoltage is %d",lastpkthwinfo.undervoltagein220V); @@ -1769,16 +1769,16 @@ void upsdrv_updateinfo(void) { } // end if else { // Energy is below limit. Nobreak problably in battery mode - if (lastpktdata.s_battery_low) + if (lastpktdata.s_battery_low) dstate_setinfo("ups.status","%s","LB"); else { // or network failure - dstate_setinfo("ups.status","%s","OB"); + dstate_setinfo("ups.status","%s","OB"); } // end else } // end else } // end else } // end else - + alarm[0] = '\0'; numbat = get_numbat(); if (numbat == 0) @@ -1883,13 +1883,13 @@ void upsdrv_updateinfo(void) { dstate_setinfo("battery.temperature","%u",(unsigned int)round(lastpktdata.tempmed_real)); dstate_setinfo("battery.packs","%u",numbat); // We will calculate autonomy in seconds - + // Autonomy calculation in NHS nobreaks is a rocket science. Some are one, some are other. I'll do my best to put one that works in 4 models that I have here. - // That result is IN HOURS. We need to convert it on seconds + // That result is IN HOURS. We need to convert it on seconds //autonomy_secs = (int)round((ah / (vpower / lastpktdata.vdcmed_real)) * 3600); autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; //upsdebugx(1,"(numbat * lastpktdata.vdcmed_real * va * pf) / ((lastpktdata.potrms * va * pf) / 100.0) = (%d * %0.2f * %d * %0.2f) / ((%d * %d * %0.2f) / 100.0) --> %0.2f",numbat,lastpktdata.vdcmed_real,va,pf,lastpktdata.potrms,va,pf,autonomy_secs); - // That result is IN HOURS. We need to convert it on seconds + // That result is IN HOURS. We need to convert it on seconds dstate_setinfo("battery.runtime","%u",autonomy_secs); dstate_setinfo("battery.runtime.low","%u",30); @@ -1901,7 +1901,7 @@ void upsdrv_updateinfo(void) { else dstate_setinfo("battery.charger.status","%s","RESTING"); } - // Now, creating a structure called NHS, + // Now, creating a structure called NHS, dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); @@ -2122,5 +2122,4 @@ void upsdrv_help(void) { //int main(int argc, char **argv) { // upsdrv_info.version = "1.0"; // upsdrv_initinfo(); -//} - +//} From a4d08cf9a4307aba23f4089e0c77414ee0585acb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:27:12 +0100 Subject: [PATCH 17/60] drivers/nhs-nut.c: fix upsdrv_shutdown() [#2692] Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 204fe40ddc..5ebec9c6b6 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -2072,10 +2072,11 @@ void upsdrv_updateinfo(void) { void upsdrv_shutdown(void) { upsdebugx(1,"Start shutdown()"); - if (serial_fd != -1) { - close(serial_fd); - serial_fd = -1; - } + + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); + upsdebugx(1,"Driver shutdown"); } From c219c1563340b227903ce79183cd60d1561215b4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:30:23 +0100 Subject: [PATCH 18/60] NEWS.adoc: introduce nhs-nut (sic) driver [#2692] Signed-off-by: Jim Klimov --- NEWS.adoc | 3 +++ docs/nut.dict | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS.adoc b/NEWS.adoc index fe174f6b1f..3dc7698b67 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -149,6 +149,9 @@ https://github.com/networkupstools/nut/milestone/11 - liebert-gxe: added new driver with support for Liebert GXE Series UPS (serial or USB posing as a serial port). [#2629] + - nhs-nut: added new driver for numerous Nobreak UPS models with serial port, + made by NHS Sistemas Eletronicos LTDA and popular in Brazil. [#2692] + - usbhid-ups updates: * Support of the `onlinedischarge_log_throttle_hovercharge` in the NUT v2.8.2 release was found to be incomplete. [#2423, follow-up to #2215] diff --git a/docs/nut.dict b/docs/nut.dict index 2338eba070..c24866056a 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3244 utf-8 +personal_ws-1.1 en 3248 utf-8 AAC AAS ABI @@ -338,6 +338,7 @@ Effekta Egys Ekkehard Electrys +Eletronicos Elio Elizarov Eltek @@ -605,6 +606,7 @@ LOADPCT LOCKFN LOCKNAME LOTRANS +LTDA LTS LUA LVM @@ -777,6 +779,7 @@ Neus Niels Niklas Niro +Nobreak Nobreaks Nom NotePad @@ -2434,6 +2437,7 @@ newvictronups nf ng nhnl +nhs nielchiano nitram nl From 01f01d9227c8605a185faf2ad85afad0b4e70154 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:51:01 +0100 Subject: [PATCH 19/60] drivers/nhs-nut.c: fix DRIVER_VERSION to double-digits [#2692] Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 5ebec9c6b6..7535bce471 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -76,7 +76,7 @@ #define DEFAULTBATV 12.0 #define DRIVER_NAME "NHS Nobreak Drivers" -#define DRIVER_VERSION "0.1" +#define DRIVER_VERSION "0.01" #define MANUFACTURER "NHS Sistemas Eletronicos LTDA" /* driver description structure */ From 0e7068e5103fdb8936cb15157192990557075f6f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 09:59:45 +0100 Subject: [PATCH 20/60] drivers/nhs-nut.c: revise upsdrv_makevartable() content and markup [#2692] Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 7535bce471..1ba60158c3 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -2097,22 +2097,34 @@ void upsdrv_initups(void) { void upsdrv_makevartable(void) { char help[4096]; - addvar(VAR_VALUE, "port", "Port to communication"); + + // Standard variable in main.c + //addvar(VAR_VALUE, "port", "Port to communication"); + addvar(VAR_VALUE, "baud", "Baud Rate from port"); + addvar(VAR_VALUE,"ah","Battery discharge capacity in Ampere/hour"); + addvar(VAR_VALUE,"va","Nobreak NOMINAL POWER in VA"); + sprintf(help,"Power Factor to use in calculations of battery time, default is %0.2f",DEFAULTPF); addvar(VAR_VALUE,"pf",help); + sprintf(help,"Voltage In Percentage to calculate warning low level. Default is %0.2f",DEFAULLTPERC); addvar(VAR_VALUE,"vin_low_warn_perc",help); + sprintf(help,"Voltage In Percentage to calculate critical low level. Default is %0.2f",DEFAULLTPERC); addvar(VAR_VALUE,"vin_low_crit_perc",help); + sprintf(help,"Voltage In Percentage to calculate warning high level. Default is %0.2f",DEFAULLTPERC); addvar(VAR_VALUE,"vin_high_warn_perc",help); + sprintf(help,"Voltage In Percentage to calculate critical high level. Default is %0.2f",DEFAULLTPERC); addvar(VAR_VALUE,"vin_high_crit_perc",help); + sprintf(help,"Num Batteries (override value from nobreak)"); addvar(VAR_VALUE,"numbatteries",help); + sprintf(help,"Battery Voltage (override default value. Default is %0.2f",DEFAULTBATV); addvar(VAR_VALUE,"vbat",help); } From 90d715e854b6cf752a33eb876bb44c45ec66c7ca Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:01:30 +0100 Subject: [PATCH 21/60] drivers/nhs-nut.c: revise upsdrv_makevartable(): use snprintf() and fix some more markup [#2692] Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 1ba60158c3..55f4416067 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -2103,30 +2103,30 @@ void upsdrv_makevartable(void) { addvar(VAR_VALUE, "baud", "Baud Rate from port"); - addvar(VAR_VALUE,"ah","Battery discharge capacity in Ampere/hour"); + addvar(VAR_VALUE, "ah", "Battery discharge capacity in Ampere/hour"); - addvar(VAR_VALUE,"va","Nobreak NOMINAL POWER in VA"); + addvar(VAR_VALUE, "va", "Nobreak NOMINAL POWER in VA"); - sprintf(help,"Power Factor to use in calculations of battery time, default is %0.2f",DEFAULTPF); - addvar(VAR_VALUE,"pf",help); + snprintf(help, sizeof(help), "Power Factor to use in calculations of battery time, default is %0.2f", DEFAULTPF); + addvar(VAR_VALUE, "pf", help); - sprintf(help,"Voltage In Percentage to calculate warning low level. Default is %0.2f",DEFAULLTPERC); - addvar(VAR_VALUE,"vin_low_warn_perc",help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning low level. Default is %0.2f", DEFAULLTPERC); + addvar(VAR_VALUE, "vin_low_warn_perc", help); - sprintf(help,"Voltage In Percentage to calculate critical low level. Default is %0.2f",DEFAULLTPERC); - addvar(VAR_VALUE,"vin_low_crit_perc",help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical low level. Default is %0.2f", DEFAULLTPERC); + addvar(VAR_VALUE, "vin_low_crit_perc", help); - sprintf(help,"Voltage In Percentage to calculate warning high level. Default is %0.2f",DEFAULLTPERC); - addvar(VAR_VALUE,"vin_high_warn_perc",help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning high level. Default is %0.2f", DEFAULLTPERC); + addvar(VAR_VALUE, "vin_high_warn_perc", help); - sprintf(help,"Voltage In Percentage to calculate critical high level. Default is %0.2f",DEFAULLTPERC); - addvar(VAR_VALUE,"vin_high_crit_perc",help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical high level. Default is %0.2f", DEFAULLTPERC); + addvar(VAR_VALUE, "vin_high_crit_perc", help); - sprintf(help,"Num Batteries (override value from nobreak)"); - addvar(VAR_VALUE,"numbatteries",help); + snprintf(help, sizeof(help), "Num Batteries (override value from nobreak)"); + addvar(VAR_VALUE, "numbatteries", help); - sprintf(help,"Battery Voltage (override default value. Default is %0.2f",DEFAULTBATV); - addvar(VAR_VALUE,"vbat",help); + snprintf(help, sizeof(help), "Battery Voltage (override default value. Default is %0.2f", DEFAULTBATV); + addvar(VAR_VALUE, "vbat", help); } void upsdrv_help(void) { From 29235a0881c4c6a46043b4c328f5b7845dc11671 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:08:28 +0100 Subject: [PATCH 22/60] drivers/nhs-nut.c: revise upsdrv_makevartable(): fix help messages [#2692] Signed-off-by: Jim Klimov --- drivers/nhs-nut.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/nhs-nut.c b/drivers/nhs-nut.c index 55f4416067..a08deee47a 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs-nut.c @@ -2107,7 +2107,7 @@ void upsdrv_makevartable(void) { addvar(VAR_VALUE, "va", "Nobreak NOMINAL POWER in VA"); - snprintf(help, sizeof(help), "Power Factor to use in calculations of battery time, default is %0.2f", DEFAULTPF); + snprintf(help, sizeof(help), "Power Factor to use in calculations of battery time. Default is %0.2f", DEFAULTPF); addvar(VAR_VALUE, "pf", help); snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning low level. Default is %0.2f", DEFAULLTPERC); @@ -2125,7 +2125,7 @@ void upsdrv_makevartable(void) { snprintf(help, sizeof(help), "Num Batteries (override value from nobreak)"); addvar(VAR_VALUE, "numbatteries", help); - snprintf(help, sizeof(help), "Battery Voltage (override default value. Default is %0.2f", DEFAULTBATV); + snprintf(help, sizeof(help), "Battery Voltage (override default value). Default is %0.2f", DEFAULTBATV); addvar(VAR_VALUE, "vbat", help); } From 341d4241dc71b829fa8085d4b5a68750a388fc5a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:10:22 +0100 Subject: [PATCH 23/60] docs/man/nhs-nut.txt: introduce new driver manpage [#2692] Signed-off-by: Jim Klimov --- docs/man/Makefile.am | 3 ++ docs/man/nhs-nut.txt | 77 ++++++++++++++++++++++++++++++++++++++++++++ docs/nut.dict | 9 +++++- 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 docs/man/nhs-nut.txt diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 2d96d85224..b890fdd6c2 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -512,6 +512,7 @@ SRC_SERIAL_PAGES = \ powerpanel.txt \ rhino.txt \ riello_ser.txt \ + nhs-nut.txt \ sms_ser.txt \ safenet.txt \ solis.txt \ @@ -561,6 +562,7 @@ MAN_SERIAL_PAGES = \ powerpanel.8 \ rhino.8 \ riello_ser.8 \ + nhs-nut.8 \ sms_ser.8 \ safenet.8 \ solis.8 \ @@ -613,6 +615,7 @@ HTML_SERIAL_MANS = \ powerpanel.html \ rhino.html \ riello_ser.html \ + nhs-nut.html \ sms_ser.html \ safenet.html \ solis.html \ diff --git a/docs/man/nhs-nut.txt b/docs/man/nhs-nut.txt new file mode 100644 index 0000000000..671894aa1c --- /dev/null +++ b/docs/man/nhs-nut.txt @@ -0,0 +1,77 @@ +NHS-NUT(8) +========== + +NAME +---- + +nhs-nut - driver for NHS Nobreak devices with serial port + +SYNOPSIS +-------- + +*nhs-nut* -h + +*nhs-nut* -a 'UPS_NAME' ['OPTIONS'] + +NOTE: This man page only documents the hardware-specific features of the +*nhs-nut* driver. For information about the core driver, see +linkman:nutupsdrv[8]. + +SUPPORTED HARDWARE +------------------ + +*nhs-nut* supports numerous UPS models made by NHS Sistemas Eletronicos LTDA +and marketed in Brazil. They feature a serial port and a binary wire protocol. + +EXTRA ARGUMENTS +--------------- + +This driver also supports the following optional settings: + +*baud*='num':: +Set the value of serial port baud rate (default: 2400) + +*ah*='num':: +Battery discharge capacity in Ampere/hour. + +*va*='num':: +Nobreak NOMINAL POWER in VA. + +*pf*='num':: +Power Factor to use in calculations of battery time (default: 0.90). + +*vin_low_warn_perc*='num':: +Voltage In Percentage to calculate warning low level (default: 2.00). + +*vin_low_crit_perc*='num':: +Voltage In Percentage to calculate critical low level (default: 2.00). + +*vin_high_warn_perc*='num':: +Voltage In Percentage to calculate warning high level (default: 2.00). + +*vin_high_crit_perc*='num':: +Voltage In Percentage to calculate critical high level (default: 2.00). + +*numbatteries*='num':: +Num Batteries (override value from nobreak). + +*vbat*='num':: +Battery Voltage (default: 12.00). + +AUTHORS +------- + +Lucas Willian Bocchi + +SEE ALSO +-------- + +The core driver: +~~~~~~~~~~~~~~~~ + +linkman:nutupsdrv[8] + +Internet resources: +~~~~~~~~~~~~~~~~~~~ + +The NUT (Network UPS Tools) home page: https://www.networkupstools.org/ diff --git a/docs/nut.dict b/docs/nut.dict index c24866056a..2f04c63be7 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3248 utf-8 +personal_ws-1.1 en 3255 utf-8 AAC AAS ABI @@ -129,6 +129,7 @@ BlackOut BladeUPS BlueOcean Bo +Bocchi Bohe Borns Borri @@ -1379,6 +1380,7 @@ Wextra WhizBang WiX Wikipedia +Willian WinMerge WinNUT WinPower @@ -1714,6 +1716,7 @@ cpqpower cpsups cr crestfactor +crit criticality crlf cron @@ -2449,6 +2452,7 @@ nn nnn noAuthNoPriv nobody's +nobreak nobt nodev nodownload @@ -2482,6 +2486,7 @@ nuget num numOfBytesFromUPS numa +numbatteries numlogins numq nutclient @@ -2562,6 +2567,7 @@ pe peasy peername pem +perc perl pfSense pfexec @@ -3147,6 +3153,7 @@ variadic varlow varname varvalue +vbat vbatt vc vendorid From 638e0afb46a206ec5e78701de5485f98b7baa78c Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:22:06 +0100 Subject: [PATCH 24/60] Rename "nhs-nut" to "nhs_ser" [#2692] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 +- docs/man/Makefile.am | 6 +++--- docs/man/{nhs-nut.txt => nhs_ser.txt} | 12 ++++++------ drivers/Makefile.am | 4 ++-- drivers/{nhs-nut.c => nhs_ser.c} | 12 ++++++------ 5 files changed, 18 insertions(+), 18 deletions(-) rename docs/man/{nhs-nut.txt => nhs_ser.txt} (85%) rename drivers/{nhs-nut.c => nhs_ser.c} (99%) diff --git a/NEWS.adoc b/NEWS.adoc index 3dc7698b67..021ca548f3 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -149,7 +149,7 @@ https://github.com/networkupstools/nut/milestone/11 - liebert-gxe: added new driver with support for Liebert GXE Series UPS (serial or USB posing as a serial port). [#2629] - - nhs-nut: added new driver for numerous Nobreak UPS models with serial port, + - nhs_ser: added new driver for numerous Nobreak UPS models with serial port, made by NHS Sistemas Eletronicos LTDA and popular in Brazil. [#2692] - usbhid-ups updates: diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index b890fdd6c2..53c2eb0413 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -512,7 +512,7 @@ SRC_SERIAL_PAGES = \ powerpanel.txt \ rhino.txt \ riello_ser.txt \ - nhs-nut.txt \ + nhs_ser.txt \ sms_ser.txt \ safenet.txt \ solis.txt \ @@ -562,7 +562,7 @@ MAN_SERIAL_PAGES = \ powerpanel.8 \ rhino.8 \ riello_ser.8 \ - nhs-nut.8 \ + nhs_ser.8 \ sms_ser.8 \ safenet.8 \ solis.8 \ @@ -615,7 +615,7 @@ HTML_SERIAL_MANS = \ powerpanel.html \ rhino.html \ riello_ser.html \ - nhs-nut.html \ + nhs_ser.html \ sms_ser.html \ safenet.html \ solis.html \ diff --git a/docs/man/nhs-nut.txt b/docs/man/nhs_ser.txt similarity index 85% rename from docs/man/nhs-nut.txt rename to docs/man/nhs_ser.txt index 671894aa1c..980abf5de2 100644 --- a/docs/man/nhs-nut.txt +++ b/docs/man/nhs_ser.txt @@ -1,26 +1,26 @@ -NHS-NUT(8) +NHS_SER(8) ========== NAME ---- -nhs-nut - driver for NHS Nobreak devices with serial port +nhs_ser - driver for NHS Nobreak devices with serial port SYNOPSIS -------- -*nhs-nut* -h +*nhs_ser* -h -*nhs-nut* -a 'UPS_NAME' ['OPTIONS'] +*nhs_ser* -a 'UPS_NAME' ['OPTIONS'] NOTE: This man page only documents the hardware-specific features of the -*nhs-nut* driver. For information about the core driver, see +*nhs_ser* driver. For information about the core driver, see linkman:nutupsdrv[8]. SUPPORTED HARDWARE ------------------ -*nhs-nut* supports numerous UPS models made by NHS Sistemas Eletronicos LTDA +*nhs_ser* supports numerous UPS models made by NHS Sistemas Eletronicos LTDA and marketed in Brazil. They feature a serial port and a binary wire protocol. EXTRA ARGUMENTS diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 7cbf4883b5..9ce91ffec9 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -55,7 +55,7 @@ NUTSW_DRIVERLIST = dummy-ups clone clone-outlet apcupsd-ups skel SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \ bestfortress bestuferrups bestups etapro everups \ gamatronic genericups isbmex liebert liebert-esp2 liebert-gxe masterguard metasys \ - mge-utalk microdowell microsol-apc mge-shut nhs-nut oneac optiups powercom rhino \ + mge-utalk microdowell microsol-apc mge-shut nhs_ser oneac optiups powercom rhino \ safenet nutdrv_siemens-sitop solis tripplite tripplitesu upscode2 victronups powerpanel \ blazer_ser ivtscd apcsmart apcsmart-old riello_ser sms_ser bicker_ser SNMP_DRIVERLIST = snmp-ups @@ -165,7 +165,7 @@ mge_utalk_SOURCES = mge-utalk.c microdowell_SOURCES = microdowell.c microsol_apc_SOURCES = microsol-apc.c microsol-common.c microsol_apc_LDADD = $(LDADD) -lm -nhs_nut_SOURCES = nhs-nut.c +nhs_nut_SOURCES = nhs_ser.c nhs_nut_LDADD = $(LDADD) -lm oneac_SOURCES = oneac.c optiups_SOURCES = optiups.c diff --git a/drivers/nhs-nut.c b/drivers/nhs_ser.c similarity index 99% rename from drivers/nhs-nut.c rename to drivers/nhs_ser.c index a08deee47a..fff5348a4a 100644 --- a/drivers/nhs-nut.c +++ b/drivers/nhs_ser.c @@ -1,5 +1,5 @@ /* - * nhs-nut.c - NUT support for NHS Nobreaks, senoidal line + * nhs_ser.c - NUT support for NHS Nobreaks, senoidal line * * * Copyright (C) 2024 - Lucas Willian Bocchi @@ -57,14 +57,14 @@ 5) back to root nut source directory, then dpkg-buildpackage -us -uc 6) dpkg -i - * gcc -g -O0 -o nhs-nut nhs-nut.c main.c dstate.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm + * gcc -g -O0 -o nhs_ser nhs_ser.c main.c dstate.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm * upsdrvquery.c (optional) - * copy nhs-nut to nut driver's directory and test + * copy nhs_ser to nut driver's directory and test To debug: - * clang --analyze nhs-nut.c - * cppcheck nhs-nut.c + * clang --analyze nhs_ser.c + * cppcheck nhs_ser.c * upsdrvctl -D start - * nhs-nut -a -D + * nhs_ser -a -D * upsd -D */ From 8a4fafbe29318434d3b94f3f46d2f76b417d8f5a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:26:35 +0100 Subject: [PATCH 25/60] NEWS.adoc, docs/man/nhs_ser.txt: rephrase naming of devices covered by nhs_ser driver [#2692] Signed-off-by: Jim Klimov --- NEWS.adoc | 5 +++-- docs/man/nhs_ser.txt | 2 +- docs/nut.dict | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 021ca548f3..429b137863 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -149,8 +149,9 @@ https://github.com/networkupstools/nut/milestone/11 - liebert-gxe: added new driver with support for Liebert GXE Series UPS (serial or USB posing as a serial port). [#2629] - - nhs_ser: added new driver for numerous Nobreak UPS models with serial port, - made by NHS Sistemas Eletronicos LTDA and popular in Brazil. [#2692] + - nhs_ser: added new driver for numerous NHS Nobreaks, senoidal line -- UPS + models with serial port, made by NHS Sistemas Eletronicos LTDA and popular + in Brazil. [#2692] - usbhid-ups updates: * Support of the `onlinedischarge_log_throttle_hovercharge` in the NUT diff --git a/docs/man/nhs_ser.txt b/docs/man/nhs_ser.txt index 980abf5de2..5de21745fd 100644 --- a/docs/man/nhs_ser.txt +++ b/docs/man/nhs_ser.txt @@ -4,7 +4,7 @@ NHS_SER(8) NAME ---- -nhs_ser - driver for NHS Nobreak devices with serial port +nhs_ser - driver for NHS Nobreaks, senoidal line, with serial port SYNOPSIS -------- diff --git a/docs/nut.dict b/docs/nut.dict index 2f04c63be7..f31f67b641 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3255 utf-8 +personal_ws-1.1 en 3256 utf-8 AAC AAS ABI @@ -2783,6 +2783,7 @@ sendmail sendsignal sendsignalfn sendsignalpid +senoidal sequentialized ser seria From 9672972cfa722f059d72ebe2840af7bf6aa05431 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:33:41 +0100 Subject: [PATCH 26/60] data/driver.list.in: update with devices supported by nhs_ser driver [#2692] List extracted from current driver code with grep 'strcpy(data.upsdesc' drivers/nhs_ser.c | \ sed 's/^ *strcpy(data.upsdesc,"\(.*\)".*$/"NHS Sistemas Eletronicos LTDA"\t"ups"\t"2"\t"\1"\t"Serial port"\t"nhs_ser"/' \ >> data/driver.list.in Signed-off-by: Jim Klimov --- data/driver.list.in | 111 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/data/driver.list.in b/data/driver.list.in index 2ce4a099ed..c21584e7b3 100644 --- a/data/driver.list.in +++ b/data/driver.list.in @@ -914,6 +914,117 @@ "NHS Sistemas de Energia" "ups" "5" "Expert S Online 10000" "" "gamatronic" "NHS Sistemas de Energia" "ups" "5" "Laser Senoidal 5000VA" "USB" "gamatronic" # http://www.nhs.com.br/produtos_interna/id/T0RrPQ== +# Large block coming from https://github.com/networkupstools/nut/pulls/2692 : +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS SENOIDAL" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS RACK" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PREMIUM PDV" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PREMIUM PDV SENOIDAL" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PREMIUM 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PREMIUM 2200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PREMIUM SENOIDAL" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS LASER 2600VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS LASER 3300VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS LASER 2600VA ISOLADOR" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS LASER SENOIDAL" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS LASER ON-LINE" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "COMPACT PLUS SENOIDAL 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "COMPACT PLUS RACK 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM PDV 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM PDV SENOIDAL 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM 1500VA 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM 2200VA 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER 2600VA 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER 3300VA 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER 2600VA ISOLADOR 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV ONLINE 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "EXPERT ONLINE 2003" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "MINI 2" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "COMPACT PLUS 2" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ON-LINE" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV SENOIDAL 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV SENOIDAL 1000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 3750VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 5000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 2000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 3500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM PDV 1200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM 2200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER 2600VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER 3300VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "COMPACT PLUS SENOIDAL 700VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM ONLINE 2000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "EXPERT ONLINE 10000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 4200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS EXTENDIDO 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 6000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER EXT 3300VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS 1200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 3000VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 3500VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 4200VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 3000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 3750VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 5000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 6000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM ONLINE 2000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM ONLINE 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM ONLINE 1200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "COMPACT PLUS II MAX 1400VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM PDV MAX 2200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM PDV 3000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 2200VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER PRIME SENOIDAL 3200VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM RACK ONLINE 3000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM ONLINE 3000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 4000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 7500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE BIFASICO 5000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE BIFASICO 6000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE BIFASICO 7500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS MINI ST" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS MINI 120" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS MINI BIVOLT" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV 600" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS MINI MAX" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS MINI EXT" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS AUTONOMY PDV 4T" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS AUTONOMY PDV 8T" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS COMPACT PLUS RACK 1200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV SENOIDAL ISOLADOR 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PDV RACK 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PDV 1400VA S GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV SENOIDAL ISOLADOR 1500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER PRIME SENOIDAL ISOLADOR 2000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 2400VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS PDV 1400VA S 8T GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM ONLINE 2000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER PRIME ONLINE 2200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM RACK ONLINE 2200VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 2400VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 10000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE BIFASICO 10000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 3300VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 2600VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 3000VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PREMIUM SENOIDAL 2200VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE BIFASICO 4000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 12000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 8000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV SENOIDAL ISOLADOR 1000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "MINI SENOIDAL 500VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER SENOIDAL 5000VA GII" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "COMPACT PLUS SENOIDAL 1000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "QUAD_COM 80A" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "LASER ONLINE 5000VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "PDV SENOIDAL ISOLADOR 700VA" "Serial port" "nhs_ser" +"NHS Sistemas Eletronicos LTDA" "ups" "2" "NHS UNKNOWN" "Serial port" "nhs_ser" + "Nitram" "ups" "1" "Elite 500" "" "genericups upstype=8" "Nitram" "ups" "1" "Elite 2002" "" "genericups upstype=16" "Nitram" "ups" "1" "Elite 2005" "" "powerpanel" From bbbf3e96f5b0537b0a4574f3ffbcc438cc29aa3e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 10:36:44 +0100 Subject: [PATCH 27/60] drivers/nhs_ser.c: update comment about use of "clang --analyze" [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index fff5348a4a..418af219fa 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -61,7 +61,7 @@ * upsdrvquery.c (optional) * copy nhs_ser to nut driver's directory and test To debug: - * clang --analyze nhs_ser.c + * clang --analyze -I../include nhs_ser.c * cppcheck nhs_ser.c * upsdrvctl -D start * nhs_ser -a -D From 8fbb57eae5f55b76abd8a57a90cec4424e541320 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 11:26:55 +0100 Subject: [PATCH 28/60] Rename "nhs-nut" to "nhs_ser" follow-up [#2692] Signed-off-by: Jim Klimov --- drivers/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 9ce91ffec9..bfa2638954 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -165,8 +165,8 @@ mge_utalk_SOURCES = mge-utalk.c microdowell_SOURCES = microdowell.c microsol_apc_SOURCES = microsol-apc.c microsol-common.c microsol_apc_LDADD = $(LDADD) -lm -nhs_nut_SOURCES = nhs_ser.c -nhs_nut_LDADD = $(LDADD) -lm +nhs_ser_SOURCES = nhs_ser.c +nhs_ser_LDADD = $(LDADD) -lm oneac_SOURCES = oneac.c optiups_SOURCES = optiups.c powercom_SOURCES = powercom.c From ce20dbe70c683eddca0daf4ab5b77971549861ae Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 11:49:10 +0100 Subject: [PATCH 29/60] drivers/nhs-nut.c: fix compiler complaints - static vars/methods and strict parameters [#2692] * Static internal methods and pre-declarations on top of file: nhs_ser.c:1549:14: error: no previous prototype for function 'get_va' [-Werror,-Wmissing-prototypes] unsigned int get_va(int equipment) { ^ nhs_ser.c:1549:1: note: declare 'static' if the function is not intended to be used outside of this translation unit unsigned int get_va(int equipment) { ^ static * Explicit void args: nhs_ser.c:1571:20: error: this old-style function definition is not preceded by a prototype [-Werror,-Wstrict-prototypes] unsigned int get_ah() { ^ Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 78 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 418af219fa..83410b3b0c 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -97,7 +97,7 @@ typedef struct { const char * description; // Description } baud_rate_t; -baud_rate_t baud_rates[] = { +static baud_rate_t baud_rates[] = { { B50, 50, "50 bps" }, { B75, 75, "75 bps" }, { B110, 110, "110 bps" }, @@ -231,8 +231,8 @@ typedef struct { unsigned int VA; } upsinfo; -const unsigned int string_initialization_long[9] = {0xFF, 0x09, 0x53, 0x83, 0x00, 0x00, 0x00, 0xDF, 0xFE}; -const unsigned int string_initialization_short[9] = {0xFF, 0x09, 0x53, 0x03, 0x00, 0x00, 0x00, 0x5F, 0xFE}; +static const unsigned int string_initialization_long[9] = {0xFF, 0x09, 0x53, 0x83, 0x00, 0x00, 0x00, 0xDF, 0xFE}; +static const unsigned int string_initialization_short[9] = {0xFF, 0x09, 0x53, 0x03, 0x00, 0x00, 0x00, 0x5F, 0xFE}; static int serial_fd = -1; static unsigned char chr; @@ -348,7 +348,36 @@ static pkt_data lastpktdata = { 0xFE // end_marker }; -int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int invertorder) { +/* internal methods */ +static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int invertorder); +static float createfloat(int integer, int decimal); +static char * strtolow(char* s); + +static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim); +static float calculate_efficiency(float vacoutrms, float vacinrms); + +static int openfd(const char * porta, int BAUDRATE); +static int write_serial(int serial_fd, const char * dados, int size); +static int write_serial_int(int serial_fd, const unsigned int * data, int size); + +static void print_pkt_hwinfo(pkt_hwinfo data); +static void print_pkt_data(pkt_data data); +static void pdatapacket(unsigned char * datapacket, int size); +static pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido, pkt_hwinfo pkt_upsinfo); +static pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size); +static upsinfo getupsinfo(unsigned int upscode); + +static unsigned int get_va(int equipment); +static unsigned int get_vbat(void); +static float get_pf(void); +static unsigned int get_ah(void); +static float get_vin_perc(char * var); +static unsigned int get_numbat(void); + + +/* method implementations */ + +static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int invertorder) { unsigned char *byte_ptr = (unsigned char *)ptr; int retval = -2; size_t byte_index = bit_position / 8; @@ -365,7 +394,7 @@ int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int inverto return retval; } -void print_pkt_hwinfo(pkt_hwinfo data) { +static void print_pkt_hwinfo(pkt_hwinfo data) { upsdebugx(1,"Header: %u", data.header); upsdebugx(1,"Size: %u", data.size); upsdebugx(1,"Type: %c", data.type); @@ -432,7 +461,7 @@ void print_pkt_hwinfo(pkt_hwinfo data) { upsdebugx(1,"End Marker: %u", data.end_marker); } -void print_pkt_data(pkt_data data) { +static void print_pkt_data(pkt_data data) { upsdebugx(1,"Header: %u", data.header); upsdebugx(1,"Length: %u", data.length); upsdebugx(1,"Packet Type: %c", data.packet_type); @@ -487,7 +516,7 @@ void print_pkt_data(pkt_data data) { upsdebugx(1,"End Marker: %u", data.end_marker); } -int openfd(const char * porta, int BAUDRATE) { +static int openfd(const char * porta, int BAUDRATE) { long unsigned int i = 0; int done = 0; struct termios tty; @@ -524,6 +553,7 @@ int openfd(const char * porta, int BAUDRATE) { } i++; } + // if done is 0, no one speed has selected, then use default if (done == 0) { while ((i < NUM_BAUD_RATES) && (done == 0)) { @@ -534,13 +564,13 @@ int openfd(const char * porta, int BAUDRATE) { i++; } } + if (done == 0) { upsdebugx(1,"Baud rate not found, using default %d",DEFAULTBAUD); done = B2400; } - tty.c_cflag &= ~PARENB; // Disable Parity tty.c_cflag &= ~CSTOPB; // 1 stop bit tty.c_cflag &= ~CSIZE; // Clear Bit Set @@ -576,7 +606,7 @@ int openfd(const char * porta, int BAUDRATE) { return fd; } -unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { +static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { int soma = 0; for (int i = inicio; i <= fim; i++) { soma += pacote[i]; @@ -584,7 +614,7 @@ unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { return soma & 0xFF; } -void pdatapacket(unsigned char * datapacket,int size) { +static void pdatapacket(unsigned char * datapacket,int size) { int i = 0; if (datapacket != NULL) { upsdebugx(1,"Received Datapacket: "); @@ -594,13 +624,13 @@ void pdatapacket(unsigned char * datapacket,int size) { } } -float createfloat(int integer, int decimal) { +static float createfloat(int integer, int decimal) { char flt[1024]; sprintf(flt,"%d.%d",integer,decimal); return atof(flt); } -unsigned int get_vbat() { +static unsigned int get_vbat() { char * v = getval("vbat"); if (v) { return atoi(v); @@ -610,7 +640,7 @@ unsigned int get_vbat() { } } -pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { +static pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { int i = 0; unsigned int vbat = 0; unsigned char checksum = 0x00; @@ -733,7 +763,7 @@ pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodeco return pktdata; } -pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { +static pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { int i = 0; unsigned char checksum = 0x00; pkt_hwinfo pkthwinfo = { @@ -849,7 +879,7 @@ pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { return pkthwinfo; } -int write_serial(int serial_fd, const char * dados, int size) { +static int write_serial(int serial_fd, const char * dados, int size) { if (serial_fd > 0) { ssize_t bytes_written = write(serial_fd, dados, size); if (bytes_written < 0) @@ -862,7 +892,7 @@ int write_serial(int serial_fd, const char * dados, int size) { return serial_fd; } -int write_serial_int(int serial_fd, const unsigned int * data, int size) { +static int write_serial_int(int serial_fd, const unsigned int * data, int size) { uint8_t message[size]; int i = 0; if (serial_fd > 0) { @@ -881,12 +911,12 @@ int write_serial_int(int serial_fd, const unsigned int * data, int size) { return serial_fd; } -char * strtolow(char* s) { +static char * strtolow(char* s) { for(char *p=s; *p; p++) *p=tolower(*p); return s; } -upsinfo getupsinfo(unsigned int upscode) { +static upsinfo getupsinfo(unsigned int upscode) { upsinfo data; switch(upscode) { case 1: @@ -1546,7 +1576,7 @@ upsinfo getupsinfo(unsigned int upscode) { return data; } -unsigned int get_va(int equipment) { +static unsigned int get_va(int equipment) { upsinfo ups; char * va = getval("va"); ups = getupsinfo(equipment); @@ -1560,7 +1590,7 @@ unsigned int get_va(int equipment) { } } -float get_pf() { +static float get_pf(void) { char * pf = getval("pf"); if (pf) return atof(pf); @@ -1568,7 +1598,7 @@ float get_pf() { return DEFAULTPF; } -unsigned int get_ah() { +static unsigned int get_ah(void) { char * ah = getval("ah"); if (ah) return (unsigned int)atoi(ah); @@ -1576,7 +1606,7 @@ unsigned int get_ah() { fatalx(EXIT_FAILURE,"Please set AH (Ampere Hour) value to your battery's equipment in ups.conf."); } -float get_vin_perc(char * var) { +static float get_vin_perc(char * var) { char * perc = getval(var); if (perc) return atof(perc); @@ -1608,11 +1638,11 @@ void upsdrv_initinfo(void) { upsdebugx(1,"End initinfo()"); } -float calculate_efficiency(float vacoutrms, float vacinrms) { +static float calculate_efficiency(float vacoutrms, float vacinrms) { return (vacoutrms * vacinrms) / 100.0; } -unsigned int get_numbat() { +static unsigned int get_numbat(void) { char * nb = getval("numbat"); unsigned int retval = 0; if (nb) From d3f58bdcaf5d9584278f4f550ee435787a495b42 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 11:58:59 +0100 Subject: [PATCH 30/60] drivers/nhs-nut.c: fix compiler complaints - shadowed variables [#2692] nhs_ser.c:519:32: error: declaration shadows a variable in the global scope [-Werror,-Wshadow] static int openfd(const char * porta, int BAUDRATE) { ^ nhs_ser.c:247:13: note: previous declaration is here static char porta[1024] = DEFAULTPORT; ^ nhs_ser.c:1943:42: error: declaration shadows a local variable [-Werror,-Wshadow] for (int i = 0; i < 5; i++) { ^ nhs_ser.c:1657:18: note: previous declaration is here unsigned int i = 0; ^ Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 153 +++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 83410b3b0c..770f72c572 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -356,15 +356,15 @@ static char * strtolow(char* s); static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim); static float calculate_efficiency(float vacoutrms, float vacinrms); -static int openfd(const char * porta, int BAUDRATE); +static int openfd(const char * portarg, int BAUDRATE); static int write_serial(int serial_fd, const char * dados, int size); static int write_serial_int(int serial_fd, const unsigned int * data, int size); static void print_pkt_hwinfo(pkt_hwinfo data); static void print_pkt_data(pkt_data data); -static void pdatapacket(unsigned char * datapacket, int size); -static pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido, pkt_hwinfo pkt_upsinfo); -static pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size); +static void pdatapacket(unsigned char * datapkt, int size); +static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempodecorrido, pkt_hwinfo pkt_upsinfo); +static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size); static upsinfo getupsinfo(unsigned int upscode); static unsigned int get_va(int equipment); @@ -516,27 +516,28 @@ static void print_pkt_data(pkt_data data) { upsdebugx(1,"End Marker: %u", data.end_marker); } -static int openfd(const char * porta, int BAUDRATE) { +/* FIXME: Replace with NUT ser_open() and ser_set_speed() */ +static int openfd(const char * portarg, int BAUDRATE) { long unsigned int i = 0; int done = 0; struct termios tty; struct serial_struct serial; - //int fd = ser_open(porta); - int fd = open(porta, O_RDWR | O_NOCTTY | O_SYNC); + //int fd = ser_open(portarg); + int fd = open(portarg, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { - upsdebugx(1, "Erro on open %s", porta); + upsdebugx(1, "Error on open %s", portarg); return -1; } if (tcflush(fd, TCIOFLUSH) != 0) { - upsdebugx(1, "Error on flush data on %s", porta); + upsdebugx(1, "Error on flush data on %s", portarg); return -1; } if (tcgetattr(fd, &tty) != 0) { - upsdebugx(1, "Erro on set termios values to %s", porta); + upsdebugx(1, "Error on set termios values to %s", portarg); close(fd); return -1; } @@ -599,7 +600,7 @@ static int openfd(const char * porta, int BAUDRATE) { cfsetospeed(&tty, done); if (tcsetattr(fd, TCSANOW, &tty) != 0) { - upsdebugx(1, "Error on tcsetattr on port %s", porta); + upsdebugx(1, "Error on tcsetattr on port %s", portarg); close(fd); return -1; } @@ -614,12 +615,12 @@ static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int f return soma & 0xFF; } -static void pdatapacket(unsigned char * datapacket,int size) { +static void pdatapacket(unsigned char * datapkt, int size) { int i = 0; - if (datapacket != NULL) { + if (datapkt != NULL) { upsdebugx(1,"Received Datapacket: "); for (i = 0; i < size; i++) { - upsdebugx(1,"\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapacket[i], datapacket[i], datapacket[i]); + upsdebugx(1,"\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapkt[i], datapkt[i], datapkt[i]); } } } @@ -640,7 +641,7 @@ static unsigned int get_vbat() { } } -static pkt_data mount_datapacket(unsigned char * datapacket, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { +static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { int i = 0; unsigned int vbat = 0; unsigned char checksum = 0x00; @@ -693,37 +694,37 @@ static pkt_data mount_datapacket(unsigned char * datapacket, int size, double te NUT_UNUSED_VARIABLE(tempodecorrido); - pktdata.length = (int)datapacket[1]; - pktdata.packet_type = datapacket[2]; - pktdata.vacinrms_high = (int)datapacket[3]; - pktdata.vacinrms_low = (int)datapacket[4]; + pktdata.length = (int)datapkt[1]; + pktdata.packet_type = datapkt[2]; + pktdata.vacinrms_high = (int)datapkt[3]; + pktdata.vacinrms_low = (int)datapkt[4]; pktdata.vacinrms = createfloat(pktdata.vacinrms_high,pktdata.vacinrms_low); - pktdata.vdcmed_high = (int)datapacket[5]; - pktdata.vdcmed_low = (int)datapacket[6]; + pktdata.vdcmed_high = (int)datapkt[5]; + pktdata.vdcmed_low = (int)datapkt[6]; pktdata.vdcmed = createfloat(pktdata.vdcmed_high,pktdata.vdcmed_low); pktdata.vdcmed_real = pktdata.vdcmed; if (pktdata.vdcmed_low == 0) pktdata.vdcmed_real = pktdata.vdcmed / 10; - pktdata.potrms = (int)datapacket[7]; - pktdata.vacinrmsmin_high = (int)datapacket[8]; - pktdata.vacinrmsmin_low = (int)datapacket[9]; + pktdata.potrms = (int)datapkt[7]; + pktdata.vacinrmsmin_high = (int)datapkt[8]; + pktdata.vacinrmsmin_low = (int)datapkt[9]; pktdata.vacinrmsmin = createfloat(pktdata.vacinrmsmin_high,pktdata.vacinrmsmin_low); - pktdata.vacinrmsmax_high = (int)datapacket[10]; - pktdata.vacinrmsmax_low = (int)datapacket[11]; + pktdata.vacinrmsmax_high = (int)datapkt[10]; + pktdata.vacinrmsmax_low = (int)datapkt[11]; pktdata.vacinrmsmax = createfloat(pktdata.vacinrmsmax_high,pktdata.vacinrmsmax_low); - pktdata.vacoutrms_high = (int)datapacket[12]; - pktdata.vacoutrms_low = (int)datapacket[13]; + pktdata.vacoutrms_high = (int)datapkt[12]; + pktdata.vacoutrms_low = (int)datapkt[13]; pktdata.vacoutrms = createfloat(pktdata.vacoutrms_high,pktdata.vacoutrms_low); - pktdata.tempmed_high = (int)datapacket[14]; - pktdata.tempmed_low = (int)datapacket[15]; + pktdata.tempmed_high = (int)datapkt[14]; + pktdata.tempmed_low = (int)datapkt[15]; pktdata.tempmed = createfloat(pktdata.tempmed_high,pktdata.tempmed_low); pktdata.tempmed_real = pktdata.tempmed; - pktdata.icarregrms = (int)datapacket[16]; + pktdata.icarregrms = (int)datapkt[16]; // 25 units = 750mA, then 1 unit = 30mA pktdata.icarregrms_real = pktdata.icarregrms * 30; - pktdata.statusval = datapacket[17]; + pktdata.statusval = datapkt[17]; for (i = 0; i < 8; i++) - pktdata.status[i] = get_bit_in_position(&datapacket[17],sizeof(datapacket[17]),i,0); + pktdata.status[i] = get_bit_in_position(&datapkt[17],sizeof(datapkt[17]),i,0); // I don't know WHY, but bit order is INVERTED here. Discovered on clyra's github python implementation // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more pktdata.s_battery_mode = (bool)pktdata.status[7]; @@ -735,8 +736,8 @@ static pkt_data mount_datapacket(unsigned char * datapacket, int size, double te pktdata.s_bypass_on = (bool)pktdata.status[1]; pktdata.s_charger_on = (bool)pktdata.status[0]; // Position 18 mean status, but I won't discover what's it - pktdata.checksum = datapacket[19]; - checksum = calculate_checksum(datapacket,1,18); + pktdata.checksum = datapkt[19]; + checksum = calculate_checksum(datapkt,1,18); pktdata.checksum_calc = checksum; if (pktdata.checksum == checksum) pktdata.checksum_ok = true; @@ -757,13 +758,13 @@ static pkt_data mount_datapacket(unsigned char * datapacket, int size, double te } // end if NUT_UNUSED_VARIABLE(size); - //pdatapacket(datapacket,size); + //pdatapacket(datapkt,size); //print_pkt_data(pktdata); return pktdata; } -static pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { +static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { int i = 0; unsigned char checksum = 0x00; pkt_hwinfo pkthwinfo = { @@ -816,30 +817,30 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { 0xFE // end_marker }; - pkthwinfo.size = (int)datapacket[1]; - pkthwinfo.type = datapacket[2]; - pkthwinfo.model = (int)datapacket[3]; - pkthwinfo.hardwareversion = (int)datapacket[4]; - pkthwinfo.softwareversion = (int)datapacket[5]; - pkthwinfo.configuration = datapacket[6]; + pkthwinfo.size = (int)datapkt[1]; + pkthwinfo.type = datapkt[2]; + pkthwinfo.model = (int)datapkt[3]; + pkthwinfo.hardwareversion = (int)datapkt[4]; + pkthwinfo.softwareversion = (int)datapkt[5]; + pkthwinfo.configuration = datapkt[6]; for (i = 0; i < 5; i++) - pkthwinfo.configuration_array[i] = get_bit_in_position(&datapacket[6],sizeof(datapacket[6]),i,0); + pkthwinfo.configuration_array[i] = get_bit_in_position(&datapkt[6],sizeof(datapkt[6]),i,0); // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more pkthwinfo.c_oem_mode = (bool)pkthwinfo.configuration_array[0]; pkthwinfo.c_buzzer_disable = (bool)pkthwinfo.configuration_array[1]; pkthwinfo.c_potmin_disable = (bool)pkthwinfo.configuration_array[2]; pkthwinfo.c_rearm_enable = (bool)pkthwinfo.configuration_array[3]; pkthwinfo.c_bootloader_enable = (bool)pkthwinfo.configuration_array[4]; - pkthwinfo.numbatteries = (int)datapacket[7]; - pkthwinfo.undervoltagein120V = (int)datapacket[8]; - pkthwinfo.overvoltagein120V = (int)datapacket[9]; - pkthwinfo.undervoltagein220V = (int)datapacket[10]; - pkthwinfo.overvoltagein220V = (int)datapacket[11]; - pkthwinfo.tensionout120V = (int)datapacket[12]; - pkthwinfo.tensionout220V = (int)datapacket[13]; - pkthwinfo.statusval = datapacket[14]; + pkthwinfo.numbatteries = (int)datapkt[7]; + pkthwinfo.undervoltagein120V = (int)datapkt[8]; + pkthwinfo.overvoltagein120V = (int)datapkt[9]; + pkthwinfo.undervoltagein220V = (int)datapkt[10]; + pkthwinfo.overvoltagein220V = (int)datapkt[11]; + pkthwinfo.tensionout120V = (int)datapkt[12]; + pkthwinfo.tensionout220V = (int)datapkt[13]; + pkthwinfo.statusval = datapkt[14]; for (i = 0; i < 6; i++) - pkthwinfo.status[i] = get_bit_in_position(&datapacket[14],sizeof(datapacket[14]),i,0); + pkthwinfo.status[i] = get_bit_in_position(&datapkt[14],sizeof(datapkt[14]),i,0); // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more pkthwinfo.s_220V_in = (bool)pkthwinfo.status[0]; pkthwinfo.s_220V_out = (bool)pkthwinfo.status[1]; @@ -847,35 +848,35 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapacket, int size) { pkthwinfo.s_show_out_tension = (bool)pkthwinfo.status[3]; pkthwinfo.s_show_temperature = (bool)pkthwinfo.status[4]; pkthwinfo.s_show_charger_current = (bool)pkthwinfo.status[5]; - pkthwinfo.chargercurrent = (int)datapacket[15]; + pkthwinfo.chargercurrent = (int)datapkt[15]; if (pkthwinfo.size > 18) { for (i = 0; i < 16; i++) - pkthwinfo.serial[i] = datapacket[16 + i]; - pkthwinfo.year = datapacket[32]; - pkthwinfo.month = datapacket[33]; - pkthwinfo.wday = datapacket[34]; - pkthwinfo.hour = datapacket[35]; - pkthwinfo.minute = datapacket[36]; - pkthwinfo.second = datapacket[37]; - pkthwinfo.alarmyear = datapacket[38]; - pkthwinfo.alarmmonth = datapacket[39]; - pkthwinfo.alarmday = datapacket[40]; - pkthwinfo.alarmhour = datapacket[41]; - pkthwinfo.alarmminute = datapacket[42]; - pkthwinfo.alarmsecond = datapacket[43]; - pkthwinfo.checksum = datapacket[48]; - checksum = calculate_checksum(datapacket,1,47); + pkthwinfo.serial[i] = datapkt[16 + i]; + pkthwinfo.year = datapkt[32]; + pkthwinfo.month = datapkt[33]; + pkthwinfo.wday = datapkt[34]; + pkthwinfo.hour = datapkt[35]; + pkthwinfo.minute = datapkt[36]; + pkthwinfo.second = datapkt[37]; + pkthwinfo.alarmyear = datapkt[38]; + pkthwinfo.alarmmonth = datapkt[39]; + pkthwinfo.alarmday = datapkt[40]; + pkthwinfo.alarmhour = datapkt[41]; + pkthwinfo.alarmminute = datapkt[42]; + pkthwinfo.alarmsecond = datapkt[43]; + pkthwinfo.checksum = datapkt[48]; + checksum = calculate_checksum(datapkt,1,47); } // end if else { - pkthwinfo.checksum = datapacket[16]; - checksum = calculate_checksum(datapacket,1,15); + pkthwinfo.checksum = datapkt[16]; + checksum = calculate_checksum(datapkt,1,15); } pkthwinfo.checksum_calc = checksum; if (pkthwinfo.checksum == checksum) pkthwinfo.checksum_ok = true; print_pkt_hwinfo(pkthwinfo); - pdatapacket(datapacket,size); + pdatapacket(datapkt,size); return pkthwinfo; } @@ -1680,7 +1681,7 @@ void upsdrv_updateinfo(void) { upsdebugx(1,"Start updateinfo()"); if ((serial_fd <= 0) && (i < retries)) { - upsdebugx(1,"Serial problem.."); + upsdebugx(1,"Serial problem..."); while (serial_fd <= 0) { serial_fd = openfd(DEFAULTPORT,2400); upsdebugx(1,"Trying to reopen serial..."); @@ -1939,7 +1940,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); - for (int i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) { // Reusing variable sprintf(alarm,"nhs.hw.configuration_array_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); @@ -1957,7 +1958,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); - for (int i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) { // Reusing variable sprintf(alarm,"nhs.hw.status_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); @@ -2018,7 +2019,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.data.battery_tension", "%0.2f", lastpktdata.battery_tension); dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); - for (int i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { // Reusing variable sprintf(alarm,"nhs.data.status_p%d",i); dstate_setinfo(alarm, "%u", lastpktdata.status[i]); From e912dc9fbd253cf84036d025331eb540f6ba8bfc Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:11:07 +0100 Subject: [PATCH 31/60] drivers/nhs-nut.c: fix compiler complaints - mixing declarations and code [#2692] nhs_ser.c:904:17: error: mixing declarations and code is incompatible with standards before C99 [-Werror,-Wdeclaration-after-statement] ssize_t bytes_written = write(serial_fd, message,size); ^ Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 770f72c572..8411e67a5c 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -897,11 +897,12 @@ static int write_serial_int(int serial_fd, const unsigned int * data, int size) uint8_t message[size]; int i = 0; if (serial_fd > 0) { + ssize_t bytes_written; for (i = 0; i < size; i++) { message[i] = (uint8_t)data[i]; //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); } - ssize_t bytes_written = write(serial_fd, message,size); + bytes_written = write(serial_fd, message,size); if (bytes_written < 0) return -1; if (tcdrain(serial_fd) != 0) @@ -1702,8 +1703,8 @@ void upsdrv_updateinfo(void) { datapacket[datapacket_index] = chr; datapacket_index++; if (chr == 0xFE) { // DataPacket - upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); time_t now = time(NULL); + upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); if (lastdp != 0) { tempodecorrido = difftime(now, lastdp); } From 4ef008ee3804dbbb1078b4360dda10b7389391cb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:16:39 +0100 Subject: [PATCH 32/60] drivers/nhs-nut.c: fix compiler complaints - variable length array [#2692] nhs_ser.c:897:21: error: variable length array used [-Werror,-Wvla] uint8_t message[size]; ^~~~ Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 8411e67a5c..6cf84f29bb 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -894,15 +894,19 @@ static int write_serial(int serial_fd, const char * dados, int size) { } static int write_serial_int(int serial_fd, const unsigned int * data, int size) { - uint8_t message[size]; - int i = 0; if (serial_fd > 0) { ssize_t bytes_written; + uint8_t *message = NULL; + int i = 0; + + message = xcalloc(size, sizeof(uint8_t)); for (i = 0; i < size; i++) { message[i] = (uint8_t)data[i]; //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); } bytes_written = write(serial_fd, message,size); + free(message); + if (bytes_written < 0) return -1; if (tcdrain(serial_fd) != 0) From 278036158d7c25e4ebec1381f4cee129733c7de7 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:25:45 +0100 Subject: [PATCH 33/60] drivers/nhs-nut.c: fix compiler complaints - casting round() to int/long [#2692] This is an odd one, see https://stackoverflow.com/a/43481925/4715872 nhs_ser.c:1865:74: error: cast from function call of type 'double' to non-matching type 'int' [-Werror,-Wbad-function-cast] dstate_setinfo("ups.realpower","%d",(int)round(vpower)); ^~~~~~~~~~~~~ The `lrint()` family of methods should be part of C99 and above, returning a `long` approximation of a `double` or `float` argument. Had to adjust dstate_setinfo() parameters from (unsigned) int to long. Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 6cf84f29bb..50c64fe120 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1676,7 +1676,7 @@ void upsdrv_updateinfo(void) { float calculated = 0; float vpower = 0; float pf = 0; - int bcharge = 0; + long bcharge = 0; int min_input_power = 0; double tempodecorrido = 0.0; unsigned int numbat = 0; @@ -1862,8 +1862,8 @@ void upsdrv_updateinfo(void) { minpower = vpower; dstate_setinfo("ups.power","%0.2f",vpower); dstate_setinfo("ups.power.nominal","%u",va); - dstate_setinfo("ups.realpower","%d",(int)round(vpower)); - dstate_setinfo("ups.realpower.nominal","%d",(int)round(va * pf)); + dstate_setinfo("ups.realpower","%ld",lrint(round(vpower))); + dstate_setinfo("ups.realpower.nominal","%ld",lrint(round(va * pf))); dstate_setinfo("ups.beeper.status","%d",!lastpkthwinfo.c_buzzer_disable); dstate_setinfo("input.voltage","%0.2f",lastpktdata.vacinrms); dstate_setinfo("input.voltage.maximum","%0.2f",lastpktdata.vacinrmsmin); @@ -1904,19 +1904,19 @@ void upsdrv_updateinfo(void) { minpowerperc = lastpktdata.potrms; dstate_setinfo("power.maximum.percent","%u",maxpowerperc); dstate_setinfo("power.minimum.percent","%u",minpowerperc); - dstate_setinfo("realpower","%u",(unsigned int)round(vpower)); - dstate_setinfo("power","%u",(unsigned int)round(va * (lastpktdata.potrms / 100.0))); - bcharge = (int)round((lastpktdata.vdcmed_real * 100) / 12.0); + dstate_setinfo("realpower","%ld",lrint(round(vpower))); + dstate_setinfo("power","%ld",lrint(round(va * (lastpktdata.potrms / 100.0)))); + bcharge = lrint(round((lastpktdata.vdcmed_real * 100) / 12.0)); if (bcharge > 100) bcharge = 100; - dstate_setinfo("battery.charge","%d",bcharge); + dstate_setinfo("battery.charge","%ld",bcharge); dstate_setinfo("battery.voltage","%0.2f",lastpktdata.vdcmed_real); dstate_setinfo("battery.voltage.nominal","%u",vbat); dstate_setinfo("battery.capacity","%u",ah); dstate_setinfo("battery.capacity.nominal","%0.2f",(float)ah * pf); dstate_setinfo("battery.current","%0.2f",abat); dstate_setinfo("battery.current.total","%0.2f",(float)abat * numbat); - dstate_setinfo("battery.temperature","%u",(unsigned int)round(lastpktdata.tempmed_real)); + dstate_setinfo("battery.temperature","%ld",lrint(round(lastpktdata.tempmed_real))); dstate_setinfo("battery.packs","%u",numbat); // We will calculate autonomy in seconds From 99da1a0b9f657991c1ab209c2dbcd99562550023 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:31:27 +0100 Subject: [PATCH 34/60] drivers/nhs-nut.c: fix compiler complaints - comparing floating-points [#2692] nhs_ser.c:1873:74: error: comparing floating point with == or != is unsafe [-Werror,-Wfloat-equal] perc = get_vin_perc("vin_low_warn_perc") == get_vin_perc("vin_low_crit_perc") ? 2 : 1; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 50c64fe120..7973631eb3 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -24,6 +24,7 @@ #include "main.h" #include "common.h" #include "nut_stdint.h" +#include "nut_float.h" #include "serial.h" #include #include @@ -1870,7 +1871,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("input.voltage.minimum","%0.2f",lastpktdata.vacinrmsmax); vin_underv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V; vin_overv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V; - perc = get_vin_perc("vin_low_warn_perc") == get_vin_perc("vin_low_crit_perc") ? 2 : 1; + perc = f_equal(get_vin_perc("vin_low_warn_perc"), get_vin_perc("vin_low_crit_perc")) ? 2 : 1; vin_low_warn = vin_underv + (vin_underv * ((get_vin_perc("vin_low_warn_perc") * perc) / 100.0)); dstate_setinfo("input.voltage.low.warning","%0.2f",calculated); vin_low_crit = vin_underv + (vin_underv * (get_vin_perc("vin_low_crit_perc") / 100.0)); From 3b5e8e9625c10145c9c840c3ee606ab25aafb549 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:31:55 +0100 Subject: [PATCH 35/60] drivers/nhs-nut.c: update (C) heading [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 7973631eb3..3edd5882a9 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -3,7 +3,9 @@ * * * Copyright (C) 2024 - Lucas Willian Bocchi - * Initial Release + * Initial Release (as nhs-nut.c) + * Copyright (C) 2024 - Jim Klimov + * Codebase adjusted to NUT standards * * 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 From 623922897454351d2a198bd103cc91b182c5f9d6 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:35:24 +0100 Subject: [PATCH 36/60] drivers/nhs-nut.c: fix compiler complaints - shadowed variables (serial_fd) [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 3edd5882a9..aeaea799aa 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -360,8 +360,8 @@ static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int f static float calculate_efficiency(float vacoutrms, float vacinrms); static int openfd(const char * portarg, int BAUDRATE); -static int write_serial(int serial_fd, const char * dados, int size); -static int write_serial_int(int serial_fd, const unsigned int * data, int size); +static int write_serial(int fd, const char * dados, int size); +static int write_serial_int(int fd, const unsigned int * data, int size); static void print_pkt_hwinfo(pkt_hwinfo data); static void print_pkt_data(pkt_data data); @@ -883,21 +883,21 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { return pkthwinfo; } -static int write_serial(int serial_fd, const char * dados, int size) { - if (serial_fd > 0) { - ssize_t bytes_written = write(serial_fd, dados, size); +static int write_serial(int fd, const char * dados, int size) { + if (fd > 0) { + ssize_t bytes_written = write(fd, dados, size); if (bytes_written < 0) - return -1; - if (tcdrain(serial_fd) != 0) - return -2; + return -1; + if (tcdrain(fd) != 0) + return -2; return size; } else - return serial_fd; + return fd; } -static int write_serial_int(int serial_fd, const unsigned int * data, int size) { - if (serial_fd > 0) { +static int write_serial_int(int fd, const unsigned int * data, int size) { + if (fd > 0) { ssize_t bytes_written; uint8_t *message = NULL; int i = 0; @@ -907,17 +907,17 @@ static int write_serial_int(int serial_fd, const unsigned int * data, int size) message[i] = (uint8_t)data[i]; //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); } - bytes_written = write(serial_fd, message,size); + bytes_written = write(fd, message, size); free(message); if (bytes_written < 0) return -1; - if (tcdrain(serial_fd) != 0) - return -2; + if (tcdrain(fd) != 0) + return -2; return i; } else - return serial_fd; + return fd; } static char * strtolow(char* s) { From a54581701063239c69448226ea1b874233fe1157 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 12:58:08 +0100 Subject: [PATCH 37/60] docs/man/nhs_ser.txt, drivers/nhs_ser.c: introduce option flags for debug_pkt_raw, debug_pkt_data, debug_pkt_hwinfo [#2692] Also helps avoid dead code and this warning: nhs_ser.c:467:13: error: unused function 'print_pkt_data' [-Werror,-Wunused-function] static void print_pkt_data(pkt_data data) { ^ Signed-off-by: Jim Klimov --- docs/man/nhs_ser.txt | 9 +++++++++ drivers/nhs_ser.c | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/docs/man/nhs_ser.txt b/docs/man/nhs_ser.txt index 5de21745fd..c87627d9a0 100644 --- a/docs/man/nhs_ser.txt +++ b/docs/man/nhs_ser.txt @@ -58,6 +58,15 @@ Num Batteries (override value from nobreak). *vbat*='num':: Battery Voltage (default: 12.00). +*debug_pkt_raw*:: +Optional flag to enable debug logging of packet bytes. + +*debug_pkt_data*:: +Optional flag to enable debug logging of data packet decoding. + +*debug_pkt_hwinfo*:: +Optional flag to enable debug logging of hwinfo packet decoding. + AUTHORS ------- diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index aeaea799aa..e4dee352d5 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -237,6 +237,8 @@ typedef struct { static const unsigned int string_initialization_long[9] = {0xFF, 0x09, 0x53, 0x83, 0x00, 0x00, 0x00, 0xDF, 0xFE}; static const unsigned int string_initialization_short[9] = {0xFF, 0x09, 0x53, 0x03, 0x00, 0x00, 0x00, 0x5F, 0xFE}; +static int debug_pkt_data = 0, debug_pkt_hwinfo = 0, debug_pkt_raw = 0; + static int serial_fd = -1; static unsigned char chr; static int datapacket_index = 0; @@ -398,6 +400,9 @@ static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int } static void print_pkt_hwinfo(pkt_hwinfo data) { + if (!debug_pkt_hwinfo) + return; + upsdebugx(1,"Header: %u", data.header); upsdebugx(1,"Size: %u", data.size); upsdebugx(1,"Type: %c", data.type); @@ -465,6 +470,9 @@ static void print_pkt_hwinfo(pkt_hwinfo data) { } static void print_pkt_data(pkt_data data) { + if (!debug_pkt_data) + return; + upsdebugx(1,"Header: %u", data.header); upsdebugx(1,"Length: %u", data.length); upsdebugx(1,"Packet Type: %c", data.packet_type); @@ -620,6 +628,10 @@ static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int f static void pdatapacket(unsigned char * datapkt, int size) { int i = 0; + + if (!debug_pkt_raw) + return; + if (datapkt != NULL) { upsdebugx(1,"Received Datapacket: "); for (i = 0; i < size; i++) { @@ -760,9 +772,10 @@ static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempo } // end if } // end if - NUT_UNUSED_VARIABLE(size); - //pdatapacket(datapkt,size); - //print_pkt_data(pktdata); + if (debug_pkt_data) { + pdatapacket(datapkt, size); + print_pkt_data(pktdata); + } return pktdata; } @@ -878,8 +891,11 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { if (pkthwinfo.checksum == checksum) pkthwinfo.checksum_ok = true; - print_pkt_hwinfo(pkthwinfo); - pdatapacket(datapkt,size); + if (debug_pkt_hwinfo) { + pdatapacket(datapkt, size); + print_pkt_hwinfo(pkthwinfo); + } + return pkthwinfo; } @@ -2130,6 +2146,15 @@ void upsdrv_cleanup(void) { void upsdrv_initups(void) { upsdebugx(1,"Start initups()"); + + /* Process optional configuration flags */ + if (getval("debug_pkt_raw")) + debug_pkt_raw = 1; + if (getval("debug_pkt_data")) + debug_pkt_data = 1; + if (getval("debug_pkt_hwinfo")) + debug_pkt_hwinfo = 1; + upsdrv_initinfo(); upsdebugx(1,"End initups()"); } @@ -2166,6 +2191,10 @@ void upsdrv_makevartable(void) { snprintf(help, sizeof(help), "Battery Voltage (override default value). Default is %0.2f", DEFAULTBATV); addvar(VAR_VALUE, "vbat", help); + + addvar(VAR_FLAG, "debug_pkt_raw", "Enable debug logging of packet bytes"); + addvar(VAR_FLAG, "debug_pkt_data", "Enable debug logging of data packet decoding"); + addvar(VAR_FLAG, "debug_pkt_hwinfo", "Enable debug logging of hwinfo packet decoding"); } void upsdrv_help(void) { From 8b5544a3c87d3519c3c90c6ae527c31c4003ba98 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 13:01:08 +0100 Subject: [PATCH 38/60] drivers/nhs-nut.c: fix compiler complaints - unused methods [#2692] Hide them away: nhs_ser.c:939:15: error: unused function 'strtolow' [-Werror,-Wunused-function] static char * strtolow(char* s) { ^ nhs_ser.c:902:12: error: unused function 'write_serial' [-Werror,-Wunused-function] static int write_serial(int fd, const char * dados, int size) { ^ 2 errors generated. Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index e4dee352d5..8cddec5013 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -356,13 +356,17 @@ static pkt_data lastpktdata = { /* internal methods */ static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int invertorder); static float createfloat(int integer, int decimal); +#if 0 static char * strtolow(char* s); +#endif static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim); static float calculate_efficiency(float vacoutrms, float vacinrms); static int openfd(const char * portarg, int BAUDRATE); +#if 0 static int write_serial(int fd, const char * dados, int size); +#endif static int write_serial_int(int fd, const unsigned int * data, int size); static void print_pkt_hwinfo(pkt_hwinfo data); @@ -899,6 +903,7 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { return pkthwinfo; } +#if 0 static int write_serial(int fd, const char * dados, int size) { if (fd > 0) { ssize_t bytes_written = write(fd, dados, size); @@ -911,6 +916,7 @@ static int write_serial(int fd, const char * dados, int size) { else return fd; } +#endif static int write_serial_int(int fd, const unsigned int * data, int size) { if (fd > 0) { @@ -936,10 +942,12 @@ static int write_serial_int(int fd, const unsigned int * data, int size) { return fd; } +#if 0 static char * strtolow(char* s) { - for(char *p=s; *p; p++) *p=tolower(*p); - return s; + for(char *p=s; *p; p++) *p=tolower(*p); + return s; } +#endif static upsinfo getupsinfo(unsigned int upscode) { upsinfo data; From 0efde2a23e38638e559488bfdda6fbeb830346aa Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Wed, 27 Nov 2024 09:09:45 -0300 Subject: [PATCH 39/60] Error on line 1717, on function to reopen serial in case of problem. We have default values but I set with variable porta and baudrate the correct port and speed. Signed-off-by: Lucas Willian Bocchi lucas@lucas.inf.br --- drivers/nhs_ser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 8cddec5013..8564ef37e8 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1715,7 +1715,7 @@ void upsdrv_updateinfo(void) { if ((serial_fd <= 0) && (i < retries)) { upsdebugx(1,"Serial problem..."); while (serial_fd <= 0) { - serial_fd = openfd(DEFAULTPORT,2400); + serial_fd = openfd(porta,baudrate); upsdebugx(1,"Trying to reopen serial..."); usleep(checktime); retries++; From 2ad3f52f2a1ed99f73cf4bb7adaf84c4de2f7cc3 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Wed, 27 Nov 2024 13:14:59 +0100 Subject: [PATCH 40/60] drivers/nhs-nut.c: fix compiler complaints - float overflow [#2692] CodeQL alert: * Multiplication result converted to larger type High * Multiplication result may overflow 'float' before it is converted to 'double'. Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 8564ef37e8..ba04a3c4a2 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1890,7 +1890,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("ups.power","%0.2f",vpower); dstate_setinfo("ups.power.nominal","%u",va); dstate_setinfo("ups.realpower","%ld",lrint(round(vpower))); - dstate_setinfo("ups.realpower.nominal","%ld",lrint(round(va * pf))); + dstate_setinfo("ups.realpower.nominal","%ld",lrint(round((double)va * (double)pf))); dstate_setinfo("ups.beeper.status","%d",!lastpkthwinfo.c_buzzer_disable); dstate_setinfo("input.voltage","%0.2f",lastpktdata.vacinrms); dstate_setinfo("input.voltage.maximum","%0.2f",lastpktdata.vacinrmsmin); From 20c583bf362b9f7e3a88c5db416bcefc60ab4f52 Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Thu, 28 Nov 2024 13:59:30 -0300 Subject: [PATCH 41/60] Change on line 1936 - Battery voltage hardcoded in 12.0 v Signed-off-by: Lucas Willian Bocchi lucas@lucas.inf.br --- drivers/nhs_ser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index ba04a3c4a2..b5c1d63f75 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1933,7 +1933,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("power.minimum.percent","%u",minpowerperc); dstate_setinfo("realpower","%ld",lrint(round(vpower))); dstate_setinfo("power","%ld",lrint(round(va * (lastpktdata.potrms / 100.0)))); - bcharge = lrint(round((lastpktdata.vdcmed_real * 100) / 12.0)); + bcharge = lrint(round((lastpktdata.vdcmed_real * 100) / vbat)); if (bcharge > 100) bcharge = 100; dstate_setinfo("battery.charge","%ld",bcharge); From e0bd695f5fef46eeb09b0eefd71339337f3b2fed Mon Sep 17 00:00:00 2001 From: Lucas Bocchi Date: Thu, 28 Nov 2024 19:08:56 -0300 Subject: [PATCH 42/60] Another miscalculation in battery time duration. Signed-off-by: Lucas Willian Bocchi lucas@lucas.inf.br --- drivers/nhs_ser.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index b5c1d63f75..968228f77a 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1709,6 +1709,7 @@ void upsdrv_updateinfo(void) { unsigned int numbat = 0; unsigned int vbat = 0; float abat = 0; + float actual_current = 0; upsinfo ups; upsdebugx(1,"Start updateinfo()"); @@ -1945,14 +1946,18 @@ void upsdrv_updateinfo(void) { dstate_setinfo("battery.current.total","%0.2f",(float)abat * numbat); dstate_setinfo("battery.temperature","%ld",lrint(round(lastpktdata.tempmed_real))); dstate_setinfo("battery.packs","%u",numbat); - // We will calculate autonomy in seconds - - // Autonomy calculation in NHS nobreaks is a rocket science. Some are one, some are other. I'll do my best to put one that works in 4 models that I have here. - // That result is IN HOURS. We need to convert it on seconds - //autonomy_secs = (int)round((ah / (vpower / lastpktdata.vdcmed_real)) * 3600); - autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; - //upsdebugx(1,"(numbat * lastpktdata.vdcmed_real * va * pf) / ((lastpktdata.potrms * va * pf) / 100.0) = (%d * %0.2f * %d * %0.2f) / ((%d * %d * %0.2f) / 100.0) --> %0.2f",numbat,lastpktdata.vdcmed_real,va,pf,lastpktdata.potrms,va,pf,autonomy_secs); + /* We will calculate autonomy in seconds + autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; + Maybe wrong, too. + People says that the correct calculation is + + Battery Amp-Hour / (Power in Watts / battery voltage) + + Is that correct? I don't know. I'll use it for now. + */ // That result is IN HOURS. We need to convert it on seconds + actual_current = vpower / vbat; /* Current consumption in A*/ + autonomy_secs = (ah / actual_current) * 3600; dstate_setinfo("battery.runtime","%u",autonomy_secs); dstate_setinfo("battery.runtime.low","%u",30); From c63b37c4a111c954515fab9f0500792f86f073c9 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:01:30 +0100 Subject: [PATCH 43/60] drivers/nhs_ser.c: upsdrv_updateinfo(): refactor debug of bad mains [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 968228f77a..034bd8a1d7 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1806,10 +1806,15 @@ void upsdrv_updateinfo(void) { } // end if } // end if else { - // Check if MAINS (power) is not preset. Well, we can check pkt_data.s_network_failure too... + /* Check if MAINS (power) is not preset. + * Well, we can check pkt_data.s_network_failure too... */ if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { - sprintf(alarm,"UPS have power in %0.2f value and min_input_power is %d or network is in failure. Network failure is %d",lastpktdata.vacinrms,min_input_power,lastpktdata.s_network_failure); - upsdebugx(1,"%s",alarm); + upsdebugx(1, "UPS has power-in value %0.2f " + "and min_input_power is %d, " + "or network is in failure. Network failure is %d", + lastpktdata.vacinrms, + min_input_power, + lastpktdata.s_network_failure); dstate_setinfo("ups.status","%s","DISCHRG"); } // end if else { From 2750a6bda054ee1ce4a2e7206966a49a743f8f3d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:09:46 +0100 Subject: [PATCH 44/60] drivers/nhs-nut.c: fix compiler complaints - sprintf() from and to same variable [#2692] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nhs_ser.c: In function ‘upsdrv_updateinfo’: nhs_ser.c:1858:37: error: ‘sprintf’ argument 3 overlaps destination object ‘alarm’ [-Werror=restrict] 1858 | sprintf(alarm,"%s %s",alarm,"|UPS IN BATTERY MODE|"); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 034bd8a1d7..8fa21ed5e0 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1848,7 +1848,6 @@ void upsdrv_updateinfo(void) { } // end else } // end else - alarm[0] = '\0'; numbat = get_numbat(); if (numbat == 0) numbat = lastpkthwinfo.numbatteries; @@ -1856,23 +1855,32 @@ void upsdrv_updateinfo(void) { upsdebugx(1,"Number of batteries is set to %d",numbat); vbat = get_vbat(); ah = get_ah(); - // Set all alarms possible + + /* Set all alarms possible */ + alarm[0] = '\0'; if (lastpktdata.s_battery_mode) - sprintf(alarm,"%s","|UPS IN BATTERY MODE|"); + snprintf(alarm, sizeof(alarm), "%s", "|UPS IN BATTERY MODE|"); if (lastpktdata.s_battery_low) - sprintf(alarm,"%s %s",alarm,"|UPS IN BATTERY MODE|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|UPS IN BATTERY MODE|"); if (lastpktdata.s_network_failure) - sprintf(alarm,"%s %s",alarm,"|NETWORK FAILURE|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|NETWORK FAILURE|"); if (lastpktdata.s_fast_network_failure) - sprintf(alarm,"%s %s",alarm,"|FAST NETWORK FAILURE|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|FAST NETWORK FAILURE|"); if (lastpktdata.s_fast_network_failure) - sprintf(alarm,"%s %s",alarm,"|220v IN|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|220v IN|"); if (lastpktdata.s_fast_network_failure) - sprintf(alarm,"%s %s",alarm,"|220v OUT|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|220v OUT|"); if (lastpktdata.s_bypass_on) - sprintf(alarm,"%s %s",alarm,"|BYPASS ON|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|BYPASS ON|"); if (lastpktdata.s_charger_on) - sprintf(alarm,"%s %s",alarm,"|CHARGER ON|"); + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|CHARGER ON|"); dstate_setinfo("ups.alarm","%s",alarm); dstate_setinfo("ups.model","%s",ups.upsdesc); dstate_setinfo("ups.mfr","%s",MANUFACTURER); From b5c878defb9be55857f1e04e32cd3c180f8ebeb4 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 00:45:17 +0000 Subject: [PATCH 45/60] drivers/nhs_ser.c: fix comment markup, wrap long lines, inject TABs in structs [#2692] Also drop comments from standalone program legacy now that this driver is an integrated part of NUT codebase. Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 727 +++++++++++++++++++++++----------------------- 1 file changed, 368 insertions(+), 359 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 8fa21ed5e0..8a31c5ab3b 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -42,62 +42,33 @@ #include #include -/* Instructions to compile - 1) apt update - 2) apt install build-essential autoconf libtool pkg-config libusb-1.0-0-dev libssl-dev git - 3) Download NUT source code OR use apt-source to download source from your distribution (in case of debian/ubuntu). How to do it? apt-get source nut, apt-get build-dep nut, make your alterations in code (follow the steps above), dpkg-buildpackage -us -uc, dpkg -i * ./autogen.sh - 4) ./autogen.sh - 5) ./ci_build.sh - 6) ./configure $COMPILEFLAGS --with-dev - 7) cd drivers - 8) make (to generate nut_version.h) - - If you can use debian / ubuntu packages to do that: - 1) apt-get source nut - 2) apt-get build-dep nut - 3) extract flags to correct compilation with COMPILEFLAGS=$(make -f debian/rules -pn | grep '^DEB_CONFIGURE_EXTRA_FLAGS' | sed 's/^DEB_CONFIGURE_EXTRA_FLAGS := //') on root source directory - 4) Follow steps 4 to 8 earlier (ignore errors if you can only compile to use the driver with actual nut compiled debian instalation, it's only to generate nut_version.h) - 5) back to root nut source directory, then dpkg-buildpackage -us -uc - 6) dpkg -i - - * gcc -g -O0 -o nhs_ser nhs_ser.c main.c dstate.c serial.c ../common/common.c ../common/parseconf.c ../common/state.c ../common/str.c ../common/upsconf.c -I../include -lm - * upsdrvquery.c (optional) - * copy nhs_ser to nut driver's directory and test - To debug: - * clang --analyze -I../include nhs_ser.c - * cppcheck nhs_ser.c - * upsdrvctl -D start - * nhs_ser -a -D - * upsd -D -*/ - -#define DEFAULTBAUD 2400 -#define DEFAULTPORT "/dev/ttyACM0" -#define DEFAULTPF 0.9 -#define DEFAULLTPERC 2.0 -#define DATAPACKETSIZE 100 -#define DEFAULTBATV 12.0 - -#define DRIVER_NAME "NHS Nobreak Drivers" -#define DRIVER_VERSION "0.01" -#define MANUFACTURER "NHS Sistemas Eletronicos LTDA" +#define DRIVER_NAME "NHS Nobreak Drivers" +#define DRIVER_VERSION "0.01" +#define MANUFACTURER "NHS Sistemas Eletronicos LTDA" + +#define DEFAULTBAUD 2400 +#define DEFAULTPORT "/dev/ttyACM0" +#define DEFAULTPF 0.9 +#define DEFAULLTPERC 2.0 +#define DATAPACKETSIZE 100 +#define DEFAULTBATV 12.0 /* driver description structure */ upsdrv_info_t upsdrv_info = { - DRIVER_NAME, - DRIVER_VERSION, - "Lucas Willian Bocchi ", - DRV_BETA, - { NULL } + DRIVER_NAME, + DRIVER_VERSION, + "Lucas Willian Bocchi ", + DRV_BETA, + { NULL } }; -// Struct to represent serial conventions in termios.h +/* Struct to represent serial conventions in termios.h */ typedef struct { - speed_t rate; // Constant in termios.h - int speed; // Numeric speed, used on NUT - const char * description; // Description + speed_t rate; /* Constant in termios.h */ + int speed; /* Numeric speed, used in NUT */ + const char *description; /* Description */ } baud_rate_t; static baud_rate_t baud_rates[] = { @@ -129,7 +100,7 @@ static baud_rate_t baud_rates[] = { }; #define NUM_BAUD_RATES (sizeof(baud_rates) / sizeof(baud_rates[0])) -// Struct that contain nobreak info +/* Struct that contains nobreak info */ typedef struct { unsigned int header; unsigned int size; @@ -180,7 +151,7 @@ typedef struct { unsigned int end_marker; } pkt_hwinfo; -// Struct that contain the +/* Struct that contains the data packet info */ typedef struct { unsigned int header; unsigned int length; @@ -228,7 +199,8 @@ typedef struct { unsigned int end_marker; } pkt_data; - typedef struct { +/* struct that describes the nobreak model */ +typedef struct { unsigned int upscode; char upsdesc[100]; unsigned int VA; @@ -244,8 +216,8 @@ static unsigned char chr; static int datapacket_index = 0; static bool datapacketstart = false; static time_t lastdp = 0; -static unsigned int checktime = 2000000; // 2 second -static unsigned int max_checktime = 6000000; // max wait time -- 6 seconds +static unsigned int checktime = 2000000; /* 2 seconds */ +static unsigned int max_checktime = 6000000; /* max wait time: 6 seconds */ static unsigned int send_extended = 0; static int bwritten = 0; static unsigned char datapacket[DATAPACKETSIZE]; @@ -257,100 +229,100 @@ static unsigned int minpowerperc = 0; static unsigned int maxpowerperc = 0; static pkt_hwinfo lastpkthwinfo = { - 0xFF, // header - 0, // size - 'S', // type - 0, // model - 0, // hardwareversion - 0, // softwareversion - 0, // configuration - {0, 0, 0, 0, 0}, // configuration_array - false, // c_oem_mode - false, // c_buzzer_disable - false, // c_potmin_disable - false, // c_rearm_enable - false, // c_bootloader_enable - 0, // numbatteries - 0, // undervoltagein120V - 0, // overvoltagein120V - 0, // undervoltagein220V - 0, // overvoltagein220V - 0, // tensionout120V - 0, // tensionout220V - 0, // statusval - {0, 0, 0, 0, 0, 0}, // status - false, // s_220V_in - false, // s_220V_out - false, // s_sealed_battery - false, // s_show_out_tension - false, // s_show_temperature - false, // s_show_charger_current - 0, // chargercurrent - 0, // checksum - 0, // checksum_calc - false, // checksum_ok - "----------------", // serial - 0, // year - 0, // month - 0, // wday - 0, // hour - 0, // minute - 0, // second - 0, // alarmyear - 0, // alarmmonth - 0, // alarmwday - 0, // alarmday - 0, // alarmhour - 0, // alarmminute - 0, // alarmsecond - 0xFE // end_marker + 0xFF, /* header */ + 0, /* size */ + 'S', /* type */ + 0, /* model */ + 0, /* hardwareversion */ + 0, /* softwareversion */ + 0, /* configuration */ + {0, 0, 0, 0, 0}, /* configuration_array */ + false, /* c_oem_mode */ + false, /* c_buzzer_disable */ + false, /* c_potmin_disable */ + false, /* c_rearm_enable */ + false, /* c_bootloader_enable */ + 0, /* numbatteries */ + 0, /* undervoltagein120V */ + 0, /* overvoltagein120V */ + 0, /* undervoltagein220V */ + 0, /* overvoltagein220V */ + 0, /* tensionout120V */ + 0, /* tensionout220V */ + 0, /* statusval */ + {0, 0, 0, 0, 0, 0}, /* status */ + false, /* s_220V_in */ + false, /* s_220V_out */ + false, /* s_sealed_battery */ + false, /* s_show_out_tension */ + false, /* s_show_temperature */ + false, /* s_show_charger_current */ + 0, /* chargercurrent */ + 0, /* checksum */ + 0, /* checksum_calc */ + false, /* checksum_ok */ + "----------------", /* serial */ + 0, /* year */ + 0, /* month */ + 0, /* wday */ + 0, /* hour */ + 0, /* minute */ + 0, /* second */ + 0, /* alarmyear */ + 0, /* alarmmonth */ + 0, /* alarmwday */ + 0, /* alarmday */ + 0, /* alarmhour */ + 0, /* alarmminute */ + 0, /* alarmsecond */ + 0xFE /* end_marker */ }; static pkt_data lastpktdata = { - 0xFF, // header - 0x21, // length - 'D', // packet_type - 0, // vacinrms_high - 0, // vacinrms_low - 0, // vacinrms - 0, // vdcmed_high - 0, // vdcmed_low - 0, // vdcmed - 0, // vdcmed_real - 0, // potrms - 0, // vacinrmsmin_high - 0, // vacinrmsmin_low - 0, // vacinrmsmin - 0, // vacinrmsmax_high - 0, // vacinrmsmax_low - 0, // vacinrmsmax - 0, // vacoutrms_high - 0, // vacoutrms_low - 0, // vacoutrms - 0, // tempmed_high - 0, // tempmed_low - 0, // tempmed - 0, // tempmed_real - 0, // icarregrms - 0, // icarregrms_real - 0, // battery_tension - 0, // perc_output - 0, // statusval - {0, 0, 0, 0, 0, 0, 0, 0}, // status - 0, // nominaltension - 0.0f, // timeremain - false, // s_battery_mode - false, // s_battery_low - false, // s_network_failure - false, // s_fast_network_failure - false, // s_220_in - false, // s_220_out - false, // s_bypass_on - false, // s_charger_on - 0, // checksum - 0, // checksum_calc - false, // checksum_ok - 0xFE // end_marker + 0xFF, /* header */ + 0x21, /* length */ + 'D', /* packet_type */ + 0, /* vacinrms_high */ + 0, /* vacinrms_low */ + 0, /* vacinrms */ + 0, /* vdcmed_high */ + 0, /* vdcmed_low */ + 0, /* vdcmed */ + 0, /* vdcmed_real */ + 0, /* potrms */ + 0, /* vacinrmsmin_high */ + 0, /* vacinrmsmin_low */ + 0, /* vacinrmsmin */ + 0, /* vacinrmsmax_high */ + 0, /* vacinrmsmax_low */ + 0, /* vacinrmsmax */ + 0, /* vacoutrms_high */ + 0, /* vacoutrms_low */ + 0, /* vacoutrms */ + 0, /* tempmed_high */ + 0, /* tempmed_low */ + 0, /* tempmed */ + 0, /* tempmed_real */ + 0, /* icarregrms */ + 0, /* icarregrms_real */ + 0, /* battery_tension */ + 0, /* perc_output */ + 0, /* statusval */ + {0, 0, 0, 0, 0, 0, 0, 0}, /* status */ + 0, /* nominaltension */ + 0.0f, /* timeremain */ + false, /* s_battery_mode */ + false, /* s_battery_low */ + false, /* s_network_failure */ + false, /* s_fast_network_failure */ + false, /* s_220_in */ + false, /* s_220_out */ + false, /* s_bypass_on */ + false, /* s_charger_on */ + 0, /* checksum */ + 0, /* checksum_calc */ + false, /* checksum_ok */ + 0xFE /* end_marker */ }; /* internal methods */ @@ -393,7 +365,7 @@ static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int size_t bit_index = bit_position % 8; if (bit_position >= size * 8) { - return -3; // Invalid Position + return -3; /* Invalid Position */ } if (invertorder == 0) @@ -538,8 +510,7 @@ static int openfd(const char * portarg, int BAUDRATE) { struct termios tty; struct serial_struct serial; - - //int fd = ser_open(portarg); + /* //int fd = ser_open(portarg); */ int fd = open(portarg, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { upsdebugx(1, "Error on open %s", portarg); @@ -561,7 +532,7 @@ static int openfd(const char * portarg, int BAUDRATE) { ioctl(fd, TIOCSSERIAL, &serial); - // select speed based on baud + /* select speed based on baud */ while ((i < NUM_BAUD_RATES) && (done == 0)) { if (baud_rates[i].speed == BAUDRATE) { done = baud_rates[i].rate; @@ -570,7 +541,7 @@ static int openfd(const char * portarg, int BAUDRATE) { i++; } - // if done is 0, no one speed has selected, then use default + /* if done is 0, no one speed has selected, then use default */ if (done == 0) { while ((i < NUM_BAUD_RATES) && (done == 0)) { if (baud_rates[i].speed == DEFAULTBAUD) { @@ -587,26 +558,28 @@ static int openfd(const char * portarg, int BAUDRATE) { } - tty.c_cflag &= ~PARENB; // Disable Parity - tty.c_cflag &= ~CSTOPB; // 1 stop bit - tty.c_cflag &= ~CSIZE; // Clear Bit Set - tty.c_cflag |= CS8; // 8 bits per byte + tty.c_cflag &= ~PARENB; /* Disable Parity */ + tty.c_cflag &= ~CSTOPB; /* 1 stop bit */ + tty.c_cflag &= ~CSIZE; /* Clear Bit Set */ + tty.c_cflag |= CS8; /* 8 bits per byte */ - // CTS / RTS - tty.c_cflag |= CRTSCTS; // Enable hardware flow control + /* CTS / RTS */ + tty.c_cflag |= CRTSCTS; /* Enable hardware flow control */ - // Enable Read and disable modem control - //tty.c_cflag |= (CLOCAL | CREAD); + /* Enable Read and disable modem control */ + /* // tty.c_cflag |= (CLOCAL | CREAD); */ tty.c_cflag |= CREAD; - tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable Software Control + tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable Software Control */ tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); - tty.c_oflag &= ~OPOST; // Disable output post-processing - tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); // Modo raw - // To enable block read: VTIME = 1 and VMIN = 0 - // To disable block read: VTIME = 0 and VMIN = 1 + tty.c_oflag &= ~OPOST; /* Disable output post-processing */ + tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); /* Modo raw */ + + /* To enable block read: VTIME = 1 and VMIN = 0 + * To disable block read: VTIME = 0 and VMIN = 1 + */ tty.c_cc[VTIME] = 1; tty.c_cc[VMIN] = 0; @@ -665,50 +638,50 @@ static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempo unsigned int vbat = 0; unsigned char checksum = 0x00; pkt_data pktdata = { - 0xFF, // header - 0x21, // length - 'D', // packet_type - 0, // vacinrms_high - 0, // vacinrms_low - 0, // vacinrms - 0, // vdcmed_high - 0, // vdcmed_low - 0, // vdcmed - 0, // vdcmed_real - 0, // potrms - 0, // vacinrmsmin_high - 0, // vacinrmsmin_low - 0, // vacinrmsmin - 0, // vacinrmsmax_high - 0, // vacinrmsmax_low - 0, // vacinrmsmax - 0, // vacoutrms_high - 0, // vacoutrms_low - 0, // vacoutrms - 0, // tempmed_high - 0, // tempmed_low - 0, // tempmed - 0, // tempmed_real - 0, // icarregrms - 0, // icarregrms_real - 0, // battery_tension - 0, // perc_output - 0, // statusval - {0, 0, 0, 0, 0, 0, 0, 0}, // status - 0, // nominaltension - 0.0f, // timeremain - false, // s_battery_mode - false, // s_battery_low - false, // s_network_failure - false, // s_fast_network_failure - false, // s_220_in - false, // s_220_out - false, // s_bypass_on - false, // s_charger_on - 0, // checksum - 0, // checksum_calc - false, // checksum_ok - 0xFE // end_marker + 0xFF, /* header */ + 0x21, /* length */ + 'D', /* packet_type */ + 0, /* vacinrms_high */ + 0, /* vacinrms_low */ + 0, /* vacinrms */ + 0, /* vdcmed_high */ + 0, /* vdcmed_low */ + 0, /* vdcmed */ + 0, /* vdcmed_real */ + 0, /* potrms */ + 0, /* vacinrmsmin_high */ + 0, /* vacinrmsmin_low */ + 0, /* vacinrmsmin */ + 0, /* vacinrmsmax_high */ + 0, /* vacinrmsmax_low */ + 0, /* vacinrmsmax */ + 0, /* vacoutrms_high */ + 0, /* vacoutrms_low */ + 0, /* vacoutrms */ + 0, /* tempmed_high */ + 0, /* tempmed_low */ + 0, /* tempmed */ + 0, /* tempmed_real */ + 0, /* icarregrms */ + 0, /* icarregrms_real */ + 0, /* battery_tension */ + 0, /* perc_output */ + 0, /* statusval */ + {0, 0, 0, 0, 0, 0, 0, 0}, /* status */ + 0, /* nominaltension */ + 0.0f, /* timeremain */ + false, /* s_battery_mode */ + false, /* s_battery_low */ + false, /* s_network_failure */ + false, /* s_fast_network_failure */ + false, /* s_220_in */ + false, /* s_220_out */ + false, /* s_bypass_on */ + false, /* s_charger_on */ + 0, /* checksum */ + 0, /* checksum_calc */ + false, /* checksum_ok */ + 0xFE /* end_marker */ }; NUT_UNUSED_VARIABLE(tempodecorrido); @@ -739,13 +712,19 @@ static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempo pktdata.tempmed = createfloat(pktdata.tempmed_high,pktdata.tempmed_low); pktdata.tempmed_real = pktdata.tempmed; pktdata.icarregrms = (int)datapkt[16]; - // 25 units = 750mA, then 1 unit = 30mA + /* 25 units = 750mA, then 1 unit = 30mA */ pktdata.icarregrms_real = pktdata.icarregrms * 30; pktdata.statusval = datapkt[17]; for (i = 0; i < 8; i++) pktdata.status[i] = get_bit_in_position(&datapkt[17],sizeof(datapkt[17]),i,0); - // I don't know WHY, but bit order is INVERTED here. Discovered on clyra's github python implementation - // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more + + /* I don't know WHY, but bit order is INVERTED here. + * Discovered on clyra's github python implementation + */ + /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) + * have same problem. I won't have so much equipment to test + * these, then we need help to test more + */ pktdata.s_battery_mode = (bool)pktdata.status[7]; pktdata.s_battery_low = (bool)pktdata.status[6]; pktdata.s_network_failure = (bool)pktdata.status[5]; @@ -754,27 +733,31 @@ static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempo pktdata.s_220_out = (bool)pktdata.status[2]; pktdata.s_bypass_on = (bool)pktdata.status[1]; pktdata.s_charger_on = (bool)pktdata.status[0]; - // Position 18 mean status, but I won't discover what's it + /* Position 18 means status, but I won't discover what's it */ pktdata.checksum = datapkt[19]; checksum = calculate_checksum(datapkt,1,18); pktdata.checksum_calc = checksum; if (pktdata.checksum == checksum) pktdata.checksum_ok = true; - // Then, the calculations to obtain some useful information + /* Then, the calculations to obtain some useful information */ if (pkt_upsinfo.size > 0) { pktdata.battery_tension = pkt_upsinfo.numbatteries * pktdata.vdcmed_real; - // Calculate battery percent utilization - // if one battery cell have 12v, then the maximum out tension is numbatteries * 12v - // This is the watermark to low battery - // TODO: test with external battery bank to see if calculation is valid. Can generate false positive + /* Calculate battery percent utilization: + * if one battery cell has 12V, then the + * maximum out voltage is `numbatteries * 12V` + * This is the watermark to low battery + */ + /* TODO: test with external battery bank to see if + * calculation is valid. Can generate false positive + */ vbat = get_vbat(); pktdata.nominaltension = vbat * pkt_upsinfo.numbatteries; if (pktdata.nominaltension > 0) { pktdata.perc_output = (pktdata.battery_tension * 100) / pktdata.nominaltension; if (pktdata.perc_output > 100) pktdata.perc_output = 100; - } // end if - } // end if + } /* end if */ + } /* end if */ if (debug_pkt_data) { pdatapacket(datapkt, size); @@ -788,53 +771,53 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { int i = 0; unsigned char checksum = 0x00; pkt_hwinfo pkthwinfo = { - 0xFF, // header - 0, // size - 'S', // type - 0, // model - 0, // hardwareversion - 0, // softwareversion - 0, // configuration - {0, 0, 0, 0, 0}, // configuration_array - false, // c_oem_mode - false, // c_buzzer_disable - false, // c_potmin_disable - false, // c_rearm_enable - false, // c_bootloader_enable - 0, // numbatteries - 0, // undervoltagein120V - 0, // overvoltagein120V - 0, // undervoltagein220V - 0, // overvoltagein220V - 0, // tensionout120V - 0, // tensionout220V - 0, // statusval - {0, 0, 0, 0, 0, 0}, // status - false, // s_220V_in - false, // s_220V_out - false, // s_sealed_battery - false, // s_show_out_tension - false, // s_show_temperature - false, // s_show_charger_current - 0, // chargercurrent - 0, // checksum - 0, // checksum_calc - false, // checksum_ok - "----------------", // serial - 0, // year - 0, // month - 0, // wday - 0, // hour - 0, // minute - 0, // second - 0, // alarmyear - 0, // alarmmonth - 0, // alarmwday - 0, // alarmday - 0, // alarmhour - 0, // alarmminute - 0, // alarmsecond - 0xFE // end_marker + 0xFF, /* header */ + 0, /* size */ + 'S', /* type */ + 0, /* model */ + 0, /* hardwareversion */ + 0, /* softwareversion */ + 0, /* configuration */ + {0, 0, 0, 0, 0}, /* configuration_array */ + false, /* c_oem_mode */ + false, /* c_buzzer_disable */ + false, /* c_potmin_disable */ + false, /* c_rearm_enable */ + false, /* c_bootloader_enable */ + 0, /* numbatteries */ + 0, /* undervoltagein120V */ + 0, /* overvoltagein120V */ + 0, /* undervoltagein220V */ + 0, /* overvoltagein220V */ + 0, /* tensionout120V */ + 0, /* tensionout220V */ + 0, /* statusval */ + {0, 0, 0, 0, 0, 0}, /* status */ + false, /* s_220V_in */ + false, /* s_220V_out */ + false, /* s_sealed_battery */ + false, /* s_show_out_tension */ + false, /* s_show_temperature */ + false, /* s_show_charger_current */ + 0, /* chargercurrent */ + 0, /* checksum */ + 0, /* checksum_calc */ + false, /* checksum_ok */ + "----------------", /* serial */ + 0, /* year */ + 0, /* month */ + 0, /* wday */ + 0, /* hour */ + 0, /* minute */ + 0, /* second */ + 0, /* alarmyear */ + 0, /* alarmmonth */ + 0, /* alarmwday */ + 0, /* alarmday */ + 0, /* alarmhour */ + 0, /* alarmminute */ + 0, /* alarmsecond */ + 0xFE /* end_marker */ }; pkthwinfo.size = (int)datapkt[1]; @@ -845,7 +828,9 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { pkthwinfo.configuration = datapkt[6]; for (i = 0; i < 5; i++) pkthwinfo.configuration_array[i] = get_bit_in_position(&datapkt[6],sizeof(datapkt[6]),i,0); - // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more + /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) + * have same problem. I won't have so much equipment to test + * these, then we need help to test more */ pkthwinfo.c_oem_mode = (bool)pkthwinfo.configuration_array[0]; pkthwinfo.c_buzzer_disable = (bool)pkthwinfo.configuration_array[1]; pkthwinfo.c_potmin_disable = (bool)pkthwinfo.configuration_array[2]; @@ -861,7 +846,9 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { pkthwinfo.statusval = datapkt[14]; for (i = 0; i < 6; i++) pkthwinfo.status[i] = get_bit_in_position(&datapkt[14],sizeof(datapkt[14]),i,0); - // TODO: check if ANOTHER VARIABLES (like hardware array bits) have same problem. I won't have so much equipment to test these, then we need help to test more + /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) + * have same problem. I won't have so much equipment to test + * these, then we need help to test more */ pkthwinfo.s_220V_in = (bool)pkthwinfo.status[0]; pkthwinfo.s_220V_out = (bool)pkthwinfo.status[1]; pkthwinfo.s_sealed_battery = (bool)pkthwinfo.status[2]; @@ -886,7 +873,7 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { pkthwinfo.alarmsecond = datapkt[43]; pkthwinfo.checksum = datapkt[48]; checksum = calculate_checksum(datapkt,1,47); - } // end if + } /* end if */ else { pkthwinfo.checksum = datapkt[16]; checksum = calculate_checksum(datapkt,1,15); @@ -927,7 +914,7 @@ static int write_serial_int(int fd, const unsigned int * data, int size) { message = xcalloc(size, sizeof(uint8_t)); for (i = 0; i < size; i++) { message[i] = (uint8_t)data[i]; - //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); + /* //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); */ } bytes_written = write(fd, message, size); free(message); @@ -1684,7 +1671,7 @@ static unsigned int get_numbat(void) { } void upsdrv_updateinfo(void) { - // retries to open port + /* retries to open port */ unsigned int retries = 3; unsigned int i = 0; char alarm[1024]; @@ -1723,69 +1710,79 @@ void upsdrv_updateinfo(void) { } } else { - // Clean all read buffers to avoid errors - // To clean OUTPUT buffer is TCOFLUSH. To both is TCIOFLUSH. - //tcflush(serial_fd, TCIFLUSH); + /* Clean all read buffers to avoid errors: + * To clean OUTPUT buffer is TCOFLUSH. + * To both is TCIOFLUSH. + */ + /* //tcflush(serial_fd, TCIFLUSH); */ chr = '\0'; while (read(serial_fd, &chr,1) > 0) { - if (chr == 0xFF) { // DataPacket start + if (chr == 0xFF) { /* DataPacket start */ datapacketstart = true; - } // end for + } /* end for */ if (datapacketstart) { datapacket[datapacket_index] = chr; datapacket_index++; - if (chr == 0xFE) { // DataPacket + if (chr == 0xFE) { /* DataPacket */ time_t now = time(NULL); upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); if (lastdp != 0) { tempodecorrido = difftime(now, lastdp); } lastdp = now; - // if size is 18 or 50, maybe a answer packet. Then check if doesn't have already a packet processed. We don't need to read all times these information. Can be a corrupted packet too. + /* If size is 18 or 50, may be an answer packet. + * Then check if doesn't have already a packet processed. + * We don't need to read all times these information. + * Can be a corrupted packet too. */ if (((datapacket_index == 18) || (datapacket_index == 50)) && (!lastpkthwinfo.checksum_ok)) { lastpkthwinfo = mount_hwinfo(datapacket, datapacket_index); - } // end if + } /* end if */ else { if (datapacket_index == 21) lastpktdata = mount_datapacket(datapacket, datapacket_index, tempodecorrido,lastpkthwinfo); - } // end else - // Clean datapacket structure to avoid problems + } /* end else */ + /* Clean datapacket structure to avoid problems */ datapacket_index = 0; memset(datapacket,0,sizeof(datapacket)); datapacketstart = false; if (lastpktdata.checksum_ok) { - // checksum is OK, then use it to set values + /* checksum is OK, then use it to set values */ upsdebugx(1,"Data Packet seems be OK"); if (lastpkthwinfo.size == 0) upsdebugx(1,"Pkt HWINFO is not OK. See if will be requested next time!"); else { if (lastpkthwinfo.checksum_ok) { upsdebugx(1,"Pkt HWINFO is OK. Model is %d, hwversion is %d and swversion is %d",lastpkthwinfo.model,lastpkthwinfo.hardwareversion,lastpkthwinfo.softwareversion); - // We need to set data on NUT with data that I believe that I can calculate. Now setting data on NUT + /* We need to set data on NUT with data + * that I believe that I can calculate. + * Now setting data on NUT */ ups = getupsinfo(lastpkthwinfo.model); upsdebugx(1,"UPS Struct data: Code %d Model %s VA %d",ups.upscode,ups.upsdesc,ups.VA); dstate_setinfo("device.model", "%s",ups.upsdesc); dstate_setinfo("device.mfr","%s",MANUFACTURER); dstate_setinfo("device.serial","%s",lastpkthwinfo.serial); dstate_setinfo("device.type","%s","ups"); - /* Setting UPS Status - OL -- On line (mains is present): Code below - OB -- On battery (mains is not present) : Code below - LB -- Low battery: Code below - HB -- High battery: NHS doesn't have any variable with that information. Feel free to discover a way to set it - RB -- The battery needs to be replaced: Well, as mentioned, we can write some infos on nobreak fw, on structures like pkt_hwinfo.year, pkt_hwinfo.month, etc. I never found any equipment with these values. - CHRG -- The battery is charging: Code below - DISCHRG -- The battery is discharging (inverter is providing load power): Code Below - BYPASS -- UPS bypass circuit is active -- no battery protection is available: It's another PROBLEM, because NHS can work in bypass mode in some models, even if you have sealed batteries on it (without any external battery device). On the moment, i'll won't work with that. Feel free to discover how it work correctly. - CAL -- UPS is currently performing runtime calibration (on battery) - OFF -- UPS is offline and is not supplying power to the load - OVER -- UPS is overloaded - TRIM -- UPS is trimming incoming voltage (called "buck" in some hardware) - BOOST -- UPS is boosting incoming voltage - FSD -- Forced Shutdown (restricted use, see the note below) */ - - // Decision Chain - // First we check if system is on battery or not + + /* Setting UPS Status: + * OL -- On line (mains is present): Code below + * OB -- On battery (mains is not present) : Code below + * LB -- Low battery: Code below + * HB -- High battery: NHS doesn't have any variable with that information. Feel free to discover a way to set it + * RB -- The battery needs to be replaced: Well, as mentioned, we can write some infos on nobreak fw, on structures like pkt_hwinfo.year, pkt_hwinfo.month, etc. I never found any equipment with these values. + * CHRG -- The battery is charging: Code below + * DISCHRG -- The battery is discharging (inverter is providing load power): Code Below + * BYPASS -- UPS bypass circuit is active -- no battery protection is available: It's another PROBLEM, because NHS can work in bypass mode in some models, even if you have sealed batteries on it (without any external battery device). On the moment, i'll won't work with that. Feel free to discover how it work correctly. + * CAL -- UPS is currently performing runtime calibration (on battery) + * OFF -- UPS is offline and is not supplying power to the load + * OVER -- UPS is overloaded + * TRIM -- UPS is trimming incoming voltage (called "buck" in some hardware) + * BOOST -- UPS is boosting incoming voltage + * FSD -- Forced Shutdown (restricted use, see the note below) + */ + + /* Decision Chain commented below */ + + /* First we check if system is on battery or not */ upsdebugx(1,"Set UPS status as OFF and start checking. s_battery_mode is %d",lastpktdata.s_battery_mode); if (lastpkthwinfo.s_220V_in) { upsdebugx(1,"I'm on 220v IN!. My overvoltage is %d",lastpkthwinfo.undervoltagein220V); @@ -1796,15 +1793,15 @@ void upsdrv_updateinfo(void) { min_input_power = lastpkthwinfo.undervoltagein120V; } if (lastpktdata.s_battery_mode) { - // ON BATTERY + /* ON BATTERY */ upsdebugx(1,"UPS is on Battery Mode"); dstate_setinfo("ups.status","%s","OB"); if (lastpktdata.s_battery_low) { - // If battery is LOW, warn user! + /* If battery is LOW, warn user! */ upsdebugx(1,"UPS is on Battery Mode and in Low Battery State"); dstate_setinfo("ups.status","%s","LB"); - } // end if - } // end if + } /* end if */ + } /* end if */ else { /* Check if MAINS (power) is not preset. * Well, we can check pkt_data.s_network_failure too... */ @@ -1816,9 +1813,12 @@ void upsdrv_updateinfo(void) { min_input_power, lastpktdata.s_network_failure); dstate_setinfo("ups.status","%s","DISCHRG"); - } // end if + } /* end if */ else { - // MAINS is present. We need to check some situations. NHS only charge if have more than min_input_power. If MAINS is less or equal min_input_power then ups goes to BATTERY + /* MAINS is present. We need to check some situations. + * NHS only charge if have more than min_input_power. + * If MAINS is less than or equal to min_input_power, + * then the UPS goes to BATTERY */ if (lastpktdata.vacinrms > min_input_power) { upsdebugx(1,"UPS is on MAINS"); if (lastpktdata.s_charger_on) { @@ -1829,24 +1829,25 @@ void upsdrv_updateinfo(void) { if ((lastpktdata.s_network_failure) || (lastpktdata.s_fast_network_failure)) { upsdebugx(1,"UPS is on battery mode because network failure or fast network failure"); dstate_setinfo("ups.status","%s","OB"); - } // end if + } /* end if */ else { upsdebugx(1,"All is OK. UPS is on ONLINE!"); dstate_setinfo("ups.status","%s","OL"); - } // end else - } // end else - } // end if + } /* end else */ + } /* end else */ + } /* end if */ else { - // Energy is below limit. Nobreak problably in battery mode + /* Energy is below limit. + * Nobreak is probably in battery mode... */ if (lastpktdata.s_battery_low) dstate_setinfo("ups.status","%s","LB"); else { - // or network failure + /* ...or network failure */ dstate_setinfo("ups.status","%s","OB"); - } // end else - } // end else - } // end else - } // end else + } /* end else */ + } /* end else */ + } /* end else */ + } /* end else */ numbat = get_numbat(); if (numbat == 0) @@ -1886,16 +1887,20 @@ void upsdrv_updateinfo(void) { dstate_setinfo("ups.mfr","%s",MANUFACTURER); dstate_setinfo("ups.serial","%s",lastpkthwinfo.serial); dstate_setinfo("ups.firmware","%u",lastpkthwinfo.softwareversion); - // Setting hardware version here. Not found another place to do. Feel free to correct it + /* Setting hardware version here. + * Did not find another place to do this. + * Feel free to correct it. + * FIXME: move to upsdrv_initinfo() or so + */ dstate_setinfo("ups.firmware.aux","%u",lastpkthwinfo.hardwareversion); dstate_setinfo("ups.temperature","%0.2f",lastpktdata.tempmed_real); dstate_setinfo("ups.load","%u",lastpktdata.potrms); dstate_setinfo("ups.efficiency","%0.2f", calculate_efficiency(lastpktdata.vacoutrms, lastpktdata.vacinrms)); va = get_va(lastpkthwinfo.model); pf = get_pf(); - // vpower is the power in Watts + /* vpower is the power in Watts */ vpower = ((va * pf) * (lastpktdata.potrms / 100.0)); - // abat is the battery's consumption in Amperes + /* abat is the battery's consumption in Amperes */ abat = ((vpower / lastpktdata.vdcmed_real) / numbat); if (vpower > maxpower) maxpower = vpower; @@ -1959,17 +1964,18 @@ void upsdrv_updateinfo(void) { dstate_setinfo("battery.current.total","%0.2f",(float)abat * numbat); dstate_setinfo("battery.temperature","%ld",lrint(round(lastpktdata.tempmed_real))); dstate_setinfo("battery.packs","%u",numbat); - /* We will calculate autonomy in seconds - autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; - Maybe wrong, too. - People says that the correct calculation is - - Battery Amp-Hour / (Power in Watts / battery voltage) - - Is that correct? I don't know. I'll use it for now. - */ - // That result is IN HOURS. We need to convert it on seconds - actual_current = vpower / vbat; /* Current consumption in A*/ + /* We will calculate autonomy in seconds + * autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; + * Maybe wrong, too. + * People say that the correct calculation is + * + * Battery Amp-Hour / (Power in Watts / battery voltage) + * + * Is that correct? I don't know. I'll use it for now. + */ + + /* That result is IN HOURS. We need to convert it to seconds */ + actual_current = vpower / vbat; /* Current consumption in A*/ autonomy_secs = (ah / actual_current) * 3600; dstate_setinfo("battery.runtime","%u",autonomy_secs); @@ -1982,7 +1988,7 @@ void upsdrv_updateinfo(void) { else dstate_setinfo("battery.charger.status","%s","RESTING"); } - // Now, creating a structure called NHS, + /* Now, creating a structure called NHS, */ dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); @@ -1991,7 +1997,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); for (i = 0; i < 5; i++) { - // Reusing variable + /* Reusing variable */ sprintf(alarm,"nhs.hw.configuration_array_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); } @@ -2009,7 +2015,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); for (i = 0; i < 6; i++) { - // Reusing variable + /* Reusing variable */ sprintf(alarm,"nhs.hw.status_p%d",i); dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); } @@ -2039,7 +2045,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); - // Data packet + /* Data packet */ dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); @@ -2070,7 +2076,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); for (i = 0; i < 8; i++) { - // Reusing variable + /* Reusing variable */ sprintf(alarm,"nhs.data.status_p%d",i); dstate_setinfo(alarm, "%u", lastpktdata.status[i]); } @@ -2097,35 +2103,43 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.param.vin_high_crit_perc", "%0.2f", get_vin_perc("vin_high_crit_perc")); dstate_dataok(); - } // end if + } /* end if */ else upsdebugx(1,"Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request..."); - } // end else - } // end if - } // end if - } // end if - } // end if - // Now the nobreak read buffer is empty. We need a hw info packet to discover several variables, like number of batteries, to calculate some data + } /* end else */ + } /* end if */ + } /* end if */ + } /* end if */ + } /* end if */ + + /* Now the nobreak read buffer is empty. + * We need a hw info packet to discover several variables, + * like number of batteries, to calculate some data + * FIXME: move (semi)static info discovery to upsdrv_initinfo() or so + */ if (!lastpkthwinfo.checksum_ok) { upsdebugx(1,"pkt_hwinfo loss -- Requesting"); - // if size == 0, packet maybe not initizated, then send a initialization packet to obtain data - // Send two times the extended initialization string, but, on fail, try randomly send extended or normal + /* If size == 0, packet maybe not initizated, + * then send an initialization packet to obtain data. + * Send two times the extended initialization string, + * but, on fail, try randomly send extended or normal. + */ if (send_extended < 6) { upsdebugx(1,"Sending extended initialization packet. Try %d",send_extended+1); bwritten = write_serial_int(serial_fd,string_initialization_long,9); send_extended++; - } // end if + } /* end if */ else { - // randomly send + /* randomly send */ if (rand() % 2 == 0) { upsdebugx(1,"Sending long initialization packet"); bwritten = write_serial_int(serial_fd,string_initialization_long,9); - } // end if + } /* end if */ else { upsdebugx(1,"Sending short initialization packet"); bwritten = write_serial_int(serial_fd,string_initialization_short,9); - } // end else - } // end else + } /* end else */ + } /* end else */ if (bwritten < 0) { upsdebugx(1,"Problem to write data to %s",porta); if (bwritten == -1) { @@ -2136,7 +2150,7 @@ void upsdrv_updateinfo(void) { } close(serial_fd); serial_fd = -1; - } // end if + } /* end if */ else { if (checktime > max_checktime) checktime = max_checktime; @@ -2145,9 +2159,9 @@ void upsdrv_updateinfo(void) { checktime = checktime + 100000; } usleep(checktime); - } // end else - } // end if - } // end else + } /* end else */ + } /* end if */ + } /* end else */ upsdebugx(1,"End updateinfo()"); } @@ -2188,8 +2202,8 @@ void upsdrv_initups(void) { void upsdrv_makevartable(void) { char help[4096]; - // Standard variable in main.c - //addvar(VAR_VALUE, "port", "Port to communication"); + /* Standard variable in main.c */ + /* //addvar(VAR_VALUE, "port", "Port to communication"); */ addvar(VAR_VALUE, "baud", "Baud Rate from port"); @@ -2225,8 +2239,3 @@ void upsdrv_makevartable(void) { void upsdrv_help(void) { } - -//int main(int argc, char **argv) { -// upsdrv_info.version = "1.0"; -// upsdrv_initinfo(); -//} From 8480dca85e339add1c0cf374c3d07a0701fcb33e Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 00:50:22 +0000 Subject: [PATCH 46/60] drivers/nhs_ser.c: fix DEFAULLTPERC => DEFAULTPERC typo in the macro name [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 8a31c5ab3b..b8182a07ea 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -49,7 +49,7 @@ #define DEFAULTBAUD 2400 #define DEFAULTPORT "/dev/ttyACM0" #define DEFAULTPF 0.9 -#define DEFAULLTPERC 2.0 +#define DEFAULTPERC 2.0 #define DATAPACKETSIZE 100 #define DEFAULTBATV 12.0 @@ -1631,7 +1631,7 @@ static float get_vin_perc(char * var) { if (perc) return atof(perc); else - return DEFAULLTPERC; + return DEFAULTPERC; } void upsdrv_initinfo(void) { @@ -2214,16 +2214,16 @@ void upsdrv_makevartable(void) { snprintf(help, sizeof(help), "Power Factor to use in calculations of battery time. Default is %0.2f", DEFAULTPF); addvar(VAR_VALUE, "pf", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning low level. Default is %0.2f", DEFAULLTPERC); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning low level. Default is %0.2f", DEFAULTPERC); addvar(VAR_VALUE, "vin_low_warn_perc", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical low level. Default is %0.2f", DEFAULLTPERC); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical low level. Default is %0.2f", DEFAULTPERC); addvar(VAR_VALUE, "vin_low_crit_perc", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning high level. Default is %0.2f", DEFAULLTPERC); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning high level. Default is %0.2f", DEFAULTPERC); addvar(VAR_VALUE, "vin_high_warn_perc", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical high level. Default is %0.2f", DEFAULLTPERC); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical high level. Default is %0.2f", DEFAULTPERC); addvar(VAR_VALUE, "vin_high_crit_perc", help); snprintf(help, sizeof(help), "Num Batteries (override value from nobreak)"); From 2cde1940611da271444e087b5c914c1b0d6beadb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 00:58:59 +0000 Subject: [PATCH 47/60] drivers/nhs_ser.c: fix "for (int i...)" to use of pre-declared variables [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index b8182a07ea..493158bcab 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -376,6 +376,8 @@ static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int } static void print_pkt_hwinfo(pkt_hwinfo data) { + int i = 0; + if (!debug_pkt_hwinfo) return; @@ -389,7 +391,7 @@ static void print_pkt_hwinfo(pkt_hwinfo data) { upsdebugx(1,"Configuration Array: "); upsdebugx(1,"-----"); - for (int i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) { int retorno = get_bit_in_position(&data.configuration,sizeof(data.configuration),i,0); upsdebugx(1,"Binary value is %d",retorno); upsdebugx(1,"%u ", data.configuration_array[i]); @@ -412,7 +414,7 @@ static void print_pkt_hwinfo(pkt_hwinfo data) { upsdebugx(1,"Status: "); upsdebugx(1,"-----"); - for (int i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) { upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); upsdebugx(1,"status %d --> %u ", i, data.status[i]); } @@ -446,6 +448,8 @@ static void print_pkt_hwinfo(pkt_hwinfo data) { } static void print_pkt_data(pkt_data data) { + int i = 0; + if (!debug_pkt_data) return; @@ -481,7 +485,7 @@ static void print_pkt_data(pkt_data data) { upsdebugx(1,"Status: "); upsdebugx(1,"-----"); - for (int i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); upsdebugx(1,"status %d --> %u ", i, data.status[i]); } @@ -596,8 +600,9 @@ static int openfd(const char * portarg, int BAUDRATE) { } static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { - int soma = 0; - for (int i = inicio; i <= fim; i++) { + int soma = 0, i = 0; + + for (i = inicio; i <= fim; i++) { soma += pacote[i]; } return soma & 0xFF; From ce78ded4a812f4e3a6c752726756cc729c4831de Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:22:07 +0000 Subject: [PATCH 48/60] drivers/nhs_ser.c: fix code markup into NUT style [#2692] * indent with TAB characters, * separate declaration type and varname with TAB(s), * use space after comma Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 3677 +++++++++++++++++++++++---------------------- 1 file changed, 1843 insertions(+), 1834 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 493158bcab..a48f51769a 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -72,161 +72,161 @@ typedef struct { } baud_rate_t; static baud_rate_t baud_rates[] = { - { B50, 50, "50 bps" }, - { B75, 75, "75 bps" }, - { B110, 110, "110 bps" }, - { B134, 134, "134.5 bps" }, - { B150, 150, "150 bps" }, - { B200, 200, "200 bps" }, - { B300, 300, "300 bps" }, - { B600, 600, "600 bps" }, - { B1200, 1200, "1200 bps" }, - { B2400, 2400, "2400 bps" }, - { B4800, 4800, "4800 bps" }, - { B9600, 9600, "9600 bps" }, - { B19200, 19200, "19200 bps" }, - { B38400, 38400, "38400 bps" }, - { B57600, 57600, "57600 bps" }, - { B115200, 115200, "115200 bps" }, - { B230400, 230400, "230400 bps" }, - { B460800, 460800, "460800 bps" }, - { B921600, 921600, "921600 bps" }, - { B1500000, 1500000, "1.5 Mbps" }, - { B2000000, 2000000, "2 Mbps" }, - { B2500000, 2500000, "2.5 Mbps" }, - { B3000000, 3000000, "3 Mbps" }, - { B3500000, 3500000, "3.5 Mbps" }, - { B4000000, 4000000, "4 Mbps" }, + { B50, 50, "50 bps" }, + { B75, 75, "75 bps" }, + { B110, 110, "110 bps" }, + { B134, 134, "134.5 bps" }, + { B150, 150, "150 bps" }, + { B200, 200, "200 bps" }, + { B300, 300, "300 bps" }, + { B600, 600, "600 bps" }, + { B1200, 1200, "1200 bps" }, + { B2400, 2400, "2400 bps" }, + { B4800, 4800, "4800 bps" }, + { B9600, 9600, "9600 bps" }, + { B19200, 19200, "19200 bps" }, + { B38400, 38400, "38400 bps" }, + { B57600, 57600, "57600 bps" }, + { B115200, 115200, "115200 bps" }, + { B230400, 230400, "230400 bps" }, + { B460800, 460800, "460800 bps" }, + { B921600, 921600, "921600 bps" }, + { B1500000, 1500000, "1.5 Mbps" }, + { B2000000, 2000000, "2 Mbps" }, + { B2500000, 2500000, "2.5 Mbps" }, + { B3000000, 3000000, "3 Mbps" }, + { B3500000, 3500000, "3.5 Mbps" }, + { B4000000, 4000000, "4 Mbps" }, }; #define NUM_BAUD_RATES (sizeof(baud_rates) / sizeof(baud_rates[0])) /* Struct that contains nobreak info */ typedef struct { - unsigned int header; - unsigned int size; - char type; - unsigned int model; - unsigned int hardwareversion; - unsigned int softwareversion; - unsigned int configuration; - int configuration_array[5]; - bool c_oem_mode; - bool c_buzzer_disable; - bool c_potmin_disable; - bool c_rearm_enable; - bool c_bootloader_enable; - unsigned int numbatteries; - unsigned int undervoltagein120V; - unsigned int overvoltagein120V; - unsigned int undervoltagein220V; - unsigned int overvoltagein220V; - unsigned int tensionout120V; - unsigned int tensionout220V; - unsigned int statusval; - int status[6]; - bool s_220V_in; - bool s_220V_out; - bool s_sealed_battery; - bool s_show_out_tension; - bool s_show_temperature; - bool s_show_charger_current; - unsigned int chargercurrent; - unsigned char checksum; - unsigned char checksum_calc; - bool checksum_ok; - char serial[17]; - unsigned int year; - unsigned int month; - unsigned int wday; - unsigned int hour; - unsigned int minute; - unsigned int second; - unsigned int alarmyear; - unsigned int alarmmonth; - unsigned int alarmwday; - unsigned int alarmday; - unsigned int alarmhour; - unsigned int alarmminute; - unsigned int alarmsecond; - unsigned int end_marker; + unsigned int header; + unsigned int size; + char type; + unsigned int model; + unsigned int hardwareversion; + unsigned int softwareversion; + unsigned int configuration; + int configuration_array[5]; + bool c_oem_mode; + bool c_buzzer_disable; + bool c_potmin_disable; + bool c_rearm_enable; + bool c_bootloader_enable; + unsigned int numbatteries; + unsigned int undervoltagein120V; + unsigned int overvoltagein120V; + unsigned int undervoltagein220V; + unsigned int overvoltagein220V; + unsigned int tensionout120V; + unsigned int tensionout220V; + unsigned int statusval; + int status[6]; + bool s_220V_in; + bool s_220V_out; + bool s_sealed_battery; + bool s_show_out_tension; + bool s_show_temperature; + bool s_show_charger_current; + unsigned int chargercurrent; + unsigned char checksum; + unsigned char checksum_calc; + bool checksum_ok; + char serial[17]; + unsigned int year; + unsigned int month; + unsigned int wday; + unsigned int hour; + unsigned int minute; + unsigned int second; + unsigned int alarmyear; + unsigned int alarmmonth; + unsigned int alarmwday; + unsigned int alarmday; + unsigned int alarmhour; + unsigned int alarmminute; + unsigned int alarmsecond; + unsigned int end_marker; } pkt_hwinfo; /* Struct that contains the data packet info */ typedef struct { - unsigned int header; - unsigned int length; - char packet_type; - unsigned int vacinrms_high; - unsigned int vacinrms_low; - float vacinrms; - unsigned int vdcmed_high; - unsigned int vdcmed_low; - float vdcmed; - float vdcmed_real; - unsigned int potrms; - unsigned int vacinrmsmin_high; - unsigned int vacinrmsmin_low; - float vacinrmsmin; - unsigned int vacinrmsmax_high; - unsigned int vacinrmsmax_low; - float vacinrmsmax; - unsigned int vacoutrms_high; - unsigned int vacoutrms_low; - float vacoutrms; - unsigned int tempmed_high; - unsigned int tempmed_low; - float tempmed; - float tempmed_real; - unsigned int icarregrms; - unsigned int icarregrms_real; - float battery_tension; - unsigned int perc_output; - unsigned int statusval; - int status[8]; - unsigned int nominaltension; - float timeremain; - bool s_battery_mode; - bool s_battery_low; - bool s_network_failure; - bool s_fast_network_failure; - bool s_220_in; - bool s_220_out; - bool s_bypass_on; - bool s_charger_on; - unsigned char checksum; - unsigned char checksum_calc; - bool checksum_ok; - unsigned int end_marker; + unsigned int header; + unsigned int length; + char packet_type; + unsigned int vacinrms_high; + unsigned int vacinrms_low; + float vacinrms; + unsigned int vdcmed_high; + unsigned int vdcmed_low; + float vdcmed; + float vdcmed_real; + unsigned int potrms; + unsigned int vacinrmsmin_high; + unsigned int vacinrmsmin_low; + float vacinrmsmin; + unsigned int vacinrmsmax_high; + unsigned int vacinrmsmax_low; + float vacinrmsmax; + unsigned int vacoutrms_high; + unsigned int vacoutrms_low; + float vacoutrms; + unsigned int tempmed_high; + unsigned int tempmed_low; + float tempmed; + float tempmed_real; + unsigned int icarregrms; + unsigned int icarregrms_real; + float battery_tension; + unsigned int perc_output; + unsigned int statusval; + int status[8]; + unsigned int nominaltension; + float timeremain; + bool s_battery_mode; + bool s_battery_low; + bool s_network_failure; + bool s_fast_network_failure; + bool s_220_in; + bool s_220_out; + bool s_bypass_on; + bool s_charger_on; + unsigned char checksum; + unsigned char checksum_calc; + bool checksum_ok; + unsigned int end_marker; } pkt_data; /* struct that describes the nobreak model */ typedef struct { - unsigned int upscode; - char upsdesc[100]; - unsigned int VA; + unsigned int upscode; + char upsdesc[100]; + unsigned int VA; } upsinfo; -static const unsigned int string_initialization_long[9] = {0xFF, 0x09, 0x53, 0x83, 0x00, 0x00, 0x00, 0xDF, 0xFE}; -static const unsigned int string_initialization_short[9] = {0xFF, 0x09, 0x53, 0x03, 0x00, 0x00, 0x00, 0x5F, 0xFE}; - -static int debug_pkt_data = 0, debug_pkt_hwinfo = 0, debug_pkt_raw = 0; - -static int serial_fd = -1; -static unsigned char chr; -static int datapacket_index = 0; -static bool datapacketstart = false; -static time_t lastdp = 0; -static unsigned int checktime = 2000000; /* 2 seconds */ -static unsigned int max_checktime = 6000000; /* max wait time: 6 seconds */ -static unsigned int send_extended = 0; -static int bwritten = 0; -static unsigned char datapacket[DATAPACKETSIZE]; -static char porta[1024] = DEFAULTPORT; -static int baudrate = DEFAULTBAUD; -static float minpower = 0; -static float maxpower = 0; -static unsigned int minpowerperc = 0; -static unsigned int maxpowerperc = 0; +static const unsigned int string_initialization_long[9] = {0xFF, 0x09, 0x53, 0x83, 0x00, 0x00, 0x00, 0xDF, 0xFE}; +static const unsigned int string_initialization_short[9] = {0xFF, 0x09, 0x53, 0x03, 0x00, 0x00, 0x00, 0x5F, 0xFE}; + +static int debug_pkt_data = 0, debug_pkt_hwinfo = 0, debug_pkt_raw = 0; + +static int serial_fd = -1; +static unsigned char chr; +static int datapacket_index = 0; +static bool datapacketstart = false; +static time_t lastdp = 0; +static unsigned int checktime = 2000000; /* 2 seconds */ +static unsigned int max_checktime = 6000000; /* max wait time: 6 seconds */ +static unsigned int send_extended = 0; +static int bwritten = 0; +static unsigned char datapacket[DATAPACKETSIZE]; +static char porta[1024] = DEFAULTPORT; +static int baudrate = DEFAULTBAUD; +static float minpower = 0; +static float maxpower = 0; +static unsigned int minpowerperc = 0; +static unsigned int maxpowerperc = 0; static pkt_hwinfo lastpkthwinfo = { 0xFF, /* header */ @@ -359,290 +359,292 @@ static unsigned int get_numbat(void); /* method implementations */ static int get_bit_in_position(void *ptr, size_t size, size_t bit_position, int invertorder) { - unsigned char *byte_ptr = (unsigned char *)ptr; - int retval = -2; - size_t byte_index = bit_position / 8; - size_t bit_index = bit_position % 8; - - if (bit_position >= size * 8) { - return -3; /* Invalid Position */ - } - - if (invertorder == 0) - retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 1 : 0; - else - retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 0 : 1; - return retval; + unsigned char *byte_ptr = (unsigned char *)ptr; + int retval = -2; + size_t byte_index = bit_position / 8; + size_t bit_index = bit_position % 8; + + if (bit_position >= size * 8) { + return -3; /* Invalid Position */ + } + + if (invertorder == 0) + retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 1 : 0; + else + retval = (byte_ptr[byte_index] >> (7 - bit_index)) & 1 ? 0 : 1; + return retval; } static void print_pkt_hwinfo(pkt_hwinfo data) { - int i = 0; - - if (!debug_pkt_hwinfo) - return; - - upsdebugx(1,"Header: %u", data.header); - upsdebugx(1,"Size: %u", data.size); - upsdebugx(1,"Type: %c", data.type); - upsdebugx(1,"Model: %u", data.model); - upsdebugx(1,"Hardware Version: %u", data.hardwareversion); - upsdebugx(1,"Software Version: %u", data.softwareversion); - upsdebugx(1,"Configuration: %u", data.configuration); - - upsdebugx(1,"Configuration Array: "); - upsdebugx(1,"-----"); - for (i = 0; i < 5; i++) { - int retorno = get_bit_in_position(&data.configuration,sizeof(data.configuration),i,0); - upsdebugx(1,"Binary value is %d",retorno); - upsdebugx(1,"%u ", data.configuration_array[i]); - } - upsdebugx(1,"-----"); - - upsdebugx(1,"OEM Mode: %s", data.c_oem_mode ? "true" : "false"); - upsdebugx(1,"Buzzer Disable: %s", data.c_buzzer_disable ? "true" : "false"); - upsdebugx(1,"Potmin Disable: %s", data.c_potmin_disable ? "true" : "false"); - upsdebugx(1,"Rearm Enable: %s", data.c_rearm_enable ? "true" : "false"); - upsdebugx(1,"Bootloader Enable: %s", data.c_bootloader_enable ? "true" : "false"); - upsdebugx(1,"Number of Batteries: %u", data.numbatteries); - upsdebugx(1,"Undervoltage In 120V: %u", data.undervoltagein120V); - upsdebugx(1,"Overvoltage In 120V: %u", data.overvoltagein120V); - upsdebugx(1,"Undervoltage In 220V: %u", data.undervoltagein220V); - upsdebugx(1,"Overvoltage In 220V: %u", data.overvoltagein220V); - upsdebugx(1,"Tension Out 120V: %u", data.tensionout120V); - upsdebugx(1,"Tension Out 220V: %u", data.tensionout220V); - upsdebugx(1,"Status Value: %u", data.statusval); - - upsdebugx(1,"Status: "); - upsdebugx(1,"-----"); - for (i = 0; i < 6; i++) { - upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); - upsdebugx(1,"status %d --> %u ", i, data.status[i]); - } - upsdebugx(1,"-----"); - - upsdebugx(1,"220V In: %s", data.s_220V_in ? "true" : "false"); - upsdebugx(1,"220V Out: %s", data.s_220V_out ? "true" : "false"); - upsdebugx(1,"Sealed Battery: %s", data.s_sealed_battery ? "true" : "false"); - upsdebugx(1,"Show Out Tension: %s", data.s_show_out_tension ? "true" : "false"); - upsdebugx(1,"Show Temperature: %s", data.s_show_temperature ? "true" : "false"); - upsdebugx(1,"Show Charger Current: %s", data.s_show_charger_current ? "true" : "false"); - upsdebugx(1,"Charger Current: %u", data.chargercurrent); - upsdebugx(1,"Checksum: %u", data.checksum); - upsdebugx(1,"Checksum Calc: %u", data.checksum_calc); - upsdebugx(1,"Checksum OK: %s", data.checksum_ok ? "true" : "false"); - upsdebugx(1,"Serial: %s", data.serial); - upsdebugx(1,"Year: %u", data.year); - upsdebugx(1,"Month: %u", data.month); - upsdebugx(1,"Weekday: %u", data.wday); - upsdebugx(1,"Hour: %u", data.hour); - upsdebugx(1,"Minute: %u", data.minute); - upsdebugx(1,"Second: %u", data.second); - upsdebugx(1,"Alarm Year: %u", data.alarmyear); - upsdebugx(1,"Alarm Month: %u", data.alarmmonth); - upsdebugx(1,"Alarm Weekday: %u", data.alarmwday); - upsdebugx(1,"Alarm Day: %u", data.alarmday); - upsdebugx(1,"Alarm Hour: %u", data.alarmhour); - upsdebugx(1,"Alarm Minute: %u", data.alarmminute); - upsdebugx(1,"Alarm Second: %u", data.alarmsecond); - upsdebugx(1,"End Marker: %u", data.end_marker); + int i = 0; + + if (!debug_pkt_hwinfo) + return; + + upsdebugx(1, "Header: %u", data.header); + upsdebugx(1, "Size: %u", data.size); + upsdebugx(1, "Type: %c", data.type); + upsdebugx(1, "Model: %u", data.model); + upsdebugx(1, "Hardware Version: %u", data.hardwareversion); + upsdebugx(1, "Software Version: %u", data.softwareversion); + upsdebugx(1, "Configuration: %u", data.configuration); + + upsdebugx(1, "Configuration Array: "); + upsdebugx(1, "-----"); + for (i = 0; i < 5; i++) { + int retorno = get_bit_in_position(&data.configuration, sizeof(data.configuration), i, 0); + upsdebugx(1, "Binary value is %d", retorno); + upsdebugx(1, "%u ", data.configuration_array[i]); + } + upsdebugx(1, "-----"); + + upsdebugx(1, "OEM Mode: %s", data.c_oem_mode ? "true" : "false"); + upsdebugx(1, "Buzzer Disable: %s", data.c_buzzer_disable ? "true" : "false"); + upsdebugx(1, "Potmin Disable: %s", data.c_potmin_disable ? "true" : "false"); + upsdebugx(1, "Rearm Enable: %s", data.c_rearm_enable ? "true" : "false"); + upsdebugx(1, "Bootloader Enable: %s", data.c_bootloader_enable ? "true" : "false"); + upsdebugx(1, "Number of Batteries: %u", data.numbatteries); + upsdebugx(1, "Undervoltage In 120V: %u", data.undervoltagein120V); + upsdebugx(1, "Overvoltage In 120V: %u", data.overvoltagein120V); + upsdebugx(1, "Undervoltage In 220V: %u", data.undervoltagein220V); + upsdebugx(1, "Overvoltage In 220V: %u", data.overvoltagein220V); + upsdebugx(1, "Tension Out 120V: %u", data.tensionout120V); + upsdebugx(1, "Tension Out 220V: %u", data.tensionout220V); + upsdebugx(1, "Status Value: %u", data.statusval); + + upsdebugx(1, "Status: "); + upsdebugx(1, "-----"); + for (i = 0; i < 6; i++) { + upsdebugx(1, "Binary value is %d", get_bit_in_position(&data.statusval, sizeof(data.statusval), i, 0)); + upsdebugx(1, "status %d --> %u ", i, data.status[i]); + } + upsdebugx(1, "-----"); + + upsdebugx(1, "220V In: %s", data.s_220V_in ? "true" : "false"); + upsdebugx(1, "220V Out: %s", data.s_220V_out ? "true" : "false"); + upsdebugx(1, "Sealed Battery: %s", data.s_sealed_battery ? "true" : "false"); + upsdebugx(1, "Show Out Tension: %s", data.s_show_out_tension ? "true" : "false"); + upsdebugx(1, "Show Temperature: %s", data.s_show_temperature ? "true" : "false"); + upsdebugx(1, "Show Charger Current: %s", data.s_show_charger_current ? "true" : "false"); + upsdebugx(1, "Charger Current: %u", data.chargercurrent); + upsdebugx(1, "Checksum: %u", data.checksum); + upsdebugx(1, "Checksum Calc: %u", data.checksum_calc); + upsdebugx(1, "Checksum OK: %s", data.checksum_ok ? "true" : "false"); + upsdebugx(1, "Serial: %s", data.serial); + upsdebugx(1, "Year: %u", data.year); + upsdebugx(1, "Month: %u", data.month); + upsdebugx(1, "Weekday: %u", data.wday); + upsdebugx(1, "Hour: %u", data.hour); + upsdebugx(1, "Minute: %u", data.minute); + upsdebugx(1, "Second: %u", data.second); + upsdebugx(1, "Alarm Year: %u", data.alarmyear); + upsdebugx(1, "Alarm Month: %u", data.alarmmonth); + upsdebugx(1, "Alarm Weekday: %u", data.alarmwday); + upsdebugx(1, "Alarm Day: %u", data.alarmday); + upsdebugx(1, "Alarm Hour: %u", data.alarmhour); + upsdebugx(1, "Alarm Minute: %u", data.alarmminute); + upsdebugx(1, "Alarm Second: %u", data.alarmsecond); + upsdebugx(1, "End Marker: %u", data.end_marker); } static void print_pkt_data(pkt_data data) { - int i = 0; - - if (!debug_pkt_data) - return; - - upsdebugx(1,"Header: %u", data.header); - upsdebugx(1,"Length: %u", data.length); - upsdebugx(1,"Packet Type: %c", data.packet_type); - upsdebugx(1,"Vacin RMS High: %u", data.vacinrms_high); - upsdebugx(1,"Vacin RMS Low: %u", data.vacinrms_low); - upsdebugx(1,"Vacin RMS: %0.2f", data.vacinrms); - upsdebugx(1,"VDC Med High: %u", data.vdcmed_high); - upsdebugx(1,"VDC Med Low: %u", data.vdcmed_low); - upsdebugx(1,"VDC Med: %0.2f", data.vdcmed); - upsdebugx(1,"VDC Med Real: %0.2f", data.vdcmed_real); - upsdebugx(1,"Pot RMS: %u", data.potrms); - upsdebugx(1,"Vacin RMS Min High: %u", data.vacinrmsmin_high); - upsdebugx(1,"Vacin RMS Min Low: %u", data.vacinrmsmin_low); - upsdebugx(1,"Vacin RMS Min: %0.2f", data.vacinrmsmin); - upsdebugx(1,"Vacin RMS Max High: %u", data.vacinrmsmax_high); - upsdebugx(1,"Vacin RMS Max Low: %u", data.vacinrmsmax_low); - upsdebugx(1,"Vacin RMS Max: %0.2f", data.vacinrmsmax); - upsdebugx(1,"Vac Out RMS High: %u", data.vacoutrms_high); - upsdebugx(1,"Vac Out RMS Low: %u", data.vacoutrms_low); - upsdebugx(1,"Vac Out RMS: %0.2f", data.vacoutrms); - upsdebugx(1,"Temp Med High: %u", data.tempmed_high); - upsdebugx(1,"Temp Med Low: %u", data.tempmed_low); - upsdebugx(1,"Temp Med: %0.2f", data.tempmed); - upsdebugx(1,"Temp Med Real: %0.2f", data.tempmed_real); - upsdebugx(1,"Icar Reg RMS: %u", data.icarregrms); - upsdebugx(1,"Icar Reg RMS Real: %u", data.icarregrms_real); - upsdebugx(1,"Battery Tension: %0.2f", data.battery_tension); - upsdebugx(1,"Perc Output: %u", data.perc_output); - upsdebugx(1,"Status Value: %u", data.statusval); - - upsdebugx(1,"Status: "); - upsdebugx(1,"-----"); - for (i = 0; i < 8; i++) { - upsdebugx(1,"Binary value is %d",get_bit_in_position(&data.statusval,sizeof(data.statusval),i,0)); - upsdebugx(1,"status %d --> %u ", i, data.status[i]); - } - upsdebugx(1,"-----"); - - upsdebugx(1,"Nominal Tension: %u", data.nominaltension); - upsdebugx(1,"Time Remain: %0.2f", data.timeremain); - upsdebugx(1,"Battery Mode: %s", data.s_battery_mode ? "true" : "false"); - upsdebugx(1,"Battery Low: %s", data.s_battery_low ? "true" : "false"); - upsdebugx(1,"Network Failure: %s", data.s_network_failure ? "true" : "false"); - upsdebugx(1,"Fast Network Failure: %s", data.s_fast_network_failure ? "true" : "false"); - upsdebugx(1,"220 In: %s", data.s_220_in ? "true" : "false"); - upsdebugx(1,"220 Out: %s", data.s_220_out ? "true" : "false"); - upsdebugx(1,"Bypass On: %s", data.s_bypass_on ? "true" : "false"); - upsdebugx(1,"Charger On: %s", data.s_charger_on ? "true" : "false"); - upsdebugx(1,"Checksum: %u", data.checksum); - upsdebugx(1,"Checksum Calc: %u", data.checksum_calc); - upsdebugx(1,"Checksum OK: %s", data.checksum_ok ? "true" : "false"); - upsdebugx(1,"End Marker: %u", data.end_marker); + int i = 0; + + if (!debug_pkt_data) + return; + + upsdebugx(1, "Header: %u", data.header); + upsdebugx(1, "Length: %u", data.length); + upsdebugx(1, "Packet Type: %c", data.packet_type); + upsdebugx(1, "Vacin RMS High: %u", data.vacinrms_high); + upsdebugx(1, "Vacin RMS Low: %u", data.vacinrms_low); + upsdebugx(1, "Vacin RMS: %0.2f", data.vacinrms); + upsdebugx(1, "VDC Med High: %u", data.vdcmed_high); + upsdebugx(1, "VDC Med Low: %u", data.vdcmed_low); + upsdebugx(1, "VDC Med: %0.2f", data.vdcmed); + upsdebugx(1, "VDC Med Real: %0.2f", data.vdcmed_real); + upsdebugx(1, "Pot RMS: %u", data.potrms); + upsdebugx(1, "Vacin RMS Min High: %u", data.vacinrmsmin_high); + upsdebugx(1, "Vacin RMS Min Low: %u", data.vacinrmsmin_low); + upsdebugx(1, "Vacin RMS Min: %0.2f", data.vacinrmsmin); + upsdebugx(1, "Vacin RMS Max High: %u", data.vacinrmsmax_high); + upsdebugx(1, "Vacin RMS Max Low: %u", data.vacinrmsmax_low); + upsdebugx(1, "Vacin RMS Max: %0.2f", data.vacinrmsmax); + upsdebugx(1, "Vac Out RMS High: %u", data.vacoutrms_high); + upsdebugx(1, "Vac Out RMS Low: %u", data.vacoutrms_low); + upsdebugx(1, "Vac Out RMS: %0.2f", data.vacoutrms); + upsdebugx(1, "Temp Med High: %u", data.tempmed_high); + upsdebugx(1, "Temp Med Low: %u", data.tempmed_low); + upsdebugx(1, "Temp Med: %0.2f", data.tempmed); + upsdebugx(1, "Temp Med Real: %0.2f", data.tempmed_real); + upsdebugx(1, "Icar Reg RMS: %u", data.icarregrms); + upsdebugx(1, "Icar Reg RMS Real: %u", data.icarregrms_real); + upsdebugx(1, "Battery Tension: %0.2f", data.battery_tension); + upsdebugx(1, "Perc Output: %u", data.perc_output); + upsdebugx(1, "Status Value: %u", data.statusval); + + upsdebugx(1, "Status: "); + upsdebugx(1, "-----"); + for (i = 0; i < 8; i++) { + upsdebugx(1, "Binary value is %d", get_bit_in_position(&data.statusval, sizeof(data.statusval), i, 0)); + upsdebugx(1, "status %d --> %u ", i, data.status[i]); + } + upsdebugx(1, "-----"); + + upsdebugx(1, "Nominal Tension: %u", data.nominaltension); + upsdebugx(1, "Time Remain: %0.2f", data.timeremain); + upsdebugx(1, "Battery Mode: %s", data.s_battery_mode ? "true" : "false"); + upsdebugx(1, "Battery Low: %s", data.s_battery_low ? "true" : "false"); + upsdebugx(1, "Network Failure: %s", data.s_network_failure ? "true" : "false"); + upsdebugx(1, "Fast Network Failure: %s", data.s_fast_network_failure ? "true" : "false"); + upsdebugx(1, "220 In: %s", data.s_220_in ? "true" : "false"); + upsdebugx(1, "220 Out: %s", data.s_220_out ? "true" : "false"); + upsdebugx(1, "Bypass On: %s", data.s_bypass_on ? "true" : "false"); + upsdebugx(1, "Charger On: %s", data.s_charger_on ? "true" : "false"); + upsdebugx(1, "Checksum: %u", data.checksum); + upsdebugx(1, "Checksum Calc: %u", data.checksum_calc); + upsdebugx(1, "Checksum OK: %s", data.checksum_ok ? "true" : "false"); + upsdebugx(1, "End Marker: %u", data.end_marker); } /* FIXME: Replace with NUT ser_open() and ser_set_speed() */ static int openfd(const char * portarg, int BAUDRATE) { - long unsigned int i = 0; - int done = 0; - struct termios tty; - struct serial_struct serial; - - /* //int fd = ser_open(portarg); */ - int fd = open(portarg, O_RDWR | O_NOCTTY | O_SYNC); - if (fd < 0) { - upsdebugx(1, "Error on open %s", portarg); - return -1; - } - if (tcflush(fd, TCIOFLUSH) != 0) { - upsdebugx(1, "Error on flush data on %s", portarg); - return -1; - } - - - if (tcgetattr(fd, &tty) != 0) { - upsdebugx(1, "Error on set termios values to %s", portarg); - close(fd); - return -1; - } - - serial.xmit_fifo_size = 1; - ioctl(fd, TIOCSSERIAL, &serial); - - - /* select speed based on baud */ - while ((i < NUM_BAUD_RATES) && (done == 0)) { - if (baud_rates[i].speed == BAUDRATE) { - done = baud_rates[i].rate; - upsdebugx(1,"Baud selecionado: %d -- %s",baud_rates[i].speed,baud_rates[i].description); - } - i++; - } - - /* if done is 0, no one speed has selected, then use default */ - if (done == 0) { - while ((i < NUM_BAUD_RATES) && (done == 0)) { - if (baud_rates[i].speed == DEFAULTBAUD) { - done = baud_rates[i].rate; - upsdebugx(1,"Baud selecionado: %d -- %s",baud_rates[i].speed,baud_rates[i].description); - } - i++; - } - } - - if (done == 0) { - upsdebugx(1,"Baud rate not found, using default %d",DEFAULTBAUD); - done = B2400; - } - - - tty.c_cflag &= ~PARENB; /* Disable Parity */ - tty.c_cflag &= ~CSTOPB; /* 1 stop bit */ - tty.c_cflag &= ~CSIZE; /* Clear Bit Set */ - tty.c_cflag |= CS8; /* 8 bits per byte */ - - /* CTS / RTS */ - tty.c_cflag |= CRTSCTS; /* Enable hardware flow control */ - - /* Enable Read and disable modem control */ - /* // tty.c_cflag |= (CLOCAL | CREAD); */ - tty.c_cflag |= CREAD; - - - tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable Software Control */ - tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); - - tty.c_oflag &= ~OPOST; /* Disable output post-processing */ - tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); /* Modo raw */ - - /* To enable block read: VTIME = 1 and VMIN = 0 - * To disable block read: VTIME = 0 and VMIN = 1 - */ - tty.c_cc[VTIME] = 1; - tty.c_cc[VMIN] = 0; - - - cfsetispeed(&tty, done); - cfsetospeed(&tty, done); - - if (tcsetattr(fd, TCSANOW, &tty) != 0) { - upsdebugx(1, "Error on tcsetattr on port %s", portarg); - close(fd); - return -1; - } - return fd; + long unsigned int i = 0; + int done = 0; + struct termios tty; + struct serial_struct serial; + + /* //int fd = ser_open(portarg); */ + int fd = open(portarg, O_RDWR | O_NOCTTY | O_SYNC); + + if (fd < 0) { + upsdebugx(1, "Error on open %s", portarg); + return -1; + } + + if (tcflush(fd, TCIOFLUSH) != 0) { + upsdebugx(1, "Error on flush data on %s", portarg); + return -1; + } + + if (tcgetattr(fd, &tty) != 0) { + upsdebugx(1, "Error on set termios values to %s", portarg); + close(fd); + return -1; + } + + serial.xmit_fifo_size = 1; + ioctl(fd, TIOCSSERIAL, &serial); + + + /* select speed based on baud */ + while ((i < NUM_BAUD_RATES) && (done == 0)) { + if (baud_rates[i].speed == BAUDRATE) { + done = baud_rates[i].rate; + upsdebugx(1, "Baud selecionado: %d -- %s", baud_rates[i].speed, baud_rates[i].description); + } + i++; + } + + /* if done is 0, no one speed has selected, then use default */ + if (done == 0) { + while ((i < NUM_BAUD_RATES) && (done == 0)) { + if (baud_rates[i].speed == DEFAULTBAUD) { + done = baud_rates[i].rate; + upsdebugx(1, "Baud selecionado: %d -- %s", baud_rates[i].speed, baud_rates[i].description); + } + i++; + } + } + + /* Wrong macro? */ + if (done == 0) { + upsdebugx(1, "Baud rate not found, using default %d", DEFAULTBAUD); + done = B2400; + } + + + tty.c_cflag &= ~PARENB; /* Disable Parity */ + tty.c_cflag &= ~CSTOPB; /* 1 stop bit */ + tty.c_cflag &= ~CSIZE; /* Clear Bit Set */ + tty.c_cflag |= CS8; /* 8 bits per byte */ + + /* CTS / RTS */ + tty.c_cflag |= CRTSCTS; /* Enable hardware flow control */ + + /* Enable Read and disable modem control */ + /* // tty.c_cflag |= (CLOCAL | CREAD); */ + tty.c_cflag |= CREAD; + + + tty.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable Software Control */ + tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); + + tty.c_oflag &= ~OPOST; /* Disable output post-processing */ + tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); /* Modo raw */ + + /* To enable block read: VTIME = 1 and VMIN = 0 + * To disable block read: VTIME = 0 and VMIN = 1 + */ + tty.c_cc[VTIME] = 1; + tty.c_cc[VMIN] = 0; + + + cfsetispeed(&tty, done); + cfsetospeed(&tty, done); + + if (tcsetattr(fd, TCSANOW, &tty) != 0) { + upsdebugx(1, "Error on tcsetattr on port %s", portarg); + close(fd); + return -1; + } + return fd; } static unsigned char calculate_checksum(unsigned char *pacote, int inicio, int fim) { - int soma = 0, i = 0; + int soma = 0, i = 0; - for (i = inicio; i <= fim; i++) { - soma += pacote[i]; - } - return soma & 0xFF; + for (i = inicio; i <= fim; i++) { + soma += pacote[i]; + } + return (soma & 0xFF); } static void pdatapacket(unsigned char * datapkt, int size) { - int i = 0; + int i = 0; - if (!debug_pkt_raw) - return; + if (!debug_pkt_raw) + return; - if (datapkt != NULL) { - upsdebugx(1,"Received Datapacket: "); - for (i = 0; i < size; i++) { - upsdebugx(1,"\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapkt[i], datapkt[i], datapkt[i]); - } - } + if (datapkt != NULL) { + upsdebugx(1, "Received Datapacket: "); + for (i = 0; i < size; i++) { + upsdebugx(1, "\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapkt[i], datapkt[i], datapkt[i]); + } + } } static float createfloat(int integer, int decimal) { - char flt[1024]; - sprintf(flt,"%d.%d",integer,decimal); - return atof(flt); + char flt[1024]; + sprintf(flt, "%d.%d", integer, decimal); + return atof(flt); } static unsigned int get_vbat() { - char * v = getval("vbat"); - if (v) { - return atoi(v); - } - else { - return DEFAULTBATV; - } + char *v = getval("vbat"); + if (v) { + return atoi(v); + } + else { + return DEFAULTBATV; + } } -static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempodecorrido,pkt_hwinfo pkt_upsinfo) { - int i = 0; - unsigned int vbat = 0; - unsigned char checksum = 0x00; - pkt_data pktdata = { +static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempodecorrido, pkt_hwinfo pkt_upsinfo) { + int i = 0; + unsigned int vbat = 0; + unsigned char checksum = 0x00; + pkt_data pktdata = { 0xFF, /* header */ 0x21, /* length */ 'D', /* packet_type */ @@ -687,95 +689,95 @@ static pkt_data mount_datapacket(unsigned char * datapkt, int size, double tempo 0, /* checksum_calc */ false, /* checksum_ok */ 0xFE /* end_marker */ - }; - - NUT_UNUSED_VARIABLE(tempodecorrido); - - pktdata.length = (int)datapkt[1]; - pktdata.packet_type = datapkt[2]; - pktdata.vacinrms_high = (int)datapkt[3]; - pktdata.vacinrms_low = (int)datapkt[4]; - pktdata.vacinrms = createfloat(pktdata.vacinrms_high,pktdata.vacinrms_low); - pktdata.vdcmed_high = (int)datapkt[5]; - pktdata.vdcmed_low = (int)datapkt[6]; - pktdata.vdcmed = createfloat(pktdata.vdcmed_high,pktdata.vdcmed_low); - pktdata.vdcmed_real = pktdata.vdcmed; - if (pktdata.vdcmed_low == 0) - pktdata.vdcmed_real = pktdata.vdcmed / 10; - pktdata.potrms = (int)datapkt[7]; - pktdata.vacinrmsmin_high = (int)datapkt[8]; - pktdata.vacinrmsmin_low = (int)datapkt[9]; - pktdata.vacinrmsmin = createfloat(pktdata.vacinrmsmin_high,pktdata.vacinrmsmin_low); - pktdata.vacinrmsmax_high = (int)datapkt[10]; - pktdata.vacinrmsmax_low = (int)datapkt[11]; - pktdata.vacinrmsmax = createfloat(pktdata.vacinrmsmax_high,pktdata.vacinrmsmax_low); - pktdata.vacoutrms_high = (int)datapkt[12]; - pktdata.vacoutrms_low = (int)datapkt[13]; - pktdata.vacoutrms = createfloat(pktdata.vacoutrms_high,pktdata.vacoutrms_low); - pktdata.tempmed_high = (int)datapkt[14]; - pktdata.tempmed_low = (int)datapkt[15]; - pktdata.tempmed = createfloat(pktdata.tempmed_high,pktdata.tempmed_low); - pktdata.tempmed_real = pktdata.tempmed; - pktdata.icarregrms = (int)datapkt[16]; - /* 25 units = 750mA, then 1 unit = 30mA */ - pktdata.icarregrms_real = pktdata.icarregrms * 30; - pktdata.statusval = datapkt[17]; - for (i = 0; i < 8; i++) - pktdata.status[i] = get_bit_in_position(&datapkt[17],sizeof(datapkt[17]),i,0); - - /* I don't know WHY, but bit order is INVERTED here. - * Discovered on clyra's github python implementation - */ - /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) - * have same problem. I won't have so much equipment to test - * these, then we need help to test more - */ - pktdata.s_battery_mode = (bool)pktdata.status[7]; - pktdata.s_battery_low = (bool)pktdata.status[6]; - pktdata.s_network_failure = (bool)pktdata.status[5]; - pktdata.s_fast_network_failure = (bool)pktdata.status[4]; - pktdata.s_220_in = (bool)pktdata.status[3]; - pktdata.s_220_out = (bool)pktdata.status[2]; - pktdata.s_bypass_on = (bool)pktdata.status[1]; - pktdata.s_charger_on = (bool)pktdata.status[0]; - /* Position 18 means status, but I won't discover what's it */ - pktdata.checksum = datapkt[19]; - checksum = calculate_checksum(datapkt,1,18); - pktdata.checksum_calc = checksum; - if (pktdata.checksum == checksum) - pktdata.checksum_ok = true; - /* Then, the calculations to obtain some useful information */ - if (pkt_upsinfo.size > 0) { - pktdata.battery_tension = pkt_upsinfo.numbatteries * pktdata.vdcmed_real; - /* Calculate battery percent utilization: - * if one battery cell has 12V, then the - * maximum out voltage is `numbatteries * 12V` - * This is the watermark to low battery - */ - /* TODO: test with external battery bank to see if - * calculation is valid. Can generate false positive - */ - vbat = get_vbat(); - pktdata.nominaltension = vbat * pkt_upsinfo.numbatteries; - if (pktdata.nominaltension > 0) { - pktdata.perc_output = (pktdata.battery_tension * 100) / pktdata.nominaltension; - if (pktdata.perc_output > 100) - pktdata.perc_output = 100; - } /* end if */ - } /* end if */ - - if (debug_pkt_data) { - pdatapacket(datapkt, size); - print_pkt_data(pktdata); - } - - return pktdata; + }; + + NUT_UNUSED_VARIABLE(tempodecorrido); + + pktdata.length = (int)datapkt[1]; + pktdata.packet_type = datapkt[2]; + pktdata.vacinrms_high = (int)datapkt[3]; + pktdata.vacinrms_low = (int)datapkt[4]; + pktdata.vacinrms = createfloat(pktdata.vacinrms_high, pktdata.vacinrms_low); + pktdata.vdcmed_high = (int)datapkt[5]; + pktdata.vdcmed_low = (int)datapkt[6]; + pktdata.vdcmed = createfloat(pktdata.vdcmed_high, pktdata.vdcmed_low); + pktdata.vdcmed_real = pktdata.vdcmed; + if (pktdata.vdcmed_low == 0) + pktdata.vdcmed_real = pktdata.vdcmed / 10; + pktdata.potrms = (int)datapkt[7]; + pktdata.vacinrmsmin_high = (int)datapkt[8]; + pktdata.vacinrmsmin_low = (int)datapkt[9]; + pktdata.vacinrmsmin = createfloat(pktdata.vacinrmsmin_high, pktdata.vacinrmsmin_low); + pktdata.vacinrmsmax_high = (int)datapkt[10]; + pktdata.vacinrmsmax_low = (int)datapkt[11]; + pktdata.vacinrmsmax = createfloat(pktdata.vacinrmsmax_high, pktdata.vacinrmsmax_low); + pktdata.vacoutrms_high = (int)datapkt[12]; + pktdata.vacoutrms_low = (int)datapkt[13]; + pktdata.vacoutrms = createfloat(pktdata.vacoutrms_high, pktdata.vacoutrms_low); + pktdata.tempmed_high = (int)datapkt[14]; + pktdata.tempmed_low = (int)datapkt[15]; + pktdata.tempmed = createfloat(pktdata.tempmed_high, pktdata.tempmed_low); + pktdata.tempmed_real = pktdata.tempmed; + pktdata.icarregrms = (int)datapkt[16]; + /* 25 units = 750mA, then 1 unit = 30mA */ + pktdata.icarregrms_real = pktdata.icarregrms * 30; + pktdata.statusval = datapkt[17]; + for (i = 0; i < 8; i++) + pktdata.status[i] = get_bit_in_position(&datapkt[17], sizeof(datapkt[17]), i, 0); + + /* I don't know WHY, but bit order is INVERTED here. + * Discovered on clyra's github python implementation + */ + /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) + * have same problem. I won't have so much equipment to test + * these, then we need help to test more + */ + pktdata.s_battery_mode = (bool)pktdata.status[7]; + pktdata.s_battery_low = (bool)pktdata.status[6]; + pktdata.s_network_failure = (bool)pktdata.status[5]; + pktdata.s_fast_network_failure = (bool)pktdata.status[4]; + pktdata.s_220_in = (bool)pktdata.status[3]; + pktdata.s_220_out = (bool)pktdata.status[2]; + pktdata.s_bypass_on = (bool)pktdata.status[1]; + pktdata.s_charger_on = (bool)pktdata.status[0]; + /* Position 18 means status, but I won't discover what's it */ + pktdata.checksum = datapkt[19]; + checksum = calculate_checksum(datapkt, 1, 18); + pktdata.checksum_calc = checksum; + if (pktdata.checksum == checksum) + pktdata.checksum_ok = true; + /* Then, the calculations to obtain some useful information */ + if (pkt_upsinfo.size > 0) { + pktdata.battery_tension = pkt_upsinfo.numbatteries * pktdata.vdcmed_real; + /* Calculate battery percent utilization: + * if one battery cell has 12V, then the + * maximum out voltage is `numbatteries * 12V` + * This is the watermark to low battery + */ + /* TODO: test with external battery bank to see if + * calculation is valid. Can generate false positive + */ + vbat = get_vbat(); + pktdata.nominaltension = vbat * pkt_upsinfo.numbatteries; + if (pktdata.nominaltension > 0) { + pktdata.perc_output = (pktdata.battery_tension * 100) / pktdata.nominaltension; + if (pktdata.perc_output > 100) + pktdata.perc_output = 100; + } /* end if */ + } /* end if */ + + if (debug_pkt_data) { + pdatapacket(datapkt, size); + print_pkt_data(pktdata); + } + + return pktdata; } static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { - int i = 0; - unsigned char checksum = 0x00; - pkt_hwinfo pkthwinfo = { + int i = 0; + unsigned char checksum = 0x00; + pkt_hwinfo pkthwinfo = { 0xFF, /* header */ 0, /* size */ 'S', /* type */ @@ -823,1423 +825,1430 @@ static pkt_hwinfo mount_hwinfo(unsigned char *datapkt, int size) { 0, /* alarmminute */ 0, /* alarmsecond */ 0xFE /* end_marker */ - }; - - pkthwinfo.size = (int)datapkt[1]; - pkthwinfo.type = datapkt[2]; - pkthwinfo.model = (int)datapkt[3]; - pkthwinfo.hardwareversion = (int)datapkt[4]; - pkthwinfo.softwareversion = (int)datapkt[5]; - pkthwinfo.configuration = datapkt[6]; - for (i = 0; i < 5; i++) - pkthwinfo.configuration_array[i] = get_bit_in_position(&datapkt[6],sizeof(datapkt[6]),i,0); - /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) - * have same problem. I won't have so much equipment to test - * these, then we need help to test more */ - pkthwinfo.c_oem_mode = (bool)pkthwinfo.configuration_array[0]; - pkthwinfo.c_buzzer_disable = (bool)pkthwinfo.configuration_array[1]; - pkthwinfo.c_potmin_disable = (bool)pkthwinfo.configuration_array[2]; - pkthwinfo.c_rearm_enable = (bool)pkthwinfo.configuration_array[3]; - pkthwinfo.c_bootloader_enable = (bool)pkthwinfo.configuration_array[4]; - pkthwinfo.numbatteries = (int)datapkt[7]; - pkthwinfo.undervoltagein120V = (int)datapkt[8]; - pkthwinfo.overvoltagein120V = (int)datapkt[9]; - pkthwinfo.undervoltagein220V = (int)datapkt[10]; - pkthwinfo.overvoltagein220V = (int)datapkt[11]; - pkthwinfo.tensionout120V = (int)datapkt[12]; - pkthwinfo.tensionout220V = (int)datapkt[13]; - pkthwinfo.statusval = datapkt[14]; - for (i = 0; i < 6; i++) - pkthwinfo.status[i] = get_bit_in_position(&datapkt[14],sizeof(datapkt[14]),i,0); - /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) - * have same problem. I won't have so much equipment to test - * these, then we need help to test more */ - pkthwinfo.s_220V_in = (bool)pkthwinfo.status[0]; - pkthwinfo.s_220V_out = (bool)pkthwinfo.status[1]; - pkthwinfo.s_sealed_battery = (bool)pkthwinfo.status[2]; - pkthwinfo.s_show_out_tension = (bool)pkthwinfo.status[3]; - pkthwinfo.s_show_temperature = (bool)pkthwinfo.status[4]; - pkthwinfo.s_show_charger_current = (bool)pkthwinfo.status[5]; - pkthwinfo.chargercurrent = (int)datapkt[15]; - if (pkthwinfo.size > 18) { - for (i = 0; i < 16; i++) - pkthwinfo.serial[i] = datapkt[16 + i]; - pkthwinfo.year = datapkt[32]; - pkthwinfo.month = datapkt[33]; - pkthwinfo.wday = datapkt[34]; - pkthwinfo.hour = datapkt[35]; - pkthwinfo.minute = datapkt[36]; - pkthwinfo.second = datapkt[37]; - pkthwinfo.alarmyear = datapkt[38]; - pkthwinfo.alarmmonth = datapkt[39]; - pkthwinfo.alarmday = datapkt[40]; - pkthwinfo.alarmhour = datapkt[41]; - pkthwinfo.alarmminute = datapkt[42]; - pkthwinfo.alarmsecond = datapkt[43]; - pkthwinfo.checksum = datapkt[48]; - checksum = calculate_checksum(datapkt,1,47); - } /* end if */ - else { - pkthwinfo.checksum = datapkt[16]; - checksum = calculate_checksum(datapkt,1,15); - } - pkthwinfo.checksum_calc = checksum; - if (pkthwinfo.checksum == checksum) - pkthwinfo.checksum_ok = true; - - if (debug_pkt_hwinfo) { - pdatapacket(datapkt, size); - print_pkt_hwinfo(pkthwinfo); - } - - return pkthwinfo; + }; + + pkthwinfo.size = (int)datapkt[1]; + pkthwinfo.type = datapkt[2]; + pkthwinfo.model = (int)datapkt[3]; + pkthwinfo.hardwareversion = (int)datapkt[4]; + pkthwinfo.softwareversion = (int)datapkt[5]; + pkthwinfo.configuration = datapkt[6]; + for (i = 0; i < 5; i++) + pkthwinfo.configuration_array[i] = get_bit_in_position(&datapkt[6], sizeof(datapkt[6]), i, 0); + /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) + * have same problem. I won't have so much equipment to test + * these, then we need help to test more */ + pkthwinfo.c_oem_mode = (bool)pkthwinfo.configuration_array[0]; + pkthwinfo.c_buzzer_disable = (bool)pkthwinfo.configuration_array[1]; + pkthwinfo.c_potmin_disable = (bool)pkthwinfo.configuration_array[2]; + pkthwinfo.c_rearm_enable = (bool)pkthwinfo.configuration_array[3]; + pkthwinfo.c_bootloader_enable = (bool)pkthwinfo.configuration_array[4]; + pkthwinfo.numbatteries = (int)datapkt[7]; + pkthwinfo.undervoltagein120V = (int)datapkt[8]; + pkthwinfo.overvoltagein120V = (int)datapkt[9]; + pkthwinfo.undervoltagein220V = (int)datapkt[10]; + pkthwinfo.overvoltagein220V = (int)datapkt[11]; + pkthwinfo.tensionout120V = (int)datapkt[12]; + pkthwinfo.tensionout220V = (int)datapkt[13]; + pkthwinfo.statusval = datapkt[14]; + for (i = 0; i < 6; i++) + pkthwinfo.status[i] = get_bit_in_position(&datapkt[14], sizeof(datapkt[14]), i, 0); + /* TODO: check if ANY OTHER VARIABLES (like hardware array bits) + * have same problem. I won't have so much equipment to test + * these, then we need help to test more */ + pkthwinfo.s_220V_in = (bool)pkthwinfo.status[0]; + pkthwinfo.s_220V_out = (bool)pkthwinfo.status[1]; + pkthwinfo.s_sealed_battery = (bool)pkthwinfo.status[2]; + pkthwinfo.s_show_out_tension = (bool)pkthwinfo.status[3]; + pkthwinfo.s_show_temperature = (bool)pkthwinfo.status[4]; + pkthwinfo.s_show_charger_current = (bool)pkthwinfo.status[5]; + pkthwinfo.chargercurrent = (int)datapkt[15]; + if (pkthwinfo.size > 18) { + for (i = 0; i < 16; i++) + pkthwinfo.serial[i] = datapkt[16 + i]; + pkthwinfo.year = datapkt[32]; + pkthwinfo.month = datapkt[33]; + pkthwinfo.wday = datapkt[34]; + pkthwinfo.hour = datapkt[35]; + pkthwinfo.minute = datapkt[36]; + pkthwinfo.second = datapkt[37]; + pkthwinfo.alarmyear = datapkt[38]; + pkthwinfo.alarmmonth = datapkt[39]; + pkthwinfo.alarmday = datapkt[40]; + pkthwinfo.alarmhour = datapkt[41]; + pkthwinfo.alarmminute = datapkt[42]; + pkthwinfo.alarmsecond = datapkt[43]; + pkthwinfo.checksum = datapkt[48]; + checksum = calculate_checksum(datapkt, 1, 47); + } /* end if */ + else { + pkthwinfo.checksum = datapkt[16]; + checksum = calculate_checksum(datapkt, 1, 15); + } + pkthwinfo.checksum_calc = checksum; + if (pkthwinfo.checksum == checksum) + pkthwinfo.checksum_ok = true; + + if (debug_pkt_hwinfo) { + pdatapacket(datapkt, size); + print_pkt_hwinfo(pkthwinfo); + } + + return pkthwinfo; } #if 0 static int write_serial(int fd, const char * dados, int size) { - if (fd > 0) { - ssize_t bytes_written = write(fd, dados, size); - if (bytes_written < 0) - return -1; - if (tcdrain(fd) != 0) - return -2; - return size; - } - else - return fd; + if (fd > 0) { + ssize_t bytes_written = write(fd, dados, size); + if (bytes_written < 0) + return -1; + if (tcdrain(fd) != 0) + return -2; + return size; + } + else + return fd; } #endif static int write_serial_int(int fd, const unsigned int * data, int size) { - if (fd > 0) { - ssize_t bytes_written; - uint8_t *message = NULL; - int i = 0; - - message = xcalloc(size, sizeof(uint8_t)); - for (i = 0; i < size; i++) { - message[i] = (uint8_t)data[i]; - /* //upsdebugx(1,"%d %c %u %d %c %u",message[i],message[i],data[i],data[i]); */ - } - bytes_written = write(fd, message, size); - free(message); - - if (bytes_written < 0) - return -1; - if (tcdrain(fd) != 0) - return -2; - return i; - } - else - return fd; + if (fd > 0) { + ssize_t bytes_written; + uint8_t *message = NULL; + int i = 0; + + message = xcalloc(size, sizeof(uint8_t)); + for (i = 0; i < size; i++) { + message[i] = (uint8_t)data[i]; + /* //upsdebugx(1, "%d %c %u %d %c %u", message[i], message[i], data[i], data[i]); */ + } + bytes_written = write(fd, message, size); + free(message); + + if (bytes_written < 0) + return -1; + if (tcdrain(fd) != 0) + return -2; + return i; + } + else + return fd; } #if 0 static char * strtolow(char* s) { - for(char *p=s; *p; p++) *p=tolower(*p); - return s; + char *p; + for (p = s; *p; p++) + *p = tolower(*p); + return s; } #endif static upsinfo getupsinfo(unsigned int upscode) { - upsinfo data; - switch(upscode) { - case 1: - data.upscode = 1; - strcpy(data.upsdesc,"NHS COMPACT PLUS"); - data.VA = 1000; - break; - - case 2: - data.upscode = 2; - strcpy(data.upsdesc,"NHS COMPACT PLUS SENOIDAL"); - data.VA = 1000; - break; - - case 3: - data.upscode = 3; - strcpy(data.upsdesc,"NHS COMPACT PLUS RACK"); - data.VA = 1000; - break; - - case 4: - data.upscode = 4; - strcpy(data.upsdesc,"NHS PREMIUM PDV"); - data.VA = 1500; - break; - - case 5: - data.upscode = 5; - strcpy(data.upsdesc,"NHS PREMIUM PDV SENOIDAL"); - data.VA = 1500; - break; - - case 6: - data.upscode = 6; - strcpy(data.upsdesc,"NHS PREMIUM 1500VA"); - data.VA = 1500; - break; - - case 7: - data.upscode = 7; - strcpy(data.upsdesc,"NHS PREMIUM 2200VA"); - data.VA = 2200; - break; - - case 8: - data.upscode = 8; - strcpy(data.upsdesc,"NHS PREMIUM SENOIDAL"); - data.VA = 1500; - break; - - case 9: - data.upscode = 9; - strcpy(data.upsdesc,"NHS LASER 2600VA"); - data.VA = 2600; - break; - - case 10: - data.upscode = 10; - strcpy(data.upsdesc,"NHS LASER 3300VA"); - data.VA = 3300; - break; - - case 11: - data.upscode = 11; - strcpy(data.upsdesc,"NHS LASER 2600VA ISOLADOR"); - data.VA = 2600; - break; - - case 12: - data.upscode = 12; - strcpy(data.upsdesc,"NHS LASER SENOIDAL"); - data.VA = 2600; - break; - - case 13: - data.upscode = 13; - strcpy(data.upsdesc,"NHS LASER ON-LINE"); - data.VA = 2600; - break; - - case 15: - data.upscode = 15; - strcpy(data.upsdesc,"NHS COMPACT PLUS 2003"); - data.VA = 1000; - break; - - case 16: - data.upscode = 16; - strcpy(data.upsdesc,"COMPACT PLUS SENOIDAL 2003"); - data.VA = 1000; - break; - - case 17: - data.upscode = 17; - strcpy(data.upsdesc,"COMPACT PLUS RACK 2003"); - data.VA = 1000; - break; - - case 18: - data.upscode = 18; - strcpy(data.upsdesc,"PREMIUM PDV 2003"); - data.VA = 1500; - break; - - case 19: - data.upscode = 19; - strcpy(data.upsdesc,"PREMIUM PDV SENOIDAL 2003"); - data.VA = 1500; - break; - - case 20: - data.upscode = 20; - strcpy(data.upsdesc,"PREMIUM 1500VA 2003"); - data.VA = 1500; - break; - - case 21: - data.upscode = 21; - strcpy(data.upsdesc,"PREMIUM 2200VA 2003"); - data.VA = 2200; - break; - - case 22: - data.upscode = 22; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 2003"); - data.VA = 1500; - break; - - case 23: - data.upscode = 23; - strcpy(data.upsdesc,"LASER 2600VA 2003"); - data.VA = 2600; - break; - - case 24: - data.upscode = 24; - strcpy(data.upsdesc,"LASER 3300VA 2003"); - data.VA = 3300; - break; - - case 25: - data.upscode = 25; - strcpy(data.upsdesc,"LASER 2600VA ISOLADOR 2003"); - data.VA = 2600; - break; - - case 26: - data.upscode = 26; - strcpy(data.upsdesc,"LASER SENOIDAL 2003"); - data.VA = 2600; - break; - - case 27: - data.upscode = 27; - strcpy(data.upsdesc,"PDV ONLINE 2003"); - data.VA = 1500; - break; - - case 28: - data.upscode = 28; - strcpy(data.upsdesc,"LASER ONLINE 2003"); - data.VA = 3300; - break; - - case 29: - data.upscode = 29; - strcpy(data.upsdesc,"EXPERT ONLINE 2003"); - data.VA = 5000; - break; - - case 30: - data.upscode = 30; - strcpy(data.upsdesc,"MINI 2"); - data.VA = 500; - break; - - case 31: - data.upscode = 31; - strcpy(data.upsdesc,"COMPACT PLUS 2"); - data.VA = 1000; - break; - - case 32: - data.upscode = 32; - strcpy(data.upsdesc,"LASER ON-LINE"); - data.VA = 2600; - break; - - case 33: - data.upscode = 33; - strcpy(data.upsdesc,"PDV SENOIDAL 1500VA"); - data.VA = 1500; - break; - - case 34: - data.upscode = 34; - strcpy(data.upsdesc,"PDV SENOIDAL 1000VA"); - data.VA = 1000; - break; - - case 36: - data.upscode = 36; - strcpy(data.upsdesc,"LASER ONLINE 3750VA"); - data.VA = 3750; - break; - - case 37: - data.upscode = 37; - strcpy(data.upsdesc,"LASER ONLINE 5000VA"); - data.VA = 5000; - break; - - case 38: - data.upscode = 38; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 2000VA"); - data.VA = 2000; - break; - - case 39: - data.upscode = 39; - strcpy(data.upsdesc,"LASER SENOIDAL 3500VA"); - data.VA = 3500; - break; - - case 40: - data.upscode = 40; - strcpy(data.upsdesc,"PREMIUM PDV 1200VA"); - data.VA = 1200; - break; - - case 41: - data.upscode = 41; - strcpy(data.upsdesc,"PREMIUM 1500VA"); - data.VA = 1500; - break; - - case 42: - data.upscode = 42; - strcpy(data.upsdesc,"PREMIUM 2200VA"); - data.VA = 2200; - break; - - case 43: - data.upscode = 43; - strcpy(data.upsdesc,"LASER 2600VA"); - data.VA = 2600; - break; - - case 44: - data.upscode = 44; - strcpy(data.upsdesc,"LASER 3300VA"); - data.VA = 3300; - break; - - case 45: - data.upscode = 45; - strcpy(data.upsdesc,"COMPACT PLUS SENOIDAL 700VA"); - data.VA = 700; - break; - - case 46: - data.upscode = 46; - strcpy(data.upsdesc,"PREMIUM ONLINE 2000VA"); - data.VA = 2000; - break; - - case 47: - data.upscode = 47; - strcpy(data.upsdesc,"EXPERT ONLINE 10000VA"); - data.VA = 10000; - break; - - case 48: - data.upscode = 48; - strcpy(data.upsdesc,"LASER SENOIDAL 4200VA"); - data.VA = 4200; - break; - - case 49: - data.upscode = 49; - strcpy(data.upsdesc,"NHS COMPACT PLUS EXTENDIDO 1500VA"); - data.VA = 1500; - break; - - case 50: - data.upscode = 50; - strcpy(data.upsdesc,"LASER ONLINE 6000VA"); - data.VA = 6000; - break; - - case 51: - data.upscode = 51; - strcpy(data.upsdesc,"LASER EXT 3300VA"); - data.VA = 3300; - break; - - case 52: - data.upscode = 52; - strcpy(data.upsdesc,"NHS COMPACT PLUS 1200VA"); - data.VA = 1200; - break; - - case 53: - data.upscode = 53; - strcpy(data.upsdesc,"LASER SENOIDAL 3000VA GII"); - data.VA = 3000; - break; - - case 54: - data.upscode = 54; - strcpy(data.upsdesc,"LASER SENOIDAL 3500VA GII"); - data.VA = 3500; - break; - - case 55: - data.upscode = 55; - strcpy(data.upsdesc,"LASER SENOIDAL 4200VA GII"); - data.VA = 4200; - break; - - case 56: - data.upscode = 56; - strcpy(data.upsdesc,"LASER ONLINE 3000VA"); - data.VA = 3000; - break; - - case 57: - data.upscode = 57; - strcpy(data.upsdesc,"LASER ONLINE 3750VA"); - data.VA = 3750; - break; - - case 58: - data.upscode = 58; - strcpy(data.upsdesc,"LASER ONLINE 5000VA"); - data.VA = 5000; - break; - - case 59: - data.upscode = 59; - strcpy(data.upsdesc,"LASER ONLINE 6000VA"); - data.VA = 6000; - break; - - case 60: - data.upscode = 60; - strcpy(data.upsdesc,"PREMIUM ONLINE 2000VA"); - data.VA = 2000; - break; - - case 61: - data.upscode = 61; - strcpy(data.upsdesc,"PREMIUM ONLINE 1500VA"); - data.VA = 1500; - break; - - case 62: - data.upscode = 62; - strcpy(data.upsdesc,"PREMIUM ONLINE 1200VA"); - data.VA = 1200; - break; - - case 63: - data.upscode = 63; - strcpy(data.upsdesc,"COMPACT PLUS II MAX 1400VA"); - data.VA = 1400; - break; - - case 64: - data.upscode = 64; - strcpy(data.upsdesc,"PREMIUM PDV MAX 2200VA"); - data.VA = 2200; - break; - - case 65: - data.upscode = 65; - strcpy(data.upsdesc,"PREMIUM PDV 3000VA"); - data.VA = 3000; - break; - - case 66: - data.upscode = 66; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 2200VA GII"); - data.VA = 2200; - break; - - case 67: - data.upscode = 67; - strcpy(data.upsdesc,"LASER PRIME SENOIDAL 3200VA GII"); - data.VA = 3200; - break; - - case 68: - data.upscode = 68; - strcpy(data.upsdesc,"PREMIUM RACK ONLINE 3000VA"); - data.VA = 3000; - break; - - case 69: - data.upscode = 69; - strcpy(data.upsdesc,"PREMIUM ONLINE 3000VA"); - data.VA = 3000; - break; - - case 70: - data.upscode = 70; - strcpy(data.upsdesc,"LASER ONLINE 4000VA"); - data.VA = 4000; - break; - - case 71: - data.upscode = 71; - strcpy(data.upsdesc,"LASER ONLINE 7500VA"); - data.VA = 7500; - break; - - case 72: - data.upscode = 72; - strcpy(data.upsdesc,"LASER ONLINE BIFASICO 5000VA"); - data.VA = 5000; - break; - - case 73: - data.upscode = 73; - strcpy(data.upsdesc,"LASER ONLINE BIFASICO 6000VA"); - data.VA = 6000; - break; - - case 74: - data.upscode = 74; - strcpy(data.upsdesc,"LASER ONLINE BIFASICO 7500VA"); - data.VA = 7500; - break; - - case 75: - data.upscode = 75; - strcpy(data.upsdesc,"NHS MINI ST"); - data.VA = 500; - break; - - case 76: - data.upscode = 76; - strcpy(data.upsdesc,"NHS MINI 120"); - data.VA = 120; - break; - - case 77: - data.upscode = 77; - strcpy(data.upsdesc,"NHS MINI BIVOLT"); - data.VA = 500; - break; - - case 78: - data.upscode = 78; - strcpy(data.upsdesc,"PDV 600"); - data.VA = 600; - break; - - case 79: - data.upscode = 79; - strcpy(data.upsdesc,"NHS MINI MAX"); - data.VA = 500; - break; - - case 80: - data.upscode = 80; - strcpy(data.upsdesc,"NHS MINI EXT"); - data.VA = 500; - break; - - case 81: - data.upscode = 81; - strcpy(data.upsdesc,"NHS AUTONOMY PDV 4T"); - data.VA = 4000; - break; - - case 82: - data.upscode = 82; - strcpy(data.upsdesc,"NHS AUTONOMY PDV 8T"); - data.VA = 8000; - break; - - case 83: - data.upscode = 83; - strcpy(data.upsdesc,"NHS COMPACT PLUS RACK 1200VA"); - data.VA = 1200; - break; - - case 84: - data.upscode = 84; - strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 1500VA"); - data.VA = 1500; - break; - - case 85: - data.upscode = 85; - strcpy(data.upsdesc,"NHS PDV RACK 1500VA"); - data.VA = 1500; - break; - - case 86: - data.upscode = 86; - strcpy(data.upsdesc,"NHS PDV 1400VA S GII"); - data.VA = 1400; - break; - - case 87: - data.upscode = 87; - strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 1500VA"); - data.VA = 1500; - break; - - case 88: - data.upscode = 88; - strcpy(data.upsdesc,"LASER PRIME SENOIDAL ISOLADOR 2000VA"); - data.VA = 2000; - break; - - case 89: - data.upscode = 89; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 2400VA GII"); - data.VA = 2400; - break; - - case 90: - data.upscode = 90; - strcpy(data.upsdesc,"NHS PDV 1400VA S 8T GII"); - data.VA = 1400; - break; - - case 91: - data.upscode = 91; - strcpy(data.upsdesc,"PREMIUM ONLINE 2000VA"); - data.VA = 2000; - break; - - case 92: - data.upscode = 92; - strcpy(data.upsdesc,"LASER PRIME ONLINE 2200VA"); - data.VA = 2200; - break; - - case 93: - data.upscode = 93; - strcpy(data.upsdesc,"PREMIUM RACK ONLINE 2200VA"); - data.VA = 2200; - break; - - case 94: - data.upscode = 94; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 2400VA GII"); - data.VA = 2400; - break; - - case 95: - data.upscode = 95; - strcpy(data.upsdesc,"LASER ONLINE 10000VA"); - data.VA = 10000; - break; - - case 96: - data.upscode = 96; - strcpy(data.upsdesc,"LASER ONLINE BIFASICO 10000VA"); - data.VA = 10000; - break; - - case 97: - data.upscode = 97; - strcpy(data.upsdesc,"LASER SENOIDAL 3300VA GII"); - data.VA = 3300; - break; - - case 98: - data.upscode = 98; - strcpy(data.upsdesc,"LASER SENOIDAL 2600VA GII"); - data.VA = 2600; - break; - - case 99: - data.upscode = 99; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 3000VA GII"); - data.VA = 3000; - break; - - case 100: - data.upscode = 100; - strcpy(data.upsdesc,"PREMIUM SENOIDAL 2200VA GII"); - data.VA = 2200; - break; - - case 101: - data.upscode = 101; - strcpy(data.upsdesc,"LASER ONLINE BIFASICO 4000VA"); - data.VA = 4000; - break; - - case 102: - data.upscode = 102; - strcpy(data.upsdesc,"LASER ONLINE 12000VA"); - data.VA = 12000; - break; - - case 103: - data.upscode = 103; - strcpy(data.upsdesc,"LASER ONLINE 8000VA"); - data.VA = 8000; - break; - - case 104: - data.upscode = 104; - strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 1000VA"); - data.VA = 1000; - break; - - case 105: - data.upscode = 105; - strcpy(data.upsdesc,"MINI SENOIDAL 500VA"); - data.VA = 500; - break; - - case 106: - data.upscode = 106; - strcpy(data.upsdesc,"LASER SENOIDAL 5000VA GII"); - data.VA = 5000; - break; - - case 107: - data.upscode = 107; - strcpy(data.upsdesc,"COMPACT PLUS SENOIDAL 1000VA"); - data.VA = 1000; - break; - - case 108: - data.upscode = 108; - strcpy(data.upsdesc,"QUAD_COM 80A"); - data.VA = 0; - break; - - case 109: - data.upscode = 109; - strcpy(data.upsdesc,"LASER ONLINE 5000VA"); - data.VA = 5000; - break; - - case 113: - data.upscode = 113; - strcpy(data.upsdesc,"PDV SENOIDAL ISOLADOR 700VA"); - data.VA = 700; - break; - - default: - data.upscode = -1; - strcpy(data.upsdesc,"NHS UNKNOWN"); - data.VA = 0; - break; - } - return data; + upsinfo data; + switch (upscode) { + case 1: + data.upscode = 1; + strcpy(data.upsdesc, "NHS COMPACT PLUS"); + data.VA = 1000; + break; + + case 2: + data.upscode = 2; + strcpy(data.upsdesc, "NHS COMPACT PLUS SENOIDAL"); + data.VA = 1000; + break; + + case 3: + data.upscode = 3; + strcpy(data.upsdesc, "NHS COMPACT PLUS RACK"); + data.VA = 1000; + break; + + case 4: + data.upscode = 4; + strcpy(data.upsdesc, "NHS PREMIUM PDV"); + data.VA = 1500; + break; + + case 5: + data.upscode = 5; + strcpy(data.upsdesc, "NHS PREMIUM PDV SENOIDAL"); + data.VA = 1500; + break; + + case 6: + data.upscode = 6; + strcpy(data.upsdesc, "NHS PREMIUM 1500VA"); + data.VA = 1500; + break; + + case 7: + data.upscode = 7; + strcpy(data.upsdesc, "NHS PREMIUM 2200VA"); + data.VA = 2200; + break; + + case 8: + data.upscode = 8; + strcpy(data.upsdesc, "NHS PREMIUM SENOIDAL"); + data.VA = 1500; + break; + + case 9: + data.upscode = 9; + strcpy(data.upsdesc, "NHS LASER 2600VA"); + data.VA = 2600; + break; + + case 10: + data.upscode = 10; + strcpy(data.upsdesc, "NHS LASER 3300VA"); + data.VA = 3300; + break; + + case 11: + data.upscode = 11; + strcpy(data.upsdesc, "NHS LASER 2600VA ISOLADOR"); + data.VA = 2600; + break; + + case 12: + data.upscode = 12; + strcpy(data.upsdesc, "NHS LASER SENOIDAL"); + data.VA = 2600; + break; + + case 13: + data.upscode = 13; + strcpy(data.upsdesc, "NHS LASER ON-LINE"); + data.VA = 2600; + break; + + case 15: + data.upscode = 15; + strcpy(data.upsdesc, "NHS COMPACT PLUS 2003"); + data.VA = 1000; + break; + + case 16: + data.upscode = 16; + strcpy(data.upsdesc, "COMPACT PLUS SENOIDAL 2003"); + data.VA = 1000; + break; + + case 17: + data.upscode = 17; + strcpy(data.upsdesc, "COMPACT PLUS RACK 2003"); + data.VA = 1000; + break; + + case 18: + data.upscode = 18; + strcpy(data.upsdesc, "PREMIUM PDV 2003"); + data.VA = 1500; + break; + + case 19: + data.upscode = 19; + strcpy(data.upsdesc, "PREMIUM PDV SENOIDAL 2003"); + data.VA = 1500; + break; + + case 20: + data.upscode = 20; + strcpy(data.upsdesc, "PREMIUM 1500VA 2003"); + data.VA = 1500; + break; + + case 21: + data.upscode = 21; + strcpy(data.upsdesc, "PREMIUM 2200VA 2003"); + data.VA = 2200; + break; + + case 22: + data.upscode = 22; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 2003"); + data.VA = 1500; + break; + + case 23: + data.upscode = 23; + strcpy(data.upsdesc, "LASER 2600VA 2003"); + data.VA = 2600; + break; + + case 24: + data.upscode = 24; + strcpy(data.upsdesc, "LASER 3300VA 2003"); + data.VA = 3300; + break; + + case 25: + data.upscode = 25; + strcpy(data.upsdesc, "LASER 2600VA ISOLADOR 2003"); + data.VA = 2600; + break; + + case 26: + data.upscode = 26; + strcpy(data.upsdesc, "LASER SENOIDAL 2003"); + data.VA = 2600; + break; + + case 27: + data.upscode = 27; + strcpy(data.upsdesc, "PDV ONLINE 2003"); + data.VA = 1500; + break; + + case 28: + data.upscode = 28; + strcpy(data.upsdesc, "LASER ONLINE 2003"); + data.VA = 3300; + break; + + case 29: + data.upscode = 29; + strcpy(data.upsdesc, "EXPERT ONLINE 2003"); + data.VA = 5000; + break; + + case 30: + data.upscode = 30; + strcpy(data.upsdesc, "MINI 2"); + data.VA = 500; + break; + + case 31: + data.upscode = 31; + strcpy(data.upsdesc, "COMPACT PLUS 2"); + data.VA = 1000; + break; + + case 32: + data.upscode = 32; + strcpy(data.upsdesc, "LASER ON-LINE"); + data.VA = 2600; + break; + + case 33: + data.upscode = 33; + strcpy(data.upsdesc, "PDV SENOIDAL 1500VA"); + data.VA = 1500; + break; + + case 34: + data.upscode = 34; + strcpy(data.upsdesc, "PDV SENOIDAL 1000VA"); + data.VA = 1000; + break; + + case 36: + data.upscode = 36; + strcpy(data.upsdesc, "LASER ONLINE 3750VA"); + data.VA = 3750; + break; + + case 37: + data.upscode = 37; + strcpy(data.upsdesc, "LASER ONLINE 5000VA"); + data.VA = 5000; + break; + + case 38: + data.upscode = 38; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 2000VA"); + data.VA = 2000; + break; + + case 39: + data.upscode = 39; + strcpy(data.upsdesc, "LASER SENOIDAL 3500VA"); + data.VA = 3500; + break; + + case 40: + data.upscode = 40; + strcpy(data.upsdesc, "PREMIUM PDV 1200VA"); + data.VA = 1200; + break; + + case 41: + data.upscode = 41; + strcpy(data.upsdesc, "PREMIUM 1500VA"); + data.VA = 1500; + break; + + case 42: + data.upscode = 42; + strcpy(data.upsdesc, "PREMIUM 2200VA"); + data.VA = 2200; + break; + + case 43: + data.upscode = 43; + strcpy(data.upsdesc, "LASER 2600VA"); + data.VA = 2600; + break; + + case 44: + data.upscode = 44; + strcpy(data.upsdesc, "LASER 3300VA"); + data.VA = 3300; + break; + + case 45: + data.upscode = 45; + strcpy(data.upsdesc, "COMPACT PLUS SENOIDAL 700VA"); + data.VA = 700; + break; + + case 46: + data.upscode = 46; + strcpy(data.upsdesc, "PREMIUM ONLINE 2000VA"); + data.VA = 2000; + break; + + case 47: + data.upscode = 47; + strcpy(data.upsdesc, "EXPERT ONLINE 10000VA"); + data.VA = 10000; + break; + + case 48: + data.upscode = 48; + strcpy(data.upsdesc, "LASER SENOIDAL 4200VA"); + data.VA = 4200; + break; + + case 49: + data.upscode = 49; + strcpy(data.upsdesc, "NHS COMPACT PLUS EXTENDIDO 1500VA"); + data.VA = 1500; + break; + + case 50: + data.upscode = 50; + strcpy(data.upsdesc, "LASER ONLINE 6000VA"); + data.VA = 6000; + break; + + case 51: + data.upscode = 51; + strcpy(data.upsdesc, "LASER EXT 3300VA"); + data.VA = 3300; + break; + + case 52: + data.upscode = 52; + strcpy(data.upsdesc, "NHS COMPACT PLUS 1200VA"); + data.VA = 1200; + break; + + case 53: + data.upscode = 53; + strcpy(data.upsdesc, "LASER SENOIDAL 3000VA GII"); + data.VA = 3000; + break; + + case 54: + data.upscode = 54; + strcpy(data.upsdesc, "LASER SENOIDAL 3500VA GII"); + data.VA = 3500; + break; + + case 55: + data.upscode = 55; + strcpy(data.upsdesc, "LASER SENOIDAL 4200VA GII"); + data.VA = 4200; + break; + + case 56: + data.upscode = 56; + strcpy(data.upsdesc, "LASER ONLINE 3000VA"); + data.VA = 3000; + break; + + case 57: + data.upscode = 57; + strcpy(data.upsdesc, "LASER ONLINE 3750VA"); + data.VA = 3750; + break; + + case 58: + data.upscode = 58; + strcpy(data.upsdesc, "LASER ONLINE 5000VA"); + data.VA = 5000; + break; + + case 59: + data.upscode = 59; + strcpy(data.upsdesc, "LASER ONLINE 6000VA"); + data.VA = 6000; + break; + + case 60: + data.upscode = 60; + strcpy(data.upsdesc, "PREMIUM ONLINE 2000VA"); + data.VA = 2000; + break; + + case 61: + data.upscode = 61; + strcpy(data.upsdesc, "PREMIUM ONLINE 1500VA"); + data.VA = 1500; + break; + + case 62: + data.upscode = 62; + strcpy(data.upsdesc, "PREMIUM ONLINE 1200VA"); + data.VA = 1200; + break; + + case 63: + data.upscode = 63; + strcpy(data.upsdesc, "COMPACT PLUS II MAX 1400VA"); + data.VA = 1400; + break; + + case 64: + data.upscode = 64; + strcpy(data.upsdesc, "PREMIUM PDV MAX 2200VA"); + data.VA = 2200; + break; + + case 65: + data.upscode = 65; + strcpy(data.upsdesc, "PREMIUM PDV 3000VA"); + data.VA = 3000; + break; + + case 66: + data.upscode = 66; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 2200VA GII"); + data.VA = 2200; + break; + + case 67: + data.upscode = 67; + strcpy(data.upsdesc, "LASER PRIME SENOIDAL 3200VA GII"); + data.VA = 3200; + break; + + case 68: + data.upscode = 68; + strcpy(data.upsdesc, "PREMIUM RACK ONLINE 3000VA"); + data.VA = 3000; + break; + + case 69: + data.upscode = 69; + strcpy(data.upsdesc, "PREMIUM ONLINE 3000VA"); + data.VA = 3000; + break; + + case 70: + data.upscode = 70; + strcpy(data.upsdesc, "LASER ONLINE 4000VA"); + data.VA = 4000; + break; + + case 71: + data.upscode = 71; + strcpy(data.upsdesc, "LASER ONLINE 7500VA"); + data.VA = 7500; + break; + + case 72: + data.upscode = 72; + strcpy(data.upsdesc, "LASER ONLINE BIFASICO 5000VA"); + data.VA = 5000; + break; + + case 73: + data.upscode = 73; + strcpy(data.upsdesc, "LASER ONLINE BIFASICO 6000VA"); + data.VA = 6000; + break; + + case 74: + data.upscode = 74; + strcpy(data.upsdesc, "LASER ONLINE BIFASICO 7500VA"); + data.VA = 7500; + break; + + case 75: + data.upscode = 75; + strcpy(data.upsdesc, "NHS MINI ST"); + data.VA = 500; + break; + + case 76: + data.upscode = 76; + strcpy(data.upsdesc, "NHS MINI 120"); + data.VA = 120; + break; + + case 77: + data.upscode = 77; + strcpy(data.upsdesc, "NHS MINI BIVOLT"); + data.VA = 500; + break; + + case 78: + data.upscode = 78; + strcpy(data.upsdesc, "PDV 600"); + data.VA = 600; + break; + + case 79: + data.upscode = 79; + strcpy(data.upsdesc, "NHS MINI MAX"); + data.VA = 500; + break; + + case 80: + data.upscode = 80; + strcpy(data.upsdesc, "NHS MINI EXT"); + data.VA = 500; + break; + + case 81: + data.upscode = 81; + strcpy(data.upsdesc, "NHS AUTONOMY PDV 4T"); + data.VA = 4000; + break; + + case 82: + data.upscode = 82; + strcpy(data.upsdesc, "NHS AUTONOMY PDV 8T"); + data.VA = 8000; + break; + + case 83: + data.upscode = 83; + strcpy(data.upsdesc, "NHS COMPACT PLUS RACK 1200VA"); + data.VA = 1200; + break; + + case 84: + data.upscode = 84; + strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1500VA"); + data.VA = 1500; + break; + + case 85: + data.upscode = 85; + strcpy(data.upsdesc, "NHS PDV RACK 1500VA"); + data.VA = 1500; + break; + + case 86: + data.upscode = 86; + strcpy(data.upsdesc, "NHS PDV 1400VA S GII"); + data.VA = 1400; + break; + + case 87: + data.upscode = 87; + strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1500VA"); + data.VA = 1500; + break; + + case 88: + data.upscode = 88; + strcpy(data.upsdesc, "LASER PRIME SENOIDAL ISOLADOR 2000VA"); + data.VA = 2000; + break; + + case 89: + data.upscode = 89; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 2400VA GII"); + data.VA = 2400; + break; + + case 90: + data.upscode = 90; + strcpy(data.upsdesc, "NHS PDV 1400VA S 8T GII"); + data.VA = 1400; + break; + + case 91: + data.upscode = 91; + strcpy(data.upsdesc, "PREMIUM ONLINE 2000VA"); + data.VA = 2000; + break; + + case 92: + data.upscode = 92; + strcpy(data.upsdesc, "LASER PRIME ONLINE 2200VA"); + data.VA = 2200; + break; + + case 93: + data.upscode = 93; + strcpy(data.upsdesc, "PREMIUM RACK ONLINE 2200VA"); + data.VA = 2200; + break; + + case 94: + data.upscode = 94; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 2400VA GII"); + data.VA = 2400; + break; + + case 95: + data.upscode = 95; + strcpy(data.upsdesc, "LASER ONLINE 10000VA"); + data.VA = 10000; + break; + + case 96: + data.upscode = 96; + strcpy(data.upsdesc, "LASER ONLINE BIFASICO 10000VA"); + data.VA = 10000; + break; + + case 97: + data.upscode = 97; + strcpy(data.upsdesc, "LASER SENOIDAL 3300VA GII"); + data.VA = 3300; + break; + + case 98: + data.upscode = 98; + strcpy(data.upsdesc, "LASER SENOIDAL 2600VA GII"); + data.VA = 2600; + break; + + case 99: + data.upscode = 99; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 3000VA GII"); + data.VA = 3000; + break; + + case 100: + data.upscode = 100; + strcpy(data.upsdesc, "PREMIUM SENOIDAL 2200VA GII"); + data.VA = 2200; + break; + + case 101: + data.upscode = 101; + strcpy(data.upsdesc, "LASER ONLINE BIFASICO 4000VA"); + data.VA = 4000; + break; + + case 102: + data.upscode = 102; + strcpy(data.upsdesc, "LASER ONLINE 12000VA"); + data.VA = 12000; + break; + + case 103: + data.upscode = 103; + strcpy(data.upsdesc, "LASER ONLINE 8000VA"); + data.VA = 8000; + break; + + case 104: + data.upscode = 104; + strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1000VA"); + data.VA = 1000; + break; + + case 105: + data.upscode = 105; + strcpy(data.upsdesc, "MINI SENOIDAL 500VA"); + data.VA = 500; + break; + + case 106: + data.upscode = 106; + strcpy(data.upsdesc, "LASER SENOIDAL 5000VA GII"); + data.VA = 5000; + break; + + case 107: + data.upscode = 107; + strcpy(data.upsdesc, "COMPACT PLUS SENOIDAL 1000VA"); + data.VA = 1000; + break; + + case 108: + data.upscode = 108; + strcpy(data.upsdesc, "QUAD_COM 80A"); + data.VA = 0; + break; + + case 109: + data.upscode = 109; + strcpy(data.upsdesc, "LASER ONLINE 5000VA"); + data.VA = 5000; + break; + + case 113: + data.upscode = 113; + strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 700VA"); + data.VA = 700; + break; + + default: + data.upscode = -1; + strcpy(data.upsdesc, "NHS UNKNOWN"); + data.VA = 0; + break; + } + return data; } static unsigned int get_va(int equipment) { - upsinfo ups; - char * va = getval("va"); - ups = getupsinfo(equipment); - if (ups.VA > 0) - return ups.VA; - else { - if (va) - return atoi(va); - else - fatalx(EXIT_FAILURE,"Please set VA (Volt Ampere) nominal capacity value to your equipment in ups.conf."); - } + upsinfo ups; + char *va = getval("va"); + + ups = getupsinfo(equipment); + if (ups.VA > 0) + return ups.VA; + else { + if (va) + return atoi(va); + else + fatalx(EXIT_FAILURE, "Please set VA (Volt Ampere) nominal capacity value to your equipment in ups.conf."); + } } static float get_pf(void) { - char * pf = getval("pf"); - if (pf) - return atof(pf); - else - return DEFAULTPF; + char *pf = getval("pf"); + if (pf) + return atof(pf); + else + return DEFAULTPF; } static unsigned int get_ah(void) { - char * ah = getval("ah"); - if (ah) - return (unsigned int)atoi(ah); - else - fatalx(EXIT_FAILURE,"Please set AH (Ampere Hour) value to your battery's equipment in ups.conf."); + char *ah = getval("ah"); + if (ah) + return (unsigned int)atoi(ah); + else + fatalx(EXIT_FAILURE, "Please set AH (Ampere Hour) value to your battery's equipment in ups.conf."); } static float get_vin_perc(char * var) { - char * perc = getval(var); - if (perc) - return atof(perc); - else - return DEFAULTPERC; + char *perc = getval(var); + if (perc) + return atof(perc); + else + return DEFAULTPERC; } void upsdrv_initinfo(void) { - char * b = getval("baud"); - upsdebugx(1,"Port is %s and baud_rate is %s",device_path,b); - baudrate = DEFAULTBAUD; - upsdebugx(1,"Start initinfo()"); - if (b) - baudrate = atoi(b); - if (device_path) { - if (strcasecmp(device_path,"auto") == 0) - strcpy(porta,DEFAULTPORT); - else - strcpy(porta,device_path); - serial_fd = openfd(porta,baudrate); - if (serial_fd == -1) - fatalx(EXIT_FAILURE,"Unable to open port %s with baud %d",porta,baudrate); - else { - upsdebugx(1,"Communication started on port %s, baud rate %d. Calling updateinfo()",porta,baudrate); - } - } - else - fatalx(EXIT_FAILURE,"Unable to define port and baud"); - upsdebugx(1,"End initinfo()"); + char *b = getval("baud"); + + upsdebugx(1, "Port is %s and baud_rate is %s", device_path, b); + baudrate = DEFAULTBAUD; + upsdebugx(1, "Start initinfo()"); + if (b) + baudrate = atoi(b); + if (device_path) { + if (strcasecmp(device_path, "auto") == 0) + strcpy(porta, DEFAULTPORT); + else + strcpy(porta, device_path); + serial_fd = openfd(porta, baudrate); + if (serial_fd == -1) + fatalx(EXIT_FAILURE, "Unable to open port %s with baud %d", porta, baudrate); + else { + upsdebugx(1, "Communication started on port %s, baud rate %d. Calling updateinfo()", porta, baudrate); + } + } + else + fatalx(EXIT_FAILURE, "Unable to define port and baud"); + upsdebugx(1, "End initinfo()"); } static float calculate_efficiency(float vacoutrms, float vacinrms) { - return (vacoutrms * vacinrms) / 100.0; + return (vacoutrms * vacinrms) / 100.0; } static unsigned int get_numbat(void) { - char * nb = getval("numbat"); - unsigned int retval = 0; - if (nb) - retval = atoi(nb); - return retval; + char *nb = getval("numbat"); + unsigned int retval = 0; + + if (nb) + retval = atoi(nb); + return retval; } void upsdrv_updateinfo(void) { - /* retries to open port */ - unsigned int retries = 3; - unsigned int i = 0; - char alarm[1024]; - unsigned int va = 0; - unsigned int ah = 0; - unsigned int vin_underv = 0; - unsigned int vin_overv = 0; - unsigned int perc = 0; - unsigned int vin = 0; - unsigned int vout = 0; - unsigned int autonomy_secs = 0; - float vin_low_warn = 0; - float vin_low_crit = 0; - float vin_high_warn = 0; - float vin_high_crit = 0; - float calculated = 0; - float vpower = 0; - float pf = 0; - long bcharge = 0; - int min_input_power = 0; - double tempodecorrido = 0.0; - unsigned int numbat = 0; - unsigned int vbat = 0; - float abat = 0; - float actual_current = 0; - upsinfo ups; - - upsdebugx(1,"Start updateinfo()"); - if ((serial_fd <= 0) && (i < retries)) { - upsdebugx(1,"Serial problem..."); - while (serial_fd <= 0) { - serial_fd = openfd(porta,baudrate); - upsdebugx(1,"Trying to reopen serial..."); - usleep(checktime); - retries++; - } - } - else { - /* Clean all read buffers to avoid errors: - * To clean OUTPUT buffer is TCOFLUSH. - * To both is TCIOFLUSH. - */ - /* //tcflush(serial_fd, TCIFLUSH); */ - chr = '\0'; - while (read(serial_fd, &chr,1) > 0) { - if (chr == 0xFF) { /* DataPacket start */ - datapacketstart = true; - } /* end for */ - if (datapacketstart) { - datapacket[datapacket_index] = chr; - datapacket_index++; - if (chr == 0xFE) { /* DataPacket */ - time_t now = time(NULL); - upsdebugx(1,"DATAPACKET INDEX IS %d",datapacket_index); - if (lastdp != 0) { - tempodecorrido = difftime(now, lastdp); - } - lastdp = now; - /* If size is 18 or 50, may be an answer packet. - * Then check if doesn't have already a packet processed. - * We don't need to read all times these information. - * Can be a corrupted packet too. */ - if (((datapacket_index == 18) || (datapacket_index == 50)) && (!lastpkthwinfo.checksum_ok)) { - lastpkthwinfo = mount_hwinfo(datapacket, datapacket_index); - } /* end if */ - else { - if (datapacket_index == 21) - lastpktdata = mount_datapacket(datapacket, datapacket_index, tempodecorrido,lastpkthwinfo); - } /* end else */ - /* Clean datapacket structure to avoid problems */ - datapacket_index = 0; - memset(datapacket,0,sizeof(datapacket)); - datapacketstart = false; - if (lastpktdata.checksum_ok) { - /* checksum is OK, then use it to set values */ - upsdebugx(1,"Data Packet seems be OK"); - if (lastpkthwinfo.size == 0) - upsdebugx(1,"Pkt HWINFO is not OK. See if will be requested next time!"); - else { - if (lastpkthwinfo.checksum_ok) { - upsdebugx(1,"Pkt HWINFO is OK. Model is %d, hwversion is %d and swversion is %d",lastpkthwinfo.model,lastpkthwinfo.hardwareversion,lastpkthwinfo.softwareversion); - /* We need to set data on NUT with data - * that I believe that I can calculate. - * Now setting data on NUT */ - ups = getupsinfo(lastpkthwinfo.model); - upsdebugx(1,"UPS Struct data: Code %d Model %s VA %d",ups.upscode,ups.upsdesc,ups.VA); - dstate_setinfo("device.model", "%s",ups.upsdesc); - dstate_setinfo("device.mfr","%s",MANUFACTURER); - dstate_setinfo("device.serial","%s",lastpkthwinfo.serial); - dstate_setinfo("device.type","%s","ups"); - - /* Setting UPS Status: - * OL -- On line (mains is present): Code below - * OB -- On battery (mains is not present) : Code below - * LB -- Low battery: Code below - * HB -- High battery: NHS doesn't have any variable with that information. Feel free to discover a way to set it - * RB -- The battery needs to be replaced: Well, as mentioned, we can write some infos on nobreak fw, on structures like pkt_hwinfo.year, pkt_hwinfo.month, etc. I never found any equipment with these values. - * CHRG -- The battery is charging: Code below - * DISCHRG -- The battery is discharging (inverter is providing load power): Code Below - * BYPASS -- UPS bypass circuit is active -- no battery protection is available: It's another PROBLEM, because NHS can work in bypass mode in some models, even if you have sealed batteries on it (without any external battery device). On the moment, i'll won't work with that. Feel free to discover how it work correctly. - * CAL -- UPS is currently performing runtime calibration (on battery) - * OFF -- UPS is offline and is not supplying power to the load - * OVER -- UPS is overloaded - * TRIM -- UPS is trimming incoming voltage (called "buck" in some hardware) - * BOOST -- UPS is boosting incoming voltage - * FSD -- Forced Shutdown (restricted use, see the note below) - */ - - /* Decision Chain commented below */ - - /* First we check if system is on battery or not */ - upsdebugx(1,"Set UPS status as OFF and start checking. s_battery_mode is %d",lastpktdata.s_battery_mode); - if (lastpkthwinfo.s_220V_in) { - upsdebugx(1,"I'm on 220v IN!. My overvoltage is %d",lastpkthwinfo.undervoltagein220V); - min_input_power = lastpkthwinfo.undervoltagein220V; - } - else { - upsdebugx(1,"I'm on 120v IN!. My overvoltage is %d",lastpkthwinfo.undervoltagein120V); - min_input_power = lastpkthwinfo.undervoltagein120V; - } - if (lastpktdata.s_battery_mode) { - /* ON BATTERY */ - upsdebugx(1,"UPS is on Battery Mode"); - dstate_setinfo("ups.status","%s","OB"); - if (lastpktdata.s_battery_low) { - /* If battery is LOW, warn user! */ - upsdebugx(1,"UPS is on Battery Mode and in Low Battery State"); - dstate_setinfo("ups.status","%s","LB"); - } /* end if */ - } /* end if */ - else { - /* Check if MAINS (power) is not preset. - * Well, we can check pkt_data.s_network_failure too... */ - if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { - upsdebugx(1, "UPS has power-in value %0.2f " - "and min_input_power is %d, " - "or network is in failure. Network failure is %d", - lastpktdata.vacinrms, - min_input_power, - lastpktdata.s_network_failure); - dstate_setinfo("ups.status","%s","DISCHRG"); - } /* end if */ - else { - /* MAINS is present. We need to check some situations. - * NHS only charge if have more than min_input_power. - * If MAINS is less than or equal to min_input_power, - * then the UPS goes to BATTERY */ - if (lastpktdata.vacinrms > min_input_power) { - upsdebugx(1,"UPS is on MAINS"); - if (lastpktdata.s_charger_on) { - upsdebugx(1,"UPS Charging..."); - dstate_setinfo("ups.status","%s","CHRG"); - } - else { - if ((lastpktdata.s_network_failure) || (lastpktdata.s_fast_network_failure)) { - upsdebugx(1,"UPS is on battery mode because network failure or fast network failure"); - dstate_setinfo("ups.status","%s","OB"); - } /* end if */ - else { - upsdebugx(1,"All is OK. UPS is on ONLINE!"); - dstate_setinfo("ups.status","%s","OL"); - } /* end else */ - } /* end else */ - } /* end if */ - else { - /* Energy is below limit. - * Nobreak is probably in battery mode... */ - if (lastpktdata.s_battery_low) - dstate_setinfo("ups.status","%s","LB"); - else { - /* ...or network failure */ - dstate_setinfo("ups.status","%s","OB"); - } /* end else */ - } /* end else */ - } /* end else */ - } /* end else */ - - numbat = get_numbat(); - if (numbat == 0) - numbat = lastpkthwinfo.numbatteries; - else - upsdebugx(1,"Number of batteries is set to %d",numbat); - vbat = get_vbat(); - ah = get_ah(); - - /* Set all alarms possible */ - alarm[0] = '\0'; - if (lastpktdata.s_battery_mode) - snprintf(alarm, sizeof(alarm), "%s", "|UPS IN BATTERY MODE|"); - if (lastpktdata.s_battery_low) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|UPS IN BATTERY MODE|"); - if (lastpktdata.s_network_failure) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|NETWORK FAILURE|"); - if (lastpktdata.s_fast_network_failure) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|FAST NETWORK FAILURE|"); - if (lastpktdata.s_fast_network_failure) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|220v IN|"); - if (lastpktdata.s_fast_network_failure) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|220v OUT|"); - if (lastpktdata.s_bypass_on) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|BYPASS ON|"); - if (lastpktdata.s_charger_on) - snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", - "|CHARGER ON|"); - dstate_setinfo("ups.alarm","%s",alarm); - dstate_setinfo("ups.model","%s",ups.upsdesc); - dstate_setinfo("ups.mfr","%s",MANUFACTURER); - dstate_setinfo("ups.serial","%s",lastpkthwinfo.serial); - dstate_setinfo("ups.firmware","%u",lastpkthwinfo.softwareversion); - /* Setting hardware version here. - * Did not find another place to do this. - * Feel free to correct it. - * FIXME: move to upsdrv_initinfo() or so - */ - dstate_setinfo("ups.firmware.aux","%u",lastpkthwinfo.hardwareversion); - dstate_setinfo("ups.temperature","%0.2f",lastpktdata.tempmed_real); - dstate_setinfo("ups.load","%u",lastpktdata.potrms); - dstate_setinfo("ups.efficiency","%0.2f", calculate_efficiency(lastpktdata.vacoutrms, lastpktdata.vacinrms)); - va = get_va(lastpkthwinfo.model); - pf = get_pf(); - /* vpower is the power in Watts */ - vpower = ((va * pf) * (lastpktdata.potrms / 100.0)); - /* abat is the battery's consumption in Amperes */ - abat = ((vpower / lastpktdata.vdcmed_real) / numbat); - if (vpower > maxpower) - maxpower = vpower; - if (vpower < minpower) - minpower = vpower; - dstate_setinfo("ups.power","%0.2f",vpower); - dstate_setinfo("ups.power.nominal","%u",va); - dstate_setinfo("ups.realpower","%ld",lrint(round(vpower))); - dstate_setinfo("ups.realpower.nominal","%ld",lrint(round((double)va * (double)pf))); - dstate_setinfo("ups.beeper.status","%d",!lastpkthwinfo.c_buzzer_disable); - dstate_setinfo("input.voltage","%0.2f",lastpktdata.vacinrms); - dstate_setinfo("input.voltage.maximum","%0.2f",lastpktdata.vacinrmsmin); - dstate_setinfo("input.voltage.minimum","%0.2f",lastpktdata.vacinrmsmax); - vin_underv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V; - vin_overv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V; - perc = f_equal(get_vin_perc("vin_low_warn_perc"), get_vin_perc("vin_low_crit_perc")) ? 2 : 1; - vin_low_warn = vin_underv + (vin_underv * ((get_vin_perc("vin_low_warn_perc") * perc) / 100.0)); - dstate_setinfo("input.voltage.low.warning","%0.2f",calculated); - vin_low_crit = vin_underv + (vin_underv * (get_vin_perc("vin_low_crit_perc") / 100.0)); - dstate_setinfo("input.voltage.low.critical","%0.2f",calculated); - vin_high_warn = vin_overv + (vin_overv * ((get_vin_perc("vin_high_warn_perc") * perc) / 100.0)); - dstate_setinfo("input.voltage.high.warning","%0.2f",calculated); - vin_high_crit = vin_overv + (vin_overv * (get_vin_perc("vin_high_crit_perc") / 100.0)); - dstate_setinfo("input.voltage.high.critical","%0.2f",calculated); - vin = lastpkthwinfo.s_220V_in ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; - dstate_setinfo("input.voltage.nominal","%u",vin); - dstate_setinfo("input.transfer.low","%u",lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V); - dstate_setinfo("input.transfer.high","%u",lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V); - dstate_setinfo("output.voltage","%0.2f",lastpktdata.vacoutrms); - vout = lastpkthwinfo.s_220V_out ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; - dstate_setinfo("output.voltage.nominal","%u",vout); - dstate_setinfo("voltage","%0.2f",lastpktdata.vacoutrms); - dstate_setinfo("voltage.nominal","%u",vout); - dstate_setinfo("voltage.maximum","%0.2f",lastpktdata.vacinrmsmax); - dstate_setinfo("voltage.minimum","%0.2f",lastpktdata.vacinrmsmin); - dstate_setinfo("voltage.low.warning","%0.2f",vin_low_warn); - dstate_setinfo("voltage.low.critical","%0.2f",vin_low_crit); - dstate_setinfo("voltage.high.warning","%0.2f",vin_high_warn); - dstate_setinfo("voltage.high.critical","%0.2f",vin_high_crit); - dstate_setinfo("power","%0.2f",vpower); - dstate_setinfo("power.maximum","%0.2f",maxpower); - dstate_setinfo("power.minimum","%0.2f",minpower); - dstate_setinfo("power.percent","%u",lastpktdata.potrms); - if (lastpktdata.potrms > maxpowerperc) - maxpowerperc = lastpktdata.potrms; - if (lastpktdata.potrms < minpowerperc) - minpowerperc = lastpktdata.potrms; - dstate_setinfo("power.maximum.percent","%u",maxpowerperc); - dstate_setinfo("power.minimum.percent","%u",minpowerperc); - dstate_setinfo("realpower","%ld",lrint(round(vpower))); - dstate_setinfo("power","%ld",lrint(round(va * (lastpktdata.potrms / 100.0)))); - bcharge = lrint(round((lastpktdata.vdcmed_real * 100) / vbat)); - if (bcharge > 100) - bcharge = 100; - dstate_setinfo("battery.charge","%ld",bcharge); - dstate_setinfo("battery.voltage","%0.2f",lastpktdata.vdcmed_real); - dstate_setinfo("battery.voltage.nominal","%u",vbat); - dstate_setinfo("battery.capacity","%u",ah); - dstate_setinfo("battery.capacity.nominal","%0.2f",(float)ah * pf); - dstate_setinfo("battery.current","%0.2f",abat); - dstate_setinfo("battery.current.total","%0.2f",(float)abat * numbat); - dstate_setinfo("battery.temperature","%ld",lrint(round(lastpktdata.tempmed_real))); - dstate_setinfo("battery.packs","%u",numbat); - /* We will calculate autonomy in seconds - * autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; - * Maybe wrong, too. - * People say that the correct calculation is - * - * Battery Amp-Hour / (Power in Watts / battery voltage) - * - * Is that correct? I don't know. I'll use it for now. - */ - - /* That result is IN HOURS. We need to convert it to seconds */ - actual_current = vpower / vbat; /* Current consumption in A*/ - autonomy_secs = (ah / actual_current) * 3600; - - dstate_setinfo("battery.runtime","%u",autonomy_secs); - dstate_setinfo("battery.runtime.low","%u",30); - if (lastpktdata.s_charger_on) - dstate_setinfo("battery.charger.status","%s","CHARGING"); - else { - if (lastpktdata.s_battery_mode) - dstate_setinfo("battery.charger.status","%s","DISCHARGING"); - else - dstate_setinfo("battery.charger.status","%s","RESTING"); - } - /* Now, creating a structure called NHS, */ - dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); - dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); - dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); - dstate_setinfo("nhs.hw.model", "%u", lastpkthwinfo.model); - dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); - dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); - dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); - for (i = 0; i < 5; i++) { - /* Reusing variable */ - sprintf(alarm,"nhs.hw.configuration_array_p%d",i); - dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); - } - dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); - dstate_setinfo("nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); - dstate_setinfo("nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); - dstate_setinfo("nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); - dstate_setinfo("nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); - dstate_setinfo("nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); - dstate_setinfo("nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); - dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); - dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); - dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); - for (i = 0; i < 6; i++) { - /* Reusing variable */ - sprintf(alarm,"nhs.hw.status_p%d",i); - dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); - } - dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); - dstate_setinfo("nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); - dstate_setinfo("nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); - dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); - dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); - dstate_setinfo("nhs.hw.checksum_calc", "%u", lastpkthwinfo.checksum_calc); - dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); - dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); - dstate_setinfo("nhs.hw.month", "%u", lastpkthwinfo.month); - dstate_setinfo("nhs.hw.wday", "%u", lastpkthwinfo.wday); - dstate_setinfo("nhs.hw.hour", "%u", lastpkthwinfo.hour); - dstate_setinfo("nhs.hw.minute", "%u", lastpkthwinfo.minute); - dstate_setinfo("nhs.hw.second", "%u", lastpkthwinfo.second); - dstate_setinfo("nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); - dstate_setinfo("nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); - dstate_setinfo("nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); - dstate_setinfo("nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); - dstate_setinfo("nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); - dstate_setinfo("nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); - dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); - dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); - - /* Data packet */ - dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); - dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); - dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); - dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); - dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); - dstate_setinfo("nhs.data.vacinrms", "%0.2f", lastpktdata.vacinrms); - dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); - dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); - dstate_setinfo("nhs.data.vdcmed", "%0.2f", lastpktdata.vdcmed); - dstate_setinfo("nhs.data.vdcmed_real", "%0.2f", lastpktdata.vdcmed_real); - dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); - dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); - dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); - dstate_setinfo("nhs.data.vacinrmsmin", "%0.2f", lastpktdata.vacinrmsmin); - dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); - dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); - dstate_setinfo("nhs.data.vacinrmsmax", "%0.2f", lastpktdata.vacinrmsmax); - dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); - dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); - dstate_setinfo("nhs.data.vacoutrms", "%0.2f", lastpktdata.vacoutrms); - dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); - dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); - dstate_setinfo("nhs.data.tempmed", "%0.2f", lastpktdata.tempmed); - dstate_setinfo("nhs.data.tempmed_real", "%0.2f", lastpktdata.tempmed_real); - dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); - dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); - dstate_setinfo("nhs.data.battery_tension", "%0.2f", lastpktdata.battery_tension); - dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); - dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); - for (i = 0; i < 8; i++) { - /* Reusing variable */ - sprintf(alarm,"nhs.data.status_p%d",i); - dstate_setinfo(alarm, "%u", lastpktdata.status[i]); - } - dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); - dstate_setinfo("nhs.data.timeremain", "%0.2f", lastpktdata.timeremain); - dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); - dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); - dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); - dstate_setinfo("nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); - dstate_setinfo("nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); - dstate_setinfo("nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); - dstate_setinfo("nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); - dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); - dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); - dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.data.checksum_calc", "%u", lastpktdata.checksum_calc); - dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); - dstate_setinfo("nhs.param.va", "%u", va); - dstate_setinfo("nhs.param.pf", "%0.2f", pf); - dstate_setinfo("nhs.param.ah", "%u", ah); - dstate_setinfo("nhs.param.vin_low_warn_perc", "%0.2f", get_vin_perc("vin_low_warn_perc")); - dstate_setinfo("nhs.param.vin_low_crit_perc", "%0.2f", get_vin_perc("vin_low_crit_perc")); - dstate_setinfo("nhs.param.vin_high_warn_perc", "%0.2f", get_vin_perc("vin_high_warn_perc")); - dstate_setinfo("nhs.param.vin_high_crit_perc", "%0.2f", get_vin_perc("vin_high_crit_perc")); - - dstate_dataok(); - } /* end if */ - else - upsdebugx(1,"Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request..."); - } /* end else */ - } /* end if */ - } /* end if */ - } /* end if */ - } /* end if */ - - /* Now the nobreak read buffer is empty. - * We need a hw info packet to discover several variables, - * like number of batteries, to calculate some data - * FIXME: move (semi)static info discovery to upsdrv_initinfo() or so - */ - if (!lastpkthwinfo.checksum_ok) { - upsdebugx(1,"pkt_hwinfo loss -- Requesting"); - /* If size == 0, packet maybe not initizated, - * then send an initialization packet to obtain data. - * Send two times the extended initialization string, - * but, on fail, try randomly send extended or normal. - */ - if (send_extended < 6) { - upsdebugx(1,"Sending extended initialization packet. Try %d",send_extended+1); - bwritten = write_serial_int(serial_fd,string_initialization_long,9); - send_extended++; - } /* end if */ - else { - /* randomly send */ - if (rand() % 2 == 0) { - upsdebugx(1,"Sending long initialization packet"); - bwritten = write_serial_int(serial_fd,string_initialization_long,9); - } /* end if */ - else { - upsdebugx(1,"Sending short initialization packet"); - bwritten = write_serial_int(serial_fd,string_initialization_short,9); - } /* end else */ - } /* end else */ - if (bwritten < 0) { - upsdebugx(1,"Problem to write data to %s",porta); - if (bwritten == -1) { - upsdebugx(1,"Data problem"); - } - if (bwritten == -2) { - upsdebugx(1,"Flush problem"); - } - close(serial_fd); - serial_fd = -1; - } /* end if */ - else { - if (checktime > max_checktime) - checktime = max_checktime; - else { - upsdebugx(1,"Increase checktime to %d",checktime + 100000); - checktime = checktime + 100000; - } - usleep(checktime); - } /* end else */ - } /* end if */ - } /* end else */ - upsdebugx(1,"End updateinfo()"); + /* retries to open port */ + unsigned int retries = 3; + unsigned int i = 0; + char alarm[1024]; + unsigned int va = 0; + unsigned int ah = 0; + unsigned int vin_underv = 0; + unsigned int vin_overv = 0; + unsigned int perc = 0; + unsigned int vin = 0; + unsigned int vout = 0; + unsigned int autonomy_secs = 0; + float vin_low_warn = 0; + float vin_low_crit = 0; + float vin_high_warn = 0; + float vin_high_crit = 0; + float calculated = 0; + float vpower = 0; + float pf = 0; + long bcharge = 0; + int min_input_power = 0; + double tempodecorrido = 0.0; + unsigned int numbat = 0; + unsigned int vbat = 0; + float abat = 0; + float actual_current = 0; + upsinfo ups; + + upsdebugx(1, "Start updateinfo()"); + if ((serial_fd <= 0) && (i < retries)) { + upsdebugx(1, "Serial problem..."); + while (serial_fd <= 0) { + serial_fd = openfd(porta, baudrate); + upsdebugx(1, "Trying to reopen serial..."); + usleep(checktime); + retries++; + } + } + else { + /* Clean all read buffers to avoid errors: + * To clean OUTPUT buffer is TCOFLUSH. + * To both is TCIOFLUSH. + */ + /* //tcflush(serial_fd, TCIFLUSH); */ + chr = '\0'; + while (read(serial_fd, &chr, 1) > 0) { + if (chr == 0xFF) { /* DataPacket start */ + datapacketstart = true; + } /* end for */ + if (datapacketstart) { + datapacket[datapacket_index] = chr; + datapacket_index++; + if (chr == 0xFE) { /* DataPacket */ + time_t now = time(NULL); + upsdebugx(1, "DATAPACKET INDEX IS %d", datapacket_index); + if (lastdp != 0) { + tempodecorrido = difftime(now, lastdp); + } + lastdp = now; + /* If size is 18 or 50, may be an answer packet. + * Then check if doesn't have already a packet processed. + * We don't need to read all times these information. + * Can be a corrupted packet too. */ + if (((datapacket_index == 18) || (datapacket_index == 50)) && (!lastpkthwinfo.checksum_ok)) { + lastpkthwinfo = mount_hwinfo(datapacket, datapacket_index); + } /* end if */ + else { + if (datapacket_index == 21) + lastpktdata = mount_datapacket(datapacket, datapacket_index, tempodecorrido, lastpkthwinfo); + } /* end else */ + /* Clean datapacket structure to avoid problems */ + datapacket_index = 0; + memset(datapacket, 0, sizeof(datapacket)); + datapacketstart = false; + if (lastpktdata.checksum_ok) { + /* checksum is OK, then use it to set values */ + upsdebugx(1, "Data Packet seems be OK"); + if (lastpkthwinfo.size == 0) + upsdebugx(1, "Pkt HWINFO is not OK. See if will be requested next time!"); + else { + if (lastpkthwinfo.checksum_ok) { + upsdebugx(1, "Pkt HWINFO is OK. Model is %d, hwversion is %d and swversion is %d", lastpkthwinfo.model, lastpkthwinfo.hardwareversion, lastpkthwinfo.softwareversion); + /* We need to set data on NUT with data + * that I believe that I can calculate. + * Now setting data on NUT */ + ups = getupsinfo(lastpkthwinfo.model); + upsdebugx(1, "UPS Struct data: Code %d Model %s VA %d", ups.upscode, ups.upsdesc, ups.VA); + dstate_setinfo("device.model", "%s", ups.upsdesc); + dstate_setinfo("device.mfr", "%s", MANUFACTURER); + dstate_setinfo("device.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("device.type", "%s", "ups"); + + /* Setting UPS Status: + * OL -- On line (mains is present): Code below + * OB -- On battery (mains is not present) : Code below + * LB -- Low battery: Code below + * HB -- High battery: NHS doesn't have any variable with that information. Feel free to discover a way to set it + * RB -- The battery needs to be replaced: Well, as mentioned, we can write some infos on nobreak fw, on structures like pkt_hwinfo.year, pkt_hwinfo.month, etc. I never found any equipment with these values. + * CHRG -- The battery is charging: Code below + * DISCHRG -- The battery is discharging (inverter is providing load power): Code Below + * BYPASS -- UPS bypass circuit is active -- no battery protection is available: It's another PROBLEM, because NHS can work in bypass mode in some models, even if you have sealed batteries on it (without any external battery device). On the moment, i'll won't work with that. Feel free to discover how it work correctly. + * CAL -- UPS is currently performing runtime calibration (on battery) + * OFF -- UPS is offline and is not supplying power to the load + * OVER -- UPS is overloaded + * TRIM -- UPS is trimming incoming voltage (called "buck" in some hardware) + * BOOST -- UPS is boosting incoming voltage + * FSD -- Forced Shutdown (restricted use, see the note below) + */ + + /* Decision Chain commented below */ + + /* First we check if system is on battery or not */ + upsdebugx(1, "Set UPS status as OFF and start checking. s_battery_mode is %d", lastpktdata.s_battery_mode); + if (lastpkthwinfo.s_220V_in) { + upsdebugx(1, "I'm on 220v IN!. My overvoltage is %d", lastpkthwinfo.undervoltagein220V); + min_input_power = lastpkthwinfo.undervoltagein220V; + } + else { + upsdebugx(1, "I'm on 120v IN!. My overvoltage is %d", lastpkthwinfo.undervoltagein120V); + min_input_power = lastpkthwinfo.undervoltagein120V; + } + if (lastpktdata.s_battery_mode) { + /* ON BATTERY */ + upsdebugx(1, "UPS is on Battery Mode"); + dstate_setinfo("ups.status", "%s", "OB"); + if (lastpktdata.s_battery_low) { + /* If battery is LOW, warn user! */ + upsdebugx(1, "UPS is on Battery Mode and in Low Battery State"); + dstate_setinfo("ups.status", "%s", "LB"); + } /* end if */ + } /* end if */ + else { + /* Check if MAINS (power) is not preset. + * Well, we can check pkt_data.s_network_failure too... */ + if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { + upsdebugx(1, "UPS has power-in value %0.2f " + "and min_input_power is %d, " + "or network is in failure. Network failure is %d", + lastpktdata.vacinrms, + min_input_power, + lastpktdata.s_network_failure); + dstate_setinfo("ups.status", "%s", "DISCHRG"); + } /* end if */ + else { + /* MAINS is present. We need to check some situations. + * NHS only charge if have more than min_input_power. + * If MAINS is less than or equal to min_input_power, + * then the UPS goes to BATTERY */ + if (lastpktdata.vacinrms > min_input_power) { + upsdebugx(1, "UPS is on MAINS"); + if (lastpktdata.s_charger_on) { + upsdebugx(1, "UPS Charging..."); + dstate_setinfo("ups.status", "%s", "CHRG"); + } + else { + if ((lastpktdata.s_network_failure) || (lastpktdata.s_fast_network_failure)) { + upsdebugx(1, "UPS is on battery mode because network failure or fast network failure"); + dstate_setinfo("ups.status", "%s", "OB"); + } /* end if */ + else { + upsdebugx(1, "All is OK. UPS is on ONLINE!"); + dstate_setinfo("ups.status", "%s", "OL"); + } /* end else */ + } /* end else */ + } /* end if */ + else { + /* Energy is below limit. + * Nobreak is probably in battery mode... */ + if (lastpktdata.s_battery_low) + dstate_setinfo("ups.status", "%s", "LB"); + else { + /* ...or network failure */ + dstate_setinfo("ups.status", "%s", "OB"); + } /* end else */ + } /* end else */ + } /* end else */ + } /* end else */ + + numbat = get_numbat(); + if (numbat == 0) + numbat = lastpkthwinfo.numbatteries; + else + upsdebugx(1, "Number of batteries is set to %d", numbat); + vbat = get_vbat(); + ah = get_ah(); + + /* Set all alarms possible */ + alarm[0] = '\0'; + if (lastpktdata.s_battery_mode) + snprintf(alarm, sizeof(alarm), "%s", "|UPS IN BATTERY MODE|"); + if (lastpktdata.s_battery_low) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|UPS IN BATTERY MODE|"); + if (lastpktdata.s_network_failure) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|NETWORK FAILURE|"); + if (lastpktdata.s_fast_network_failure) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|FAST NETWORK FAILURE|"); + if (lastpktdata.s_fast_network_failure) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|220v IN|"); + if (lastpktdata.s_fast_network_failure) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|220v OUT|"); + if (lastpktdata.s_bypass_on) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|BYPASS ON|"); + if (lastpktdata.s_charger_on) + snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", + "|CHARGER ON|"); + dstate_setinfo("ups.alarm", "%s", alarm); + dstate_setinfo("ups.model", "%s", ups.upsdesc); + dstate_setinfo("ups.mfr", "%s", MANUFACTURER); + dstate_setinfo("ups.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("ups.firmware", "%u", lastpkthwinfo.softwareversion); + /* Setting hardware version here. + * Did not find another place to do this. + * Feel free to correct it. + * FIXME: move to upsdrv_initinfo() or so + */ + dstate_setinfo("ups.firmware.aux", "%u", lastpkthwinfo.hardwareversion); + dstate_setinfo("ups.temperature", "%0.2f", lastpktdata.tempmed_real); + dstate_setinfo("ups.load", "%u", lastpktdata.potrms); + dstate_setinfo("ups.efficiency", "%0.2f", calculate_efficiency(lastpktdata.vacoutrms, lastpktdata.vacinrms)); + va = get_va(lastpkthwinfo.model); + pf = get_pf(); + /* vpower is the power in Watts */ + vpower = ((va * pf) * (lastpktdata.potrms / 100.0)); + /* abat is the battery's consumption in Amperes */ + abat = ((vpower / lastpktdata.vdcmed_real) / numbat); + if (vpower > maxpower) + maxpower = vpower; + if (vpower < minpower) + minpower = vpower; + dstate_setinfo("ups.power", "%0.2f", vpower); + dstate_setinfo("ups.power.nominal", "%u", va); + dstate_setinfo("ups.realpower", "%ld", lrint(round(vpower))); + dstate_setinfo("ups.realpower.nominal", "%ld", lrint(round((double)va * (double)pf))); + dstate_setinfo("ups.beeper.status", "%d", !lastpkthwinfo.c_buzzer_disable); + dstate_setinfo("input.voltage", "%0.2f", lastpktdata.vacinrms); + dstate_setinfo("input.voltage.maximum", "%0.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("input.voltage.minimum", "%0.2f", lastpktdata.vacinrmsmax); + vin_underv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V; + vin_overv = lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V; + perc = f_equal(get_vin_perc("vin_low_warn_perc"), get_vin_perc("vin_low_crit_perc")) ? 2 : 1; + vin_low_warn = vin_underv + (vin_underv * ((get_vin_perc("vin_low_warn_perc") * perc) / 100.0)); + dstate_setinfo("input.voltage.low.warning", "%0.2f", calculated); + vin_low_crit = vin_underv + (vin_underv * (get_vin_perc("vin_low_crit_perc") / 100.0)); + dstate_setinfo("input.voltage.low.critical", "%0.2f", calculated); + vin_high_warn = vin_overv + (vin_overv * ((get_vin_perc("vin_high_warn_perc") * perc) / 100.0)); + dstate_setinfo("input.voltage.high.warning", "%0.2f", calculated); + vin_high_crit = vin_overv + (vin_overv * (get_vin_perc("vin_high_crit_perc") / 100.0)); + dstate_setinfo("input.voltage.high.critical", "%0.2f", calculated); + vin = lastpkthwinfo.s_220V_in ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; + dstate_setinfo("input.voltage.nominal", "%u", vin); + dstate_setinfo("input.transfer.low", "%u", lastpkthwinfo.s_220V_in ? lastpkthwinfo.undervoltagein220V : lastpkthwinfo.undervoltagein120V); + dstate_setinfo("input.transfer.high", "%u", lastpkthwinfo.s_220V_in ? lastpkthwinfo.overvoltagein220V : lastpkthwinfo.overvoltagein120V); + dstate_setinfo("output.voltage", "%0.2f", lastpktdata.vacoutrms); + vout = lastpkthwinfo.s_220V_out ? lastpkthwinfo.tensionout220V : lastpkthwinfo.tensionout120V; + dstate_setinfo("output.voltage.nominal", "%u", vout); + dstate_setinfo("voltage", "%0.2f", lastpktdata.vacoutrms); + dstate_setinfo("voltage.nominal", "%u", vout); + dstate_setinfo("voltage.maximum", "%0.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("voltage.minimum", "%0.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("voltage.low.warning", "%0.2f", vin_low_warn); + dstate_setinfo("voltage.low.critical", "%0.2f", vin_low_crit); + dstate_setinfo("voltage.high.warning", "%0.2f", vin_high_warn); + dstate_setinfo("voltage.high.critical", "%0.2f", vin_high_crit); + dstate_setinfo("power", "%0.2f", vpower); + dstate_setinfo("power.maximum", "%0.2f", maxpower); + dstate_setinfo("power.minimum", "%0.2f", minpower); + dstate_setinfo("power.percent", "%u", lastpktdata.potrms); + if (lastpktdata.potrms > maxpowerperc) + maxpowerperc = lastpktdata.potrms; + if (lastpktdata.potrms < minpowerperc) + minpowerperc = lastpktdata.potrms; + dstate_setinfo("power.maximum.percent", "%u", maxpowerperc); + dstate_setinfo("power.minimum.percent", "%u", minpowerperc); + dstate_setinfo("realpower", "%ld", lrint(round(vpower))); + dstate_setinfo("power", "%ld", lrint(round(va * (lastpktdata.potrms / 100.0)))); + bcharge = lrint(round((lastpktdata.vdcmed_real * 100) / vbat)); + if (bcharge > 100) + bcharge = 100; + dstate_setinfo("battery.charge", "%ld", bcharge); + dstate_setinfo("battery.voltage", "%0.2f", lastpktdata.vdcmed_real); + dstate_setinfo("battery.voltage.nominal", "%u", vbat); + dstate_setinfo("battery.capacity", "%u", ah); + dstate_setinfo("battery.capacity.nominal", "%0.2f", (float)ah * pf); + dstate_setinfo("battery.current", "%0.2f", abat); + dstate_setinfo("battery.current.total", "%0.2f", (float)abat * numbat); + dstate_setinfo("battery.temperature", "%ld", lrint(round(lastpktdata.tempmed_real))); + dstate_setinfo("battery.packs", "%u", numbat); + /* We will calculate autonomy in seconds + * autonomy_secs = (ah / lastpktdata.vdcmed_real) * 3600; + * Maybe wrong, too. + * People say that the correct calculation is + * + * Battery Amp-Hour / (Power in Watts / battery voltage) + * + * Is that correct? I don't know. I'll use it for now. + */ + + /* That result is IN HOURS. We need to convert it to seconds */ + actual_current = vpower / vbat; /* Current consumption in A*/ + autonomy_secs = (ah / actual_current) * 3600; + + dstate_setinfo("battery.runtime", "%u", autonomy_secs); + dstate_setinfo("battery.runtime.low", "%u", 30); + if (lastpktdata.s_charger_on) + dstate_setinfo("battery.charger.status", "%s", "CHARGING"); + else { + if (lastpktdata.s_battery_mode) + dstate_setinfo("battery.charger.status", "%s", "DISCHARGING"); + else + dstate_setinfo("battery.charger.status", "%s", "RESTING"); + } + /* Now, creating a structure called NHS, */ + dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); + dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); + dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); + dstate_setinfo("nhs.hw.model", "%u", lastpkthwinfo.model); + dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); + dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); + dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); + for (i = 0; i < 5; i++) { + /* Reusing variable */ + sprintf(alarm, "nhs.hw.configuration_array_p%d", i); + dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); + } + dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); + dstate_setinfo("nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); + dstate_setinfo("nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); + dstate_setinfo("nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); + dstate_setinfo("nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); + dstate_setinfo("nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); + dstate_setinfo("nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); + dstate_setinfo("nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); + dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); + dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); + dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); + for (i = 0; i < 6; i++) { + /* Reusing variable */ + sprintf(alarm, "nhs.hw.status_p%d", i); + dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); + } + dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); + dstate_setinfo("nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); + dstate_setinfo("nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); + dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); + dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); + dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); + dstate_setinfo("nhs.hw.checksum_calc", "%u", lastpkthwinfo.checksum_calc); + dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); + dstate_setinfo("nhs.hw.month", "%u", lastpkthwinfo.month); + dstate_setinfo("nhs.hw.wday", "%u", lastpkthwinfo.wday); + dstate_setinfo("nhs.hw.hour", "%u", lastpkthwinfo.hour); + dstate_setinfo("nhs.hw.minute", "%u", lastpkthwinfo.minute); + dstate_setinfo("nhs.hw.second", "%u", lastpkthwinfo.second); + dstate_setinfo("nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); + dstate_setinfo("nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); + dstate_setinfo("nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); + dstate_setinfo("nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); + dstate_setinfo("nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); + dstate_setinfo("nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); + dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); + dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); + + /* Data packet */ + dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); + dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); + dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); + dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); + dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); + dstate_setinfo("nhs.data.vacinrms", "%0.2f", lastpktdata.vacinrms); + dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); + dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); + dstate_setinfo("nhs.data.vdcmed", "%0.2f", lastpktdata.vdcmed); + dstate_setinfo("nhs.data.vdcmed_real", "%0.2f", lastpktdata.vdcmed_real); + dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); + dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); + dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); + dstate_setinfo("nhs.data.vacinrmsmin", "%0.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); + dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); + dstate_setinfo("nhs.data.vacinrmsmax", "%0.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); + dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); + dstate_setinfo("nhs.data.vacoutrms", "%0.2f", lastpktdata.vacoutrms); + dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); + dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); + dstate_setinfo("nhs.data.tempmed", "%0.2f", lastpktdata.tempmed); + dstate_setinfo("nhs.data.tempmed_real", "%0.2f", lastpktdata.tempmed_real); + dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); + dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); + dstate_setinfo("nhs.data.battery_tension", "%0.2f", lastpktdata.battery_tension); + dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); + dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); + for (i = 0; i < 8; i++) { + /* Reusing variable */ + sprintf(alarm, "nhs.data.status_p%d", i); + dstate_setinfo(alarm, "%u", lastpktdata.status[i]); + } + dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); + dstate_setinfo("nhs.data.timeremain", "%0.2f", lastpktdata.timeremain); + dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); + dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); + dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); + dstate_setinfo("nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); + dstate_setinfo("nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); + dstate_setinfo("nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); + dstate_setinfo("nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); + dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); + dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); + dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); + dstate_setinfo("nhs.data.checksum_calc", "%u", lastpktdata.checksum_calc); + dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); + dstate_setinfo("nhs.param.va", "%u", va); + dstate_setinfo("nhs.param.pf", "%0.2f", pf); + dstate_setinfo("nhs.param.ah", "%u", ah); + dstate_setinfo("nhs.param.vin_low_warn_perc", "%0.2f", get_vin_perc("vin_low_warn_perc")); + dstate_setinfo("nhs.param.vin_low_crit_perc", "%0.2f", get_vin_perc("vin_low_crit_perc")); + dstate_setinfo("nhs.param.vin_high_warn_perc", "%0.2f", get_vin_perc("vin_high_warn_perc")); + dstate_setinfo("nhs.param.vin_high_crit_perc", "%0.2f", get_vin_perc("vin_high_crit_perc")); + + dstate_dataok(); + } /* end if */ + else + upsdebugx(1, "Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request..."); + } /* end else */ + } /* end if */ + } /* end if */ + } /* end if */ + } /* end if */ + + /* Now the nobreak read buffer is empty. + * We need a hw info packet to discover several variables, + * like number of batteries, to calculate some data + * FIXME: move (semi)static info discovery to upsdrv_initinfo() or so + */ + if (!lastpkthwinfo.checksum_ok) { + upsdebugx(1, "pkt_hwinfo loss -- Requesting"); + /* If size == 0, packet maybe not initizated, + * then send an initialization packet to obtain data. + * Send two times the extended initialization string, + * but, on fail, try randomly send extended or normal. + */ + if (send_extended < 6) { + upsdebugx(1, "Sending extended initialization packet. Try %d", send_extended+1); + bwritten = write_serial_int(serial_fd, string_initialization_long, 9); + send_extended++; + } /* end if */ + else { + /* randomly send */ + if (rand() % 2 == 0) { + upsdebugx(1, "Sending long initialization packet"); + bwritten = write_serial_int(serial_fd, string_initialization_long, 9); + } /* end if */ + else { + upsdebugx(1, "Sending short initialization packet"); + bwritten = write_serial_int(serial_fd, string_initialization_short, 9); + } /* end else */ + } /* end else */ + if (bwritten < 0) { + upsdebugx(1, "Problem to write data to %s", porta); + if (bwritten == -1) { + upsdebugx(1, "Data problem"); + } + if (bwritten == -2) { + upsdebugx(1, "Flush problem"); + } + close(serial_fd); + serial_fd = -1; + } /* end if */ + else { + if (checktime > max_checktime) + checktime = max_checktime; + else { + upsdebugx(1, "Increase checktime to %d", checktime + 100000); + checktime = checktime + 100000; + } + usleep(checktime); + } /* end else */ + } /* end if */ + } /* end else */ + upsdebugx(1, "End updateinfo()"); } void upsdrv_shutdown(void) { - upsdebugx(1,"Start shutdown()"); + upsdebugx(1, "Start shutdown()"); - /* replace with a proper shutdown function */ - upslogx(LOG_ERR, "shutdown not supported"); - set_exit_flag(-1); + /* replace with a proper shutdown function */ + upslogx(LOG_ERR, "shutdown not supported"); + set_exit_flag(-1); - upsdebugx(1,"Driver shutdown"); + upsdebugx(1, "Driver shutdown"); } void upsdrv_cleanup(void) { - upsdebugx(1,"Start cleanup()"); - if (serial_fd != -1) { - close(serial_fd); - serial_fd = -1; - } - upsdebugx(1,"End cleanup()"); + upsdebugx(1, "Start cleanup()"); + + if (serial_fd != -1) { + close(serial_fd); + serial_fd = -1; + } + + upsdebugx(1, "End cleanup()"); } void upsdrv_initups(void) { - upsdebugx(1,"Start initups()"); - - /* Process optional configuration flags */ - if (getval("debug_pkt_raw")) - debug_pkt_raw = 1; - if (getval("debug_pkt_data")) - debug_pkt_data = 1; - if (getval("debug_pkt_hwinfo")) - debug_pkt_hwinfo = 1; - - upsdrv_initinfo(); - upsdebugx(1,"End initups()"); + upsdebugx(1, "Start initups()"); + + /* Process optional configuration flags */ + if (getval("debug_pkt_raw")) + debug_pkt_raw = 1; + if (getval("debug_pkt_data")) + debug_pkt_data = 1; + if (getval("debug_pkt_hwinfo")) + debug_pkt_hwinfo = 1; + + upsdrv_initinfo(); + upsdebugx(1, "End initups()"); } void upsdrv_makevartable(void) { - char help[4096]; + char help[4096]; - /* Standard variable in main.c */ - /* //addvar(VAR_VALUE, "port", "Port to communication"); */ + /* Standard variable in main.c */ + /* //addvar(VAR_VALUE, "port", "Port to communication"); */ - addvar(VAR_VALUE, "baud", "Baud Rate from port"); + addvar(VAR_VALUE, "baud", "Baud Rate from port"); - addvar(VAR_VALUE, "ah", "Battery discharge capacity in Ampere/hour"); + addvar(VAR_VALUE, "ah", "Battery discharge capacity in Ampere/hour"); - addvar(VAR_VALUE, "va", "Nobreak NOMINAL POWER in VA"); + addvar(VAR_VALUE, "va", "Nobreak NOMINAL POWER in VA"); - snprintf(help, sizeof(help), "Power Factor to use in calculations of battery time. Default is %0.2f", DEFAULTPF); - addvar(VAR_VALUE, "pf", help); + snprintf(help, sizeof(help), "Power Factor to use in calculations of battery time. Default is %0.2f", DEFAULTPF); + addvar(VAR_VALUE, "pf", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning low level. Default is %0.2f", DEFAULTPERC); - addvar(VAR_VALUE, "vin_low_warn_perc", help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning low level. Default is %0.2f", DEFAULTPERC); + addvar(VAR_VALUE, "vin_low_warn_perc", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical low level. Default is %0.2f", DEFAULTPERC); - addvar(VAR_VALUE, "vin_low_crit_perc", help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical low level. Default is %0.2f", DEFAULTPERC); + addvar(VAR_VALUE, "vin_low_crit_perc", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning high level. Default is %0.2f", DEFAULTPERC); - addvar(VAR_VALUE, "vin_high_warn_perc", help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate warning high level. Default is %0.2f", DEFAULTPERC); + addvar(VAR_VALUE, "vin_high_warn_perc", help); - snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical high level. Default is %0.2f", DEFAULTPERC); - addvar(VAR_VALUE, "vin_high_crit_perc", help); + snprintf(help, sizeof(help), "Voltage In Percentage to calculate critical high level. Default is %0.2f", DEFAULTPERC); + addvar(VAR_VALUE, "vin_high_crit_perc", help); - snprintf(help, sizeof(help), "Num Batteries (override value from nobreak)"); - addvar(VAR_VALUE, "numbatteries", help); + snprintf(help, sizeof(help), "Num Batteries (override value from nobreak)"); + addvar(VAR_VALUE, "numbatteries", help); - snprintf(help, sizeof(help), "Battery Voltage (override default value). Default is %0.2f", DEFAULTBATV); - addvar(VAR_VALUE, "vbat", help); + snprintf(help, sizeof(help), "Battery Voltage (override default value). Default is %0.2f", DEFAULTBATV); + addvar(VAR_VALUE, "vbat", help); - addvar(VAR_FLAG, "debug_pkt_raw", "Enable debug logging of packet bytes"); - addvar(VAR_FLAG, "debug_pkt_data", "Enable debug logging of data packet decoding"); - addvar(VAR_FLAG, "debug_pkt_hwinfo", "Enable debug logging of hwinfo packet decoding"); + addvar(VAR_FLAG, "debug_pkt_raw", "Enable debug logging of packet bytes"); + addvar(VAR_FLAG, "debug_pkt_data", "Enable debug logging of data packet decoding"); + addvar(VAR_FLAG, "debug_pkt_hwinfo", "Enable debug logging of hwinfo packet decoding"); } void upsdrv_help(void) { From 833ac4e4a463a77db1560d8725b041cc8a588099 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:30:28 +0000 Subject: [PATCH 49/60] drivers/nhs_ser.c: memory robustness: sprintf=>snprintf [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index a48f51769a..803c3db5a8 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -626,7 +626,7 @@ static void pdatapacket(unsigned char * datapkt, int size) { static float createfloat(int integer, int decimal) { char flt[1024]; - sprintf(flt, "%d.%d", integer, decimal); + snprintf(flt, sizeof(flt), "%d.%d", integer, decimal); return atof(flt); } @@ -2010,7 +2010,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); for (i = 0; i < 5; i++) { /* Reusing variable */ - sprintf(alarm, "nhs.hw.configuration_array_p%d", i); + snprintf(alarm, sizeof(alarm), "nhs.hw.configuration_array_p%d", i); dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); } dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); @@ -2028,7 +2028,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); for (i = 0; i < 6; i++) { /* Reusing variable */ - sprintf(alarm, "nhs.hw.status_p%d", i); + snprintf(alarm, sizeof(alarm), "nhs.hw.status_p%d", i); dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); } dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); @@ -2089,7 +2089,7 @@ void upsdrv_updateinfo(void) { dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); for (i = 0; i < 8; i++) { /* Reusing variable */ - sprintf(alarm, "nhs.data.status_p%d", i); + snprintf(alarm, sizeof(alarm), "nhs.data.status_p%d", i); dstate_setinfo(alarm, "%u", lastpktdata.status[i]); } dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); From cb46e9bb7a37a8d6990f091cc40643ce2853da45 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:33:20 +0000 Subject: [PATCH 50/60] drivers/nhs_ser.c: memory robustness: strcpy=>strncpy [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 218 +++++++++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 109 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 803c3db5a8..8cccb64db6 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -950,655 +950,655 @@ static upsinfo getupsinfo(unsigned int upscode) { switch (upscode) { case 1: data.upscode = 1; - strcpy(data.upsdesc, "NHS COMPACT PLUS"); + strncpy(data.upsdesc, "NHS COMPACT PLUS", sizeof(data.upsdesc)); data.VA = 1000; break; case 2: data.upscode = 2; - strcpy(data.upsdesc, "NHS COMPACT PLUS SENOIDAL"); + strncpy(data.upsdesc, "NHS COMPACT PLUS SENOIDAL", sizeof(data.upsdesc)); data.VA = 1000; break; case 3: data.upscode = 3; - strcpy(data.upsdesc, "NHS COMPACT PLUS RACK"); + strncpy(data.upsdesc, "NHS COMPACT PLUS RACK", sizeof(data.upsdesc)); data.VA = 1000; break; case 4: data.upscode = 4; - strcpy(data.upsdesc, "NHS PREMIUM PDV"); + strncpy(data.upsdesc, "NHS PREMIUM PDV", sizeof(data.upsdesc)); data.VA = 1500; break; case 5: data.upscode = 5; - strcpy(data.upsdesc, "NHS PREMIUM PDV SENOIDAL"); + strncpy(data.upsdesc, "NHS PREMIUM PDV SENOIDAL", sizeof(data.upsdesc)); data.VA = 1500; break; case 6: data.upscode = 6; - strcpy(data.upsdesc, "NHS PREMIUM 1500VA"); + strncpy(data.upsdesc, "NHS PREMIUM 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 7: data.upscode = 7; - strcpy(data.upsdesc, "NHS PREMIUM 2200VA"); + strncpy(data.upsdesc, "NHS PREMIUM 2200VA", sizeof(data.upsdesc)); data.VA = 2200; break; case 8: data.upscode = 8; - strcpy(data.upsdesc, "NHS PREMIUM SENOIDAL"); + strncpy(data.upsdesc, "NHS PREMIUM SENOIDAL", sizeof(data.upsdesc)); data.VA = 1500; break; case 9: data.upscode = 9; - strcpy(data.upsdesc, "NHS LASER 2600VA"); + strncpy(data.upsdesc, "NHS LASER 2600VA", sizeof(data.upsdesc)); data.VA = 2600; break; case 10: data.upscode = 10; - strcpy(data.upsdesc, "NHS LASER 3300VA"); + strncpy(data.upsdesc, "NHS LASER 3300VA", sizeof(data.upsdesc)); data.VA = 3300; break; case 11: data.upscode = 11; - strcpy(data.upsdesc, "NHS LASER 2600VA ISOLADOR"); + strncpy(data.upsdesc, "NHS LASER 2600VA ISOLADOR", sizeof(data.upsdesc)); data.VA = 2600; break; case 12: data.upscode = 12; - strcpy(data.upsdesc, "NHS LASER SENOIDAL"); + strncpy(data.upsdesc, "NHS LASER SENOIDAL", sizeof(data.upsdesc)); data.VA = 2600; break; case 13: data.upscode = 13; - strcpy(data.upsdesc, "NHS LASER ON-LINE"); + strncpy(data.upsdesc, "NHS LASER ON-LINE", sizeof(data.upsdesc)); data.VA = 2600; break; case 15: data.upscode = 15; - strcpy(data.upsdesc, "NHS COMPACT PLUS 2003"); + strncpy(data.upsdesc, "NHS COMPACT PLUS 2003", sizeof(data.upsdesc)); data.VA = 1000; break; case 16: data.upscode = 16; - strcpy(data.upsdesc, "COMPACT PLUS SENOIDAL 2003"); + strncpy(data.upsdesc, "COMPACT PLUS SENOIDAL 2003", sizeof(data.upsdesc)); data.VA = 1000; break; case 17: data.upscode = 17; - strcpy(data.upsdesc, "COMPACT PLUS RACK 2003"); + strncpy(data.upsdesc, "COMPACT PLUS RACK 2003", sizeof(data.upsdesc)); data.VA = 1000; break; case 18: data.upscode = 18; - strcpy(data.upsdesc, "PREMIUM PDV 2003"); + strncpy(data.upsdesc, "PREMIUM PDV 2003", sizeof(data.upsdesc)); data.VA = 1500; break; case 19: data.upscode = 19; - strcpy(data.upsdesc, "PREMIUM PDV SENOIDAL 2003"); + strncpy(data.upsdesc, "PREMIUM PDV SENOIDAL 2003", sizeof(data.upsdesc)); data.VA = 1500; break; case 20: data.upscode = 20; - strcpy(data.upsdesc, "PREMIUM 1500VA 2003"); + strncpy(data.upsdesc, "PREMIUM 1500VA 2003", sizeof(data.upsdesc)); data.VA = 1500; break; case 21: data.upscode = 21; - strcpy(data.upsdesc, "PREMIUM 2200VA 2003"); + strncpy(data.upsdesc, "PREMIUM 2200VA 2003", sizeof(data.upsdesc)); data.VA = 2200; break; case 22: data.upscode = 22; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 2003"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 2003", sizeof(data.upsdesc)); data.VA = 1500; break; case 23: data.upscode = 23; - strcpy(data.upsdesc, "LASER 2600VA 2003"); + strncpy(data.upsdesc, "LASER 2600VA 2003", sizeof(data.upsdesc)); data.VA = 2600; break; case 24: data.upscode = 24; - strcpy(data.upsdesc, "LASER 3300VA 2003"); + strncpy(data.upsdesc, "LASER 3300VA 2003", sizeof(data.upsdesc)); data.VA = 3300; break; case 25: data.upscode = 25; - strcpy(data.upsdesc, "LASER 2600VA ISOLADOR 2003"); + strncpy(data.upsdesc, "LASER 2600VA ISOLADOR 2003", sizeof(data.upsdesc)); data.VA = 2600; break; case 26: data.upscode = 26; - strcpy(data.upsdesc, "LASER SENOIDAL 2003"); + strncpy(data.upsdesc, "LASER SENOIDAL 2003", sizeof(data.upsdesc)); data.VA = 2600; break; case 27: data.upscode = 27; - strcpy(data.upsdesc, "PDV ONLINE 2003"); + strncpy(data.upsdesc, "PDV ONLINE 2003", sizeof(data.upsdesc)); data.VA = 1500; break; case 28: data.upscode = 28; - strcpy(data.upsdesc, "LASER ONLINE 2003"); + strncpy(data.upsdesc, "LASER ONLINE 2003", sizeof(data.upsdesc)); data.VA = 3300; break; case 29: data.upscode = 29; - strcpy(data.upsdesc, "EXPERT ONLINE 2003"); + strncpy(data.upsdesc, "EXPERT ONLINE 2003", sizeof(data.upsdesc)); data.VA = 5000; break; case 30: data.upscode = 30; - strcpy(data.upsdesc, "MINI 2"); + strncpy(data.upsdesc, "MINI 2", sizeof(data.upsdesc)); data.VA = 500; break; case 31: data.upscode = 31; - strcpy(data.upsdesc, "COMPACT PLUS 2"); + strncpy(data.upsdesc, "COMPACT PLUS 2", sizeof(data.upsdesc)); data.VA = 1000; break; case 32: data.upscode = 32; - strcpy(data.upsdesc, "LASER ON-LINE"); + strncpy(data.upsdesc, "LASER ON-LINE", sizeof(data.upsdesc)); data.VA = 2600; break; case 33: data.upscode = 33; - strcpy(data.upsdesc, "PDV SENOIDAL 1500VA"); + strncpy(data.upsdesc, "PDV SENOIDAL 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 34: data.upscode = 34; - strcpy(data.upsdesc, "PDV SENOIDAL 1000VA"); + strncpy(data.upsdesc, "PDV SENOIDAL 1000VA", sizeof(data.upsdesc)); data.VA = 1000; break; case 36: data.upscode = 36; - strcpy(data.upsdesc, "LASER ONLINE 3750VA"); + strncpy(data.upsdesc, "LASER ONLINE 3750VA", sizeof(data.upsdesc)); data.VA = 3750; break; case 37: data.upscode = 37; - strcpy(data.upsdesc, "LASER ONLINE 5000VA"); + strncpy(data.upsdesc, "LASER ONLINE 5000VA", sizeof(data.upsdesc)); data.VA = 5000; break; case 38: data.upscode = 38; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 2000VA"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 2000VA", sizeof(data.upsdesc)); data.VA = 2000; break; case 39: data.upscode = 39; - strcpy(data.upsdesc, "LASER SENOIDAL 3500VA"); + strncpy(data.upsdesc, "LASER SENOIDAL 3500VA", sizeof(data.upsdesc)); data.VA = 3500; break; case 40: data.upscode = 40; - strcpy(data.upsdesc, "PREMIUM PDV 1200VA"); + strncpy(data.upsdesc, "PREMIUM PDV 1200VA", sizeof(data.upsdesc)); data.VA = 1200; break; case 41: data.upscode = 41; - strcpy(data.upsdesc, "PREMIUM 1500VA"); + strncpy(data.upsdesc, "PREMIUM 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 42: data.upscode = 42; - strcpy(data.upsdesc, "PREMIUM 2200VA"); + strncpy(data.upsdesc, "PREMIUM 2200VA", sizeof(data.upsdesc)); data.VA = 2200; break; case 43: data.upscode = 43; - strcpy(data.upsdesc, "LASER 2600VA"); + strncpy(data.upsdesc, "LASER 2600VA", sizeof(data.upsdesc)); data.VA = 2600; break; case 44: data.upscode = 44; - strcpy(data.upsdesc, "LASER 3300VA"); + strncpy(data.upsdesc, "LASER 3300VA", sizeof(data.upsdesc)); data.VA = 3300; break; case 45: data.upscode = 45; - strcpy(data.upsdesc, "COMPACT PLUS SENOIDAL 700VA"); + strncpy(data.upsdesc, "COMPACT PLUS SENOIDAL 700VA", sizeof(data.upsdesc)); data.VA = 700; break; case 46: data.upscode = 46; - strcpy(data.upsdesc, "PREMIUM ONLINE 2000VA"); + strncpy(data.upsdesc, "PREMIUM ONLINE 2000VA", sizeof(data.upsdesc)); data.VA = 2000; break; case 47: data.upscode = 47; - strcpy(data.upsdesc, "EXPERT ONLINE 10000VA"); + strncpy(data.upsdesc, "EXPERT ONLINE 10000VA", sizeof(data.upsdesc)); data.VA = 10000; break; case 48: data.upscode = 48; - strcpy(data.upsdesc, "LASER SENOIDAL 4200VA"); + strncpy(data.upsdesc, "LASER SENOIDAL 4200VA", sizeof(data.upsdesc)); data.VA = 4200; break; case 49: data.upscode = 49; - strcpy(data.upsdesc, "NHS COMPACT PLUS EXTENDIDO 1500VA"); + strncpy(data.upsdesc, "NHS COMPACT PLUS EXTENDIDO 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 50: data.upscode = 50; - strcpy(data.upsdesc, "LASER ONLINE 6000VA"); + strncpy(data.upsdesc, "LASER ONLINE 6000VA", sizeof(data.upsdesc)); data.VA = 6000; break; case 51: data.upscode = 51; - strcpy(data.upsdesc, "LASER EXT 3300VA"); + strncpy(data.upsdesc, "LASER EXT 3300VA", sizeof(data.upsdesc)); data.VA = 3300; break; case 52: data.upscode = 52; - strcpy(data.upsdesc, "NHS COMPACT PLUS 1200VA"); + strncpy(data.upsdesc, "NHS COMPACT PLUS 1200VA", sizeof(data.upsdesc)); data.VA = 1200; break; case 53: data.upscode = 53; - strcpy(data.upsdesc, "LASER SENOIDAL 3000VA GII"); + strncpy(data.upsdesc, "LASER SENOIDAL 3000VA GII", sizeof(data.upsdesc)); data.VA = 3000; break; case 54: data.upscode = 54; - strcpy(data.upsdesc, "LASER SENOIDAL 3500VA GII"); + strncpy(data.upsdesc, "LASER SENOIDAL 3500VA GII", sizeof(data.upsdesc)); data.VA = 3500; break; case 55: data.upscode = 55; - strcpy(data.upsdesc, "LASER SENOIDAL 4200VA GII"); + strncpy(data.upsdesc, "LASER SENOIDAL 4200VA GII", sizeof(data.upsdesc)); data.VA = 4200; break; case 56: data.upscode = 56; - strcpy(data.upsdesc, "LASER ONLINE 3000VA"); + strncpy(data.upsdesc, "LASER ONLINE 3000VA", sizeof(data.upsdesc)); data.VA = 3000; break; case 57: data.upscode = 57; - strcpy(data.upsdesc, "LASER ONLINE 3750VA"); + strncpy(data.upsdesc, "LASER ONLINE 3750VA", sizeof(data.upsdesc)); data.VA = 3750; break; case 58: data.upscode = 58; - strcpy(data.upsdesc, "LASER ONLINE 5000VA"); + strncpy(data.upsdesc, "LASER ONLINE 5000VA", sizeof(data.upsdesc)); data.VA = 5000; break; case 59: data.upscode = 59; - strcpy(data.upsdesc, "LASER ONLINE 6000VA"); + strncpy(data.upsdesc, "LASER ONLINE 6000VA", sizeof(data.upsdesc)); data.VA = 6000; break; case 60: data.upscode = 60; - strcpy(data.upsdesc, "PREMIUM ONLINE 2000VA"); + strncpy(data.upsdesc, "PREMIUM ONLINE 2000VA", sizeof(data.upsdesc)); data.VA = 2000; break; case 61: data.upscode = 61; - strcpy(data.upsdesc, "PREMIUM ONLINE 1500VA"); + strncpy(data.upsdesc, "PREMIUM ONLINE 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 62: data.upscode = 62; - strcpy(data.upsdesc, "PREMIUM ONLINE 1200VA"); + strncpy(data.upsdesc, "PREMIUM ONLINE 1200VA", sizeof(data.upsdesc)); data.VA = 1200; break; case 63: data.upscode = 63; - strcpy(data.upsdesc, "COMPACT PLUS II MAX 1400VA"); + strncpy(data.upsdesc, "COMPACT PLUS II MAX 1400VA", sizeof(data.upsdesc)); data.VA = 1400; break; case 64: data.upscode = 64; - strcpy(data.upsdesc, "PREMIUM PDV MAX 2200VA"); + strncpy(data.upsdesc, "PREMIUM PDV MAX 2200VA", sizeof(data.upsdesc)); data.VA = 2200; break; case 65: data.upscode = 65; - strcpy(data.upsdesc, "PREMIUM PDV 3000VA"); + strncpy(data.upsdesc, "PREMIUM PDV 3000VA", sizeof(data.upsdesc)); data.VA = 3000; break; case 66: data.upscode = 66; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 2200VA GII"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 2200VA GII", sizeof(data.upsdesc)); data.VA = 2200; break; case 67: data.upscode = 67; - strcpy(data.upsdesc, "LASER PRIME SENOIDAL 3200VA GII"); + strncpy(data.upsdesc, "LASER PRIME SENOIDAL 3200VA GII", sizeof(data.upsdesc)); data.VA = 3200; break; case 68: data.upscode = 68; - strcpy(data.upsdesc, "PREMIUM RACK ONLINE 3000VA"); + strncpy(data.upsdesc, "PREMIUM RACK ONLINE 3000VA", sizeof(data.upsdesc)); data.VA = 3000; break; case 69: data.upscode = 69; - strcpy(data.upsdesc, "PREMIUM ONLINE 3000VA"); + strncpy(data.upsdesc, "PREMIUM ONLINE 3000VA", sizeof(data.upsdesc)); data.VA = 3000; break; case 70: data.upscode = 70; - strcpy(data.upsdesc, "LASER ONLINE 4000VA"); + strncpy(data.upsdesc, "LASER ONLINE 4000VA", sizeof(data.upsdesc)); data.VA = 4000; break; case 71: data.upscode = 71; - strcpy(data.upsdesc, "LASER ONLINE 7500VA"); + strncpy(data.upsdesc, "LASER ONLINE 7500VA", sizeof(data.upsdesc)); data.VA = 7500; break; case 72: data.upscode = 72; - strcpy(data.upsdesc, "LASER ONLINE BIFASICO 5000VA"); + strncpy(data.upsdesc, "LASER ONLINE BIFASICO 5000VA", sizeof(data.upsdesc)); data.VA = 5000; break; case 73: data.upscode = 73; - strcpy(data.upsdesc, "LASER ONLINE BIFASICO 6000VA"); + strncpy(data.upsdesc, "LASER ONLINE BIFASICO 6000VA", sizeof(data.upsdesc)); data.VA = 6000; break; case 74: data.upscode = 74; - strcpy(data.upsdesc, "LASER ONLINE BIFASICO 7500VA"); + strncpy(data.upsdesc, "LASER ONLINE BIFASICO 7500VA", sizeof(data.upsdesc)); data.VA = 7500; break; case 75: data.upscode = 75; - strcpy(data.upsdesc, "NHS MINI ST"); + strncpy(data.upsdesc, "NHS MINI ST", sizeof(data.upsdesc)); data.VA = 500; break; case 76: data.upscode = 76; - strcpy(data.upsdesc, "NHS MINI 120"); + strncpy(data.upsdesc, "NHS MINI 120", sizeof(data.upsdesc)); data.VA = 120; break; case 77: data.upscode = 77; - strcpy(data.upsdesc, "NHS MINI BIVOLT"); + strncpy(data.upsdesc, "NHS MINI BIVOLT", sizeof(data.upsdesc)); data.VA = 500; break; case 78: data.upscode = 78; - strcpy(data.upsdesc, "PDV 600"); + strncpy(data.upsdesc, "PDV 600", sizeof(data.upsdesc)); data.VA = 600; break; case 79: data.upscode = 79; - strcpy(data.upsdesc, "NHS MINI MAX"); + strncpy(data.upsdesc, "NHS MINI MAX", sizeof(data.upsdesc)); data.VA = 500; break; case 80: data.upscode = 80; - strcpy(data.upsdesc, "NHS MINI EXT"); + strncpy(data.upsdesc, "NHS MINI EXT", sizeof(data.upsdesc)); data.VA = 500; break; case 81: data.upscode = 81; - strcpy(data.upsdesc, "NHS AUTONOMY PDV 4T"); + strncpy(data.upsdesc, "NHS AUTONOMY PDV 4T", sizeof(data.upsdesc)); data.VA = 4000; break; case 82: data.upscode = 82; - strcpy(data.upsdesc, "NHS AUTONOMY PDV 8T"); + strncpy(data.upsdesc, "NHS AUTONOMY PDV 8T", sizeof(data.upsdesc)); data.VA = 8000; break; case 83: data.upscode = 83; - strcpy(data.upsdesc, "NHS COMPACT PLUS RACK 1200VA"); + strncpy(data.upsdesc, "NHS COMPACT PLUS RACK 1200VA", sizeof(data.upsdesc)); data.VA = 1200; break; case 84: data.upscode = 84; - strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1500VA"); + strncpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 85: data.upscode = 85; - strcpy(data.upsdesc, "NHS PDV RACK 1500VA"); + strncpy(data.upsdesc, "NHS PDV RACK 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 86: data.upscode = 86; - strcpy(data.upsdesc, "NHS PDV 1400VA S GII"); + strncpy(data.upsdesc, "NHS PDV 1400VA S GII", sizeof(data.upsdesc)); data.VA = 1400; break; case 87: data.upscode = 87; - strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1500VA"); + strncpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1500VA", sizeof(data.upsdesc)); data.VA = 1500; break; case 88: data.upscode = 88; - strcpy(data.upsdesc, "LASER PRIME SENOIDAL ISOLADOR 2000VA"); + strncpy(data.upsdesc, "LASER PRIME SENOIDAL ISOLADOR 2000VA", sizeof(data.upsdesc)); data.VA = 2000; break; case 89: data.upscode = 89; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 2400VA GII"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 2400VA GII", sizeof(data.upsdesc)); data.VA = 2400; break; case 90: data.upscode = 90; - strcpy(data.upsdesc, "NHS PDV 1400VA S 8T GII"); + strncpy(data.upsdesc, "NHS PDV 1400VA S 8T GII", sizeof(data.upsdesc)); data.VA = 1400; break; case 91: data.upscode = 91; - strcpy(data.upsdesc, "PREMIUM ONLINE 2000VA"); + strncpy(data.upsdesc, "PREMIUM ONLINE 2000VA", sizeof(data.upsdesc)); data.VA = 2000; break; case 92: data.upscode = 92; - strcpy(data.upsdesc, "LASER PRIME ONLINE 2200VA"); + strncpy(data.upsdesc, "LASER PRIME ONLINE 2200VA", sizeof(data.upsdesc)); data.VA = 2200; break; case 93: data.upscode = 93; - strcpy(data.upsdesc, "PREMIUM RACK ONLINE 2200VA"); + strncpy(data.upsdesc, "PREMIUM RACK ONLINE 2200VA", sizeof(data.upsdesc)); data.VA = 2200; break; case 94: data.upscode = 94; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 2400VA GII"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 2400VA GII", sizeof(data.upsdesc)); data.VA = 2400; break; case 95: data.upscode = 95; - strcpy(data.upsdesc, "LASER ONLINE 10000VA"); + strncpy(data.upsdesc, "LASER ONLINE 10000VA", sizeof(data.upsdesc)); data.VA = 10000; break; case 96: data.upscode = 96; - strcpy(data.upsdesc, "LASER ONLINE BIFASICO 10000VA"); + strncpy(data.upsdesc, "LASER ONLINE BIFASICO 10000VA", sizeof(data.upsdesc)); data.VA = 10000; break; case 97: data.upscode = 97; - strcpy(data.upsdesc, "LASER SENOIDAL 3300VA GII"); + strncpy(data.upsdesc, "LASER SENOIDAL 3300VA GII", sizeof(data.upsdesc)); data.VA = 3300; break; case 98: data.upscode = 98; - strcpy(data.upsdesc, "LASER SENOIDAL 2600VA GII"); + strncpy(data.upsdesc, "LASER SENOIDAL 2600VA GII", sizeof(data.upsdesc)); data.VA = 2600; break; case 99: data.upscode = 99; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 3000VA GII"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 3000VA GII", sizeof(data.upsdesc)); data.VA = 3000; break; case 100: data.upscode = 100; - strcpy(data.upsdesc, "PREMIUM SENOIDAL 2200VA GII"); + strncpy(data.upsdesc, "PREMIUM SENOIDAL 2200VA GII", sizeof(data.upsdesc)); data.VA = 2200; break; case 101: data.upscode = 101; - strcpy(data.upsdesc, "LASER ONLINE BIFASICO 4000VA"); + strncpy(data.upsdesc, "LASER ONLINE BIFASICO 4000VA", sizeof(data.upsdesc)); data.VA = 4000; break; case 102: data.upscode = 102; - strcpy(data.upsdesc, "LASER ONLINE 12000VA"); + strncpy(data.upsdesc, "LASER ONLINE 12000VA", sizeof(data.upsdesc)); data.VA = 12000; break; case 103: data.upscode = 103; - strcpy(data.upsdesc, "LASER ONLINE 8000VA"); + strncpy(data.upsdesc, "LASER ONLINE 8000VA", sizeof(data.upsdesc)); data.VA = 8000; break; case 104: data.upscode = 104; - strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1000VA"); + strncpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 1000VA", sizeof(data.upsdesc)); data.VA = 1000; break; case 105: data.upscode = 105; - strcpy(data.upsdesc, "MINI SENOIDAL 500VA"); + strncpy(data.upsdesc, "MINI SENOIDAL 500VA", sizeof(data.upsdesc)); data.VA = 500; break; case 106: data.upscode = 106; - strcpy(data.upsdesc, "LASER SENOIDAL 5000VA GII"); + strncpy(data.upsdesc, "LASER SENOIDAL 5000VA GII", sizeof(data.upsdesc)); data.VA = 5000; break; case 107: data.upscode = 107; - strcpy(data.upsdesc, "COMPACT PLUS SENOIDAL 1000VA"); + strncpy(data.upsdesc, "COMPACT PLUS SENOIDAL 1000VA", sizeof(data.upsdesc)); data.VA = 1000; break; case 108: data.upscode = 108; - strcpy(data.upsdesc, "QUAD_COM 80A"); + strncpy(data.upsdesc, "QUAD_COM 80A", sizeof(data.upsdesc)); data.VA = 0; break; case 109: data.upscode = 109; - strcpy(data.upsdesc, "LASER ONLINE 5000VA"); + strncpy(data.upsdesc, "LASER ONLINE 5000VA", sizeof(data.upsdesc)); data.VA = 5000; break; case 113: data.upscode = 113; - strcpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 700VA"); + strncpy(data.upsdesc, "PDV SENOIDAL ISOLADOR 700VA", sizeof(data.upsdesc)); data.VA = 700; break; default: data.upscode = -1; - strcpy(data.upsdesc, "NHS UNKNOWN"); + strncpy(data.upsdesc, "NHS UNKNOWN", sizeof(data.upsdesc)); data.VA = 0; break; } From 66cf349ed50603b20cab253de28355b4ea8b189d Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:36:34 +0000 Subject: [PATCH 51/60] drivers/nhs_ser.c: upsdrv_updateinfo(): FIXME commented - same criteria used for 3 alarms [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 8cccb64db6..96eca81761 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1879,6 +1879,8 @@ void upsdrv_updateinfo(void) { if (lastpktdata.s_network_failure) snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", "|NETWORK FAILURE|"); + + /* FIXME: Really same criteria in these 3? */ if (lastpktdata.s_fast_network_failure) snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", "|FAST NETWORK FAILURE|"); @@ -1888,6 +1890,7 @@ void upsdrv_updateinfo(void) { if (lastpktdata.s_fast_network_failure) snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", "|220v OUT|"); + if (lastpktdata.s_bypass_on) snprintfcat(alarm, sizeof(alarm), "%s%s", *alarm ? " " : "", "|BYPASS ON|"); From 125959ff3b8cf83fce16663de54c93630480a44f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:38:33 +0000 Subject: [PATCH 52/60] drivers/nhs_ser.c: upsdrv_updateinfo(): rename "nhs.*" datapoints into "experimental.nhs.*" namespace [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 196 +++++++++++++++++++++++----------------------- 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 96eca81761..42dc0734ed 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -2004,118 +2004,118 @@ void upsdrv_updateinfo(void) { dstate_setinfo("battery.charger.status", "%s", "RESTING"); } /* Now, creating a structure called NHS, */ - dstate_setinfo("nhs.hw.header", "%u", lastpkthwinfo.header); - dstate_setinfo("nhs.hw.size", "%u", lastpkthwinfo.size); - dstate_setinfo("nhs.hw.type", "%c", lastpkthwinfo.type); - dstate_setinfo("nhs.hw.model", "%u", lastpkthwinfo.model); - dstate_setinfo("nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); - dstate_setinfo("nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); - dstate_setinfo("nhs.hw.configuration", "%u", lastpkthwinfo.configuration); + dstate_setinfo("experimental.nhs.hw.header", "%u", lastpkthwinfo.header); + dstate_setinfo("experimental.nhs.hw.size", "%u", lastpkthwinfo.size); + dstate_setinfo("experimental.nhs.hw.type", "%c", lastpkthwinfo.type); + dstate_setinfo("experimental.nhs.hw.model", "%u", lastpkthwinfo.model); + dstate_setinfo("experimental.nhs.hw.hardwareversion", "%u", lastpkthwinfo.hardwareversion); + dstate_setinfo("experimental.nhs.hw.softwareversion", "%u", lastpkthwinfo.softwareversion); + dstate_setinfo("experimental.nhs.hw.configuration", "%u", lastpkthwinfo.configuration); for (i = 0; i < 5; i++) { /* Reusing variable */ - snprintf(alarm, sizeof(alarm), "nhs.hw.configuration_array_p%d", i); + snprintf(alarm, sizeof(alarm), "experimental.nhs.hw.configuration_array_p%d", i); dstate_setinfo(alarm, "%u", lastpkthwinfo.configuration_array[i]); } - dstate_setinfo("nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); - dstate_setinfo("nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); - dstate_setinfo("nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); - dstate_setinfo("nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); - dstate_setinfo("nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); - dstate_setinfo("nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); - dstate_setinfo("nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); - dstate_setinfo("nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); - dstate_setinfo("nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); - dstate_setinfo("nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); - dstate_setinfo("nhs.hw.statusval", "%u", lastpkthwinfo.statusval); + dstate_setinfo("experimental.nhs.hw.c_oem_mode", "%s", lastpkthwinfo.c_oem_mode ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.c_buzzer_disable", "%s", lastpkthwinfo.c_buzzer_disable ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.c_potmin_disable", "%s", lastpkthwinfo.c_potmin_disable ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.c_rearm_enable", "%s", lastpkthwinfo.c_rearm_enable ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.c_bootloader_enable", "%s", lastpkthwinfo.c_bootloader_enable ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.numbatteries", "%u", lastpkthwinfo.numbatteries); + dstate_setinfo("experimental.nhs.hw.undervoltagein120V", "%u", lastpkthwinfo.undervoltagein120V); + dstate_setinfo("experimental.nhs.hw.overvoltagein120V", "%u", lastpkthwinfo.overvoltagein120V); + dstate_setinfo("experimental.nhs.hw.undervoltagein220V", "%u", lastpkthwinfo.undervoltagein220V); + dstate_setinfo("experimental.nhs.hw.overvoltagein220V", "%u", lastpkthwinfo.overvoltagein220V); + dstate_setinfo("experimental.nhs.hw.tensionout120V", "%u", lastpkthwinfo.tensionout120V); + dstate_setinfo("experimental.nhs.hw.tensionout220V", "%u", lastpkthwinfo.tensionout220V); + dstate_setinfo("experimental.nhs.hw.statusval", "%u", lastpkthwinfo.statusval); for (i = 0; i < 6; i++) { /* Reusing variable */ - snprintf(alarm, sizeof(alarm), "nhs.hw.status_p%d", i); + snprintf(alarm, sizeof(alarm), "experimental.nhs.hw.status_p%d", i); dstate_setinfo(alarm, "%u", lastpkthwinfo.status[i]); } - dstate_setinfo("nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); - dstate_setinfo("nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); - dstate_setinfo("nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); - dstate_setinfo("nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); - dstate_setinfo("nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); - dstate_setinfo("nhs.hw.checksum", "%u", lastpkthwinfo.checksum); - dstate_setinfo("nhs.hw.checksum_calc", "%u", lastpkthwinfo.checksum_calc); - dstate_setinfo("nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.hw.serial", "%s", lastpkthwinfo.serial); - dstate_setinfo("nhs.hw.year", "%u", lastpkthwinfo.year); - dstate_setinfo("nhs.hw.month", "%u", lastpkthwinfo.month); - dstate_setinfo("nhs.hw.wday", "%u", lastpkthwinfo.wday); - dstate_setinfo("nhs.hw.hour", "%u", lastpkthwinfo.hour); - dstate_setinfo("nhs.hw.minute", "%u", lastpkthwinfo.minute); - dstate_setinfo("nhs.hw.second", "%u", lastpkthwinfo.second); - dstate_setinfo("nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); - dstate_setinfo("nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); - dstate_setinfo("nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); - dstate_setinfo("nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); - dstate_setinfo("nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); - dstate_setinfo("nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); - dstate_setinfo("nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); - dstate_setinfo("nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); + dstate_setinfo("experimental.nhs.hw.s_220V_in", "%s", lastpkthwinfo.s_220V_in ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.s_220V_out", "%s", lastpkthwinfo.s_220V_out ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.s_sealed_battery", "%s", lastpkthwinfo.s_sealed_battery ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.s_show_out_tension", "%s", lastpkthwinfo.s_show_out_tension ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.s_show_temperature", "%s", lastpkthwinfo.s_show_temperature ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.s_show_charger_current", "%s", lastpkthwinfo.s_show_charger_current ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.chargercurrent", "%u", lastpkthwinfo.chargercurrent); + dstate_setinfo("experimental.nhs.hw.checksum", "%u", lastpkthwinfo.checksum); + dstate_setinfo("experimental.nhs.hw.checksum_calc", "%u", lastpkthwinfo.checksum_calc); + dstate_setinfo("experimental.nhs.hw.checksum_ok", "%s", lastpkthwinfo.checksum_ok ? "true" : "false"); + dstate_setinfo("experimental.nhs.hw.serial", "%s", lastpkthwinfo.serial); + dstate_setinfo("experimental.nhs.hw.year", "%u", lastpkthwinfo.year); + dstate_setinfo("experimental.nhs.hw.month", "%u", lastpkthwinfo.month); + dstate_setinfo("experimental.nhs.hw.wday", "%u", lastpkthwinfo.wday); + dstate_setinfo("experimental.nhs.hw.hour", "%u", lastpkthwinfo.hour); + dstate_setinfo("experimental.nhs.hw.minute", "%u", lastpkthwinfo.minute); + dstate_setinfo("experimental.nhs.hw.second", "%u", lastpkthwinfo.second); + dstate_setinfo("experimental.nhs.hw.alarmyear", "%u", lastpkthwinfo.alarmyear); + dstate_setinfo("experimental.nhs.hw.alarmmonth", "%u", lastpkthwinfo.alarmmonth); + dstate_setinfo("experimental.nhs.hw.alarmwday", "%u", lastpkthwinfo.alarmwday); + dstate_setinfo("experimental.nhs.hw.alarmday", "%u", lastpkthwinfo.alarmday); + dstate_setinfo("experimental.nhs.hw.alarmhour", "%u", lastpkthwinfo.alarmhour); + dstate_setinfo("experimental.nhs.hw.alarmminute", "%u", lastpkthwinfo.alarmminute); + dstate_setinfo("experimental.nhs.hw.alarmsecond", "%u", lastpkthwinfo.alarmsecond); + dstate_setinfo("experimental.nhs.hw.end_marker", "%u", lastpkthwinfo.end_marker); /* Data packet */ - dstate_setinfo("nhs.data.header", "%u", lastpktdata.header); - dstate_setinfo("nhs.data.length", "%u", lastpktdata.length); - dstate_setinfo("nhs.data.packet_type", "%c", lastpktdata.packet_type); - dstate_setinfo("nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); - dstate_setinfo("nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); - dstate_setinfo("nhs.data.vacinrms", "%0.2f", lastpktdata.vacinrms); - dstate_setinfo("nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); - dstate_setinfo("nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); - dstate_setinfo("nhs.data.vdcmed", "%0.2f", lastpktdata.vdcmed); - dstate_setinfo("nhs.data.vdcmed_real", "%0.2f", lastpktdata.vdcmed_real); - dstate_setinfo("nhs.data.potrms", "%u", lastpktdata.potrms); - dstate_setinfo("nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); - dstate_setinfo("nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); - dstate_setinfo("nhs.data.vacinrmsmin", "%0.2f", lastpktdata.vacinrmsmin); - dstate_setinfo("nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); - dstate_setinfo("nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); - dstate_setinfo("nhs.data.vacinrmsmax", "%0.2f", lastpktdata.vacinrmsmax); - dstate_setinfo("nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); - dstate_setinfo("nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); - dstate_setinfo("nhs.data.vacoutrms", "%0.2f", lastpktdata.vacoutrms); - dstate_setinfo("nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); - dstate_setinfo("nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); - dstate_setinfo("nhs.data.tempmed", "%0.2f", lastpktdata.tempmed); - dstate_setinfo("nhs.data.tempmed_real", "%0.2f", lastpktdata.tempmed_real); - dstate_setinfo("nhs.data.icarregrms", "%u", lastpktdata.icarregrms); - dstate_setinfo("nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); - dstate_setinfo("nhs.data.battery_tension", "%0.2f", lastpktdata.battery_tension); - dstate_setinfo("nhs.data.perc_output", "%u", lastpktdata.perc_output); - dstate_setinfo("nhs.data.statusval", "%u", lastpktdata.statusval); + dstate_setinfo("experimental.nhs.data.header", "%u", lastpktdata.header); + dstate_setinfo("experimental.nhs.data.length", "%u", lastpktdata.length); + dstate_setinfo("experimental.nhs.data.packet_type", "%c", lastpktdata.packet_type); + dstate_setinfo("experimental.nhs.data.vacinrms_high", "%u", lastpktdata.vacinrms_high); + dstate_setinfo("experimental.nhs.data.vacinrms_low", "%u", lastpktdata.vacinrms_low); + dstate_setinfo("experimental.nhs.data.vacinrms", "%0.2f", lastpktdata.vacinrms); + dstate_setinfo("experimental.nhs.data.vdcmed_high", "%u", lastpktdata.vdcmed_high); + dstate_setinfo("experimental.nhs.data.vdcmed_low", "%u", lastpktdata.vdcmed_low); + dstate_setinfo("experimental.nhs.data.vdcmed", "%0.2f", lastpktdata.vdcmed); + dstate_setinfo("experimental.nhs.data.vdcmed_real", "%0.2f", lastpktdata.vdcmed_real); + dstate_setinfo("experimental.nhs.data.potrms", "%u", lastpktdata.potrms); + dstate_setinfo("experimental.nhs.data.vacinrmsmin_high", "%u", lastpktdata.vacinrmsmin_high); + dstate_setinfo("experimental.nhs.data.vacinrmsmin_low", "%u", lastpktdata.vacinrmsmin_low); + dstate_setinfo("experimental.nhs.data.vacinrmsmin", "%0.2f", lastpktdata.vacinrmsmin); + dstate_setinfo("experimental.nhs.data.vacinrmsmax_high", "%u", lastpktdata.vacinrmsmax_high); + dstate_setinfo("experimental.nhs.data.vacinrmsmax_low", "%u", lastpktdata.vacinrmsmax_low); + dstate_setinfo("experimental.nhs.data.vacinrmsmax", "%0.2f", lastpktdata.vacinrmsmax); + dstate_setinfo("experimental.nhs.data.vacoutrms_high", "%u", lastpktdata.vacoutrms_high); + dstate_setinfo("experimental.nhs.data.vacoutrms_low", "%u", lastpktdata.vacoutrms_low); + dstate_setinfo("experimental.nhs.data.vacoutrms", "%0.2f", lastpktdata.vacoutrms); + dstate_setinfo("experimental.nhs.data.tempmed_high", "%u", lastpktdata.tempmed_high); + dstate_setinfo("experimental.nhs.data.tempmed_low", "%u", lastpktdata.tempmed_low); + dstate_setinfo("experimental.nhs.data.tempmed", "%0.2f", lastpktdata.tempmed); + dstate_setinfo("experimental.nhs.data.tempmed_real", "%0.2f", lastpktdata.tempmed_real); + dstate_setinfo("experimental.nhs.data.icarregrms", "%u", lastpktdata.icarregrms); + dstate_setinfo("experimental.nhs.data.icarregrms_real", "%u", lastpktdata.icarregrms_real); + dstate_setinfo("experimental.nhs.data.battery_tension", "%0.2f", lastpktdata.battery_tension); + dstate_setinfo("experimental.nhs.data.perc_output", "%u", lastpktdata.perc_output); + dstate_setinfo("experimental.nhs.data.statusval", "%u", lastpktdata.statusval); for (i = 0; i < 8; i++) { /* Reusing variable */ - snprintf(alarm, sizeof(alarm), "nhs.data.status_p%d", i); + snprintf(alarm, sizeof(alarm), "experimental.nhs.data.status_p%d", i); dstate_setinfo(alarm, "%u", lastpktdata.status[i]); } - dstate_setinfo("nhs.data.nominaltension", "%u", lastpktdata.nominaltension); - dstate_setinfo("nhs.data.timeremain", "%0.2f", lastpktdata.timeremain); - dstate_setinfo("nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); - dstate_setinfo("nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); - dstate_setinfo("nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); - dstate_setinfo("nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); - dstate_setinfo("nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); - dstate_setinfo("nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); - dstate_setinfo("nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); - dstate_setinfo("nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); - dstate_setinfo("nhs.data.checksum", "%u", lastpktdata.checksum); - dstate_setinfo("nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); - dstate_setinfo("nhs.data.checksum_calc", "%u", lastpktdata.checksum_calc); - dstate_setinfo("nhs.data.end_marker", "%u", lastpktdata.end_marker); - dstate_setinfo("nhs.param.va", "%u", va); - dstate_setinfo("nhs.param.pf", "%0.2f", pf); - dstate_setinfo("nhs.param.ah", "%u", ah); - dstate_setinfo("nhs.param.vin_low_warn_perc", "%0.2f", get_vin_perc("vin_low_warn_perc")); - dstate_setinfo("nhs.param.vin_low_crit_perc", "%0.2f", get_vin_perc("vin_low_crit_perc")); - dstate_setinfo("nhs.param.vin_high_warn_perc", "%0.2f", get_vin_perc("vin_high_warn_perc")); - dstate_setinfo("nhs.param.vin_high_crit_perc", "%0.2f", get_vin_perc("vin_high_crit_perc")); + dstate_setinfo("experimental.nhs.data.nominaltension", "%u", lastpktdata.nominaltension); + dstate_setinfo("experimental.nhs.data.timeremain", "%0.2f", lastpktdata.timeremain); + dstate_setinfo("experimental.nhs.data.s_battery_mode", "%s", lastpktdata.s_battery_mode ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_battery_low", "%s", lastpktdata.s_battery_low ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_network_failure", "%s", lastpktdata.s_network_failure ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_fast_network_failure", "%s", lastpktdata.s_fast_network_failure ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_220_in", "%s", lastpktdata.s_220_in ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_220_out", "%s", lastpktdata.s_220_out ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_bypass_on", "%s", lastpktdata.s_bypass_on ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.s_charger_on", "%s", lastpktdata.s_charger_on ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.checksum", "%u", lastpktdata.checksum); + dstate_setinfo("experimental.nhs.data.checksum_ok", "%s", lastpktdata.checksum_ok ? "true" : "false"); + dstate_setinfo("experimental.nhs.data.checksum_calc", "%u", lastpktdata.checksum_calc); + dstate_setinfo("experimental.nhs.data.end_marker", "%u", lastpktdata.end_marker); + dstate_setinfo("experimental.nhs.param.va", "%u", va); + dstate_setinfo("experimental.nhs.param.pf", "%0.2f", pf); + dstate_setinfo("experimental.nhs.param.ah", "%u", ah); + dstate_setinfo("experimental.nhs.param.vin_low_warn_perc", "%0.2f", get_vin_perc("vin_low_warn_perc")); + dstate_setinfo("experimental.nhs.param.vin_low_crit_perc", "%0.2f", get_vin_perc("vin_low_crit_perc")); + dstate_setinfo("experimental.nhs.param.vin_high_warn_perc", "%0.2f", get_vin_perc("vin_high_warn_perc")); + dstate_setinfo("experimental.nhs.param.vin_high_crit_perc", "%0.2f", get_vin_perc("vin_high_crit_perc")); dstate_dataok(); } /* end if */ From f85b97b203c96224c752892b02438d53b0d48c94 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:43:28 +0000 Subject: [PATCH 53/60] drivers/nhs_ser.c: log method starting/ending quieter and with use of __func__ [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 42dc0734ed..26680feea9 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1649,7 +1649,7 @@ void upsdrv_initinfo(void) { upsdebugx(1, "Port is %s and baud_rate is %s", device_path, b); baudrate = DEFAULTBAUD; - upsdebugx(1, "Start initinfo()"); + upsdebugx(3, "%s: starting...", __func__); if (b) baudrate = atoi(b); if (device_path) { @@ -1666,7 +1666,7 @@ void upsdrv_initinfo(void) { } else fatalx(EXIT_FAILURE, "Unable to define port and baud"); - upsdebugx(1, "End initinfo()"); + upsdebugx(3, "%s: finished", __func__); } static float calculate_efficiency(float vacoutrms, float vacinrms) { @@ -1711,7 +1711,7 @@ void upsdrv_updateinfo(void) { float actual_current = 0; upsinfo ups; - upsdebugx(1, "Start updateinfo()"); + upsdebugx(3, "%s: starting...", __func__); if ((serial_fd <= 0) && (i < retries)) { upsdebugx(1, "Serial problem..."); while (serial_fd <= 0) { @@ -2177,11 +2177,11 @@ void upsdrv_updateinfo(void) { } /* end else */ } /* end if */ } /* end else */ - upsdebugx(1, "End updateinfo()"); + upsdebugx(3, "%s: finished", __func__); } void upsdrv_shutdown(void) { - upsdebugx(1, "Start shutdown()"); + upsdebugx(3, "%s: starting...", __func__); /* replace with a proper shutdown function */ upslogx(LOG_ERR, "shutdown not supported"); @@ -2191,18 +2191,18 @@ void upsdrv_shutdown(void) { } void upsdrv_cleanup(void) { - upsdebugx(1, "Start cleanup()"); + upsdebugx(3, "%s: starting...", __func__); if (serial_fd != -1) { close(serial_fd); serial_fd = -1; } - upsdebugx(1, "End cleanup()"); + upsdebugx(3, "%s: finished", __func__); } void upsdrv_initups(void) { - upsdebugx(1, "Start initups()"); + upsdebugx(3, "%s: starting...", __func__); /* Process optional configuration flags */ if (getval("debug_pkt_raw")) @@ -2213,7 +2213,7 @@ void upsdrv_initups(void) { debug_pkt_hwinfo = 1; upsdrv_initinfo(); - upsdebugx(1, "End initups()"); + upsdebugx(3, "%s: finished", __func__); } void upsdrv_makevartable(void) { From 8063a2195737fa24242ca039a11c72bf97dbb476 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 01:49:30 +0000 Subject: [PATCH 54/60] drivers/nhs_ser.c: quieter logging in print_pkt_hwinfo() and print_pkt_data() [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 230 ++++++++++++++++++++++++---------------------- 1 file changed, 118 insertions(+), 112 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 26680feea9..0c2fd42fdf 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -381,70 +381,72 @@ static void print_pkt_hwinfo(pkt_hwinfo data) { if (!debug_pkt_hwinfo) return; - upsdebugx(1, "Header: %u", data.header); - upsdebugx(1, "Size: %u", data.size); - upsdebugx(1, "Type: %c", data.type); - upsdebugx(1, "Model: %u", data.model); - upsdebugx(1, "Hardware Version: %u", data.hardwareversion); - upsdebugx(1, "Software Version: %u", data.softwareversion); - upsdebugx(1, "Configuration: %u", data.configuration); - - upsdebugx(1, "Configuration Array: "); - upsdebugx(1, "-----"); + upsdebugx(1, "%s: logging packet details at debug verbosity 5 or more", __func__); + + upsdebugx(5, "Header: %u", data.header); + upsdebugx(5, "Size: %u", data.size); + upsdebugx(5, "Type: %c", data.type); + upsdebugx(5, "Model: %u", data.model); + upsdebugx(5, "Hardware Version: %u", data.hardwareversion); + upsdebugx(5, "Software Version: %u", data.softwareversion); + upsdebugx(5, "Configuration: %u", data.configuration); + + upsdebugx(5, "Configuration Array: "); + upsdebugx(5, "-----"); for (i = 0; i < 5; i++) { int retorno = get_bit_in_position(&data.configuration, sizeof(data.configuration), i, 0); - upsdebugx(1, "Binary value is %d", retorno); - upsdebugx(1, "%u ", data.configuration_array[i]); + upsdebugx(5, "Binary value is %d", retorno); + upsdebugx(5, "%u ", data.configuration_array[i]); } - upsdebugx(1, "-----"); - - upsdebugx(1, "OEM Mode: %s", data.c_oem_mode ? "true" : "false"); - upsdebugx(1, "Buzzer Disable: %s", data.c_buzzer_disable ? "true" : "false"); - upsdebugx(1, "Potmin Disable: %s", data.c_potmin_disable ? "true" : "false"); - upsdebugx(1, "Rearm Enable: %s", data.c_rearm_enable ? "true" : "false"); - upsdebugx(1, "Bootloader Enable: %s", data.c_bootloader_enable ? "true" : "false"); - upsdebugx(1, "Number of Batteries: %u", data.numbatteries); - upsdebugx(1, "Undervoltage In 120V: %u", data.undervoltagein120V); - upsdebugx(1, "Overvoltage In 120V: %u", data.overvoltagein120V); - upsdebugx(1, "Undervoltage In 220V: %u", data.undervoltagein220V); - upsdebugx(1, "Overvoltage In 220V: %u", data.overvoltagein220V); - upsdebugx(1, "Tension Out 120V: %u", data.tensionout120V); - upsdebugx(1, "Tension Out 220V: %u", data.tensionout220V); - upsdebugx(1, "Status Value: %u", data.statusval); - - upsdebugx(1, "Status: "); - upsdebugx(1, "-----"); + upsdebugx(5, "-----"); + + upsdebugx(5, "OEM Mode: %s", data.c_oem_mode ? "true" : "false"); + upsdebugx(5, "Buzzer Disable: %s", data.c_buzzer_disable ? "true" : "false"); + upsdebugx(5, "Potmin Disable: %s", data.c_potmin_disable ? "true" : "false"); + upsdebugx(5, "Rearm Enable: %s", data.c_rearm_enable ? "true" : "false"); + upsdebugx(5, "Bootloader Enable: %s", data.c_bootloader_enable ? "true" : "false"); + upsdebugx(5, "Number of Batteries: %u", data.numbatteries); + upsdebugx(5, "Undervoltage In 120V: %u", data.undervoltagein120V); + upsdebugx(5, "Overvoltage In 120V: %u", data.overvoltagein120V); + upsdebugx(5, "Undervoltage In 220V: %u", data.undervoltagein220V); + upsdebugx(5, "Overvoltage In 220V: %u", data.overvoltagein220V); + upsdebugx(5, "Tension Out 120V: %u", data.tensionout120V); + upsdebugx(5, "Tension Out 220V: %u", data.tensionout220V); + upsdebugx(5, "Status Value: %u", data.statusval); + + upsdebugx(5, "Status: "); + upsdebugx(5, "-----"); for (i = 0; i < 6; i++) { - upsdebugx(1, "Binary value is %d", get_bit_in_position(&data.statusval, sizeof(data.statusval), i, 0)); - upsdebugx(1, "status %d --> %u ", i, data.status[i]); + upsdebugx(5, "Binary value is %d", get_bit_in_position(&data.statusval, sizeof(data.statusval), i, 0)); + upsdebugx(5, "status %d --> %u ", i, data.status[i]); } - upsdebugx(1, "-----"); - - upsdebugx(1, "220V In: %s", data.s_220V_in ? "true" : "false"); - upsdebugx(1, "220V Out: %s", data.s_220V_out ? "true" : "false"); - upsdebugx(1, "Sealed Battery: %s", data.s_sealed_battery ? "true" : "false"); - upsdebugx(1, "Show Out Tension: %s", data.s_show_out_tension ? "true" : "false"); - upsdebugx(1, "Show Temperature: %s", data.s_show_temperature ? "true" : "false"); - upsdebugx(1, "Show Charger Current: %s", data.s_show_charger_current ? "true" : "false"); - upsdebugx(1, "Charger Current: %u", data.chargercurrent); - upsdebugx(1, "Checksum: %u", data.checksum); - upsdebugx(1, "Checksum Calc: %u", data.checksum_calc); - upsdebugx(1, "Checksum OK: %s", data.checksum_ok ? "true" : "false"); - upsdebugx(1, "Serial: %s", data.serial); - upsdebugx(1, "Year: %u", data.year); - upsdebugx(1, "Month: %u", data.month); - upsdebugx(1, "Weekday: %u", data.wday); - upsdebugx(1, "Hour: %u", data.hour); - upsdebugx(1, "Minute: %u", data.minute); - upsdebugx(1, "Second: %u", data.second); - upsdebugx(1, "Alarm Year: %u", data.alarmyear); - upsdebugx(1, "Alarm Month: %u", data.alarmmonth); - upsdebugx(1, "Alarm Weekday: %u", data.alarmwday); - upsdebugx(1, "Alarm Day: %u", data.alarmday); - upsdebugx(1, "Alarm Hour: %u", data.alarmhour); - upsdebugx(1, "Alarm Minute: %u", data.alarmminute); - upsdebugx(1, "Alarm Second: %u", data.alarmsecond); - upsdebugx(1, "End Marker: %u", data.end_marker); + upsdebugx(5, "-----"); + + upsdebugx(5, "220V In: %s", data.s_220V_in ? "true" : "false"); + upsdebugx(5, "220V Out: %s", data.s_220V_out ? "true" : "false"); + upsdebugx(5, "Sealed Battery: %s", data.s_sealed_battery ? "true" : "false"); + upsdebugx(5, "Show Out Tension: %s", data.s_show_out_tension ? "true" : "false"); + upsdebugx(5, "Show Temperature: %s", data.s_show_temperature ? "true" : "false"); + upsdebugx(5, "Show Charger Current: %s", data.s_show_charger_current ? "true" : "false"); + upsdebugx(5, "Charger Current: %u", data.chargercurrent); + upsdebugx(5, "Checksum: %u", data.checksum); + upsdebugx(5, "Checksum Calc: %u", data.checksum_calc); + upsdebugx(5, "Checksum OK: %s", data.checksum_ok ? "true" : "false"); + upsdebugx(5, "Serial: %s", data.serial); + upsdebugx(5, "Year: %u", data.year); + upsdebugx(5, "Month: %u", data.month); + upsdebugx(5, "Weekday: %u", data.wday); + upsdebugx(5, "Hour: %u", data.hour); + upsdebugx(5, "Minute: %u", data.minute); + upsdebugx(5, "Second: %u", data.second); + upsdebugx(5, "Alarm Year: %u", data.alarmyear); + upsdebugx(5, "Alarm Month: %u", data.alarmmonth); + upsdebugx(5, "Alarm Weekday: %u", data.alarmwday); + upsdebugx(5, "Alarm Day: %u", data.alarmday); + upsdebugx(5, "Alarm Hour: %u", data.alarmhour); + upsdebugx(5, "Alarm Minute: %u", data.alarmminute); + upsdebugx(5, "Alarm Second: %u", data.alarmsecond); + upsdebugx(5, "End Marker: %u", data.end_marker); } static void print_pkt_data(pkt_data data) { @@ -453,58 +455,60 @@ static void print_pkt_data(pkt_data data) { if (!debug_pkt_data) return; - upsdebugx(1, "Header: %u", data.header); - upsdebugx(1, "Length: %u", data.length); - upsdebugx(1, "Packet Type: %c", data.packet_type); - upsdebugx(1, "Vacin RMS High: %u", data.vacinrms_high); - upsdebugx(1, "Vacin RMS Low: %u", data.vacinrms_low); - upsdebugx(1, "Vacin RMS: %0.2f", data.vacinrms); - upsdebugx(1, "VDC Med High: %u", data.vdcmed_high); - upsdebugx(1, "VDC Med Low: %u", data.vdcmed_low); - upsdebugx(1, "VDC Med: %0.2f", data.vdcmed); - upsdebugx(1, "VDC Med Real: %0.2f", data.vdcmed_real); - upsdebugx(1, "Pot RMS: %u", data.potrms); - upsdebugx(1, "Vacin RMS Min High: %u", data.vacinrmsmin_high); - upsdebugx(1, "Vacin RMS Min Low: %u", data.vacinrmsmin_low); - upsdebugx(1, "Vacin RMS Min: %0.2f", data.vacinrmsmin); - upsdebugx(1, "Vacin RMS Max High: %u", data.vacinrmsmax_high); - upsdebugx(1, "Vacin RMS Max Low: %u", data.vacinrmsmax_low); - upsdebugx(1, "Vacin RMS Max: %0.2f", data.vacinrmsmax); - upsdebugx(1, "Vac Out RMS High: %u", data.vacoutrms_high); - upsdebugx(1, "Vac Out RMS Low: %u", data.vacoutrms_low); - upsdebugx(1, "Vac Out RMS: %0.2f", data.vacoutrms); - upsdebugx(1, "Temp Med High: %u", data.tempmed_high); - upsdebugx(1, "Temp Med Low: %u", data.tempmed_low); - upsdebugx(1, "Temp Med: %0.2f", data.tempmed); - upsdebugx(1, "Temp Med Real: %0.2f", data.tempmed_real); - upsdebugx(1, "Icar Reg RMS: %u", data.icarregrms); - upsdebugx(1, "Icar Reg RMS Real: %u", data.icarregrms_real); - upsdebugx(1, "Battery Tension: %0.2f", data.battery_tension); - upsdebugx(1, "Perc Output: %u", data.perc_output); - upsdebugx(1, "Status Value: %u", data.statusval); - - upsdebugx(1, "Status: "); - upsdebugx(1, "-----"); + upsdebugx(1, "%s: logging packet details at debug verbosity 5 or more", __func__); + + upsdebugx(5, "Header: %u", data.header); + upsdebugx(5, "Length: %u", data.length); + upsdebugx(5, "Packet Type: %c", data.packet_type); + upsdebugx(5, "Vacin RMS High: %u", data.vacinrms_high); + upsdebugx(5, "Vacin RMS Low: %u", data.vacinrms_low); + upsdebugx(5, "Vacin RMS: %0.2f", data.vacinrms); + upsdebugx(5, "VDC Med High: %u", data.vdcmed_high); + upsdebugx(5, "VDC Med Low: %u", data.vdcmed_low); + upsdebugx(5, "VDC Med: %0.2f", data.vdcmed); + upsdebugx(5, "VDC Med Real: %0.2f", data.vdcmed_real); + upsdebugx(5, "Pot RMS: %u", data.potrms); + upsdebugx(5, "Vacin RMS Min High: %u", data.vacinrmsmin_high); + upsdebugx(5, "Vacin RMS Min Low: %u", data.vacinrmsmin_low); + upsdebugx(5, "Vacin RMS Min: %0.2f", data.vacinrmsmin); + upsdebugx(5, "Vacin RMS Max High: %u", data.vacinrmsmax_high); + upsdebugx(5, "Vacin RMS Max Low: %u", data.vacinrmsmax_low); + upsdebugx(5, "Vacin RMS Max: %0.2f", data.vacinrmsmax); + upsdebugx(5, "Vac Out RMS High: %u", data.vacoutrms_high); + upsdebugx(5, "Vac Out RMS Low: %u", data.vacoutrms_low); + upsdebugx(5, "Vac Out RMS: %0.2f", data.vacoutrms); + upsdebugx(5, "Temp Med High: %u", data.tempmed_high); + upsdebugx(5, "Temp Med Low: %u", data.tempmed_low); + upsdebugx(5, "Temp Med: %0.2f", data.tempmed); + upsdebugx(5, "Temp Med Real: %0.2f", data.tempmed_real); + upsdebugx(5, "Icar Reg RMS: %u", data.icarregrms); + upsdebugx(5, "Icar Reg RMS Real: %u", data.icarregrms_real); + upsdebugx(5, "Battery Tension: %0.2f", data.battery_tension); + upsdebugx(5, "Perc Output: %u", data.perc_output); + upsdebugx(5, "Status Value: %u", data.statusval); + + upsdebugx(5, "Status: "); + upsdebugx(5, "-----"); for (i = 0; i < 8; i++) { - upsdebugx(1, "Binary value is %d", get_bit_in_position(&data.statusval, sizeof(data.statusval), i, 0)); - upsdebugx(1, "status %d --> %u ", i, data.status[i]); + upsdebugx(5, "Binary value is %d", get_bit_in_position(&data.statusval, sizeof(data.statusval), i, 0)); + upsdebugx(5, "status %d --> %u ", i, data.status[i]); } - upsdebugx(1, "-----"); - - upsdebugx(1, "Nominal Tension: %u", data.nominaltension); - upsdebugx(1, "Time Remain: %0.2f", data.timeremain); - upsdebugx(1, "Battery Mode: %s", data.s_battery_mode ? "true" : "false"); - upsdebugx(1, "Battery Low: %s", data.s_battery_low ? "true" : "false"); - upsdebugx(1, "Network Failure: %s", data.s_network_failure ? "true" : "false"); - upsdebugx(1, "Fast Network Failure: %s", data.s_fast_network_failure ? "true" : "false"); - upsdebugx(1, "220 In: %s", data.s_220_in ? "true" : "false"); - upsdebugx(1, "220 Out: %s", data.s_220_out ? "true" : "false"); - upsdebugx(1, "Bypass On: %s", data.s_bypass_on ? "true" : "false"); - upsdebugx(1, "Charger On: %s", data.s_charger_on ? "true" : "false"); - upsdebugx(1, "Checksum: %u", data.checksum); - upsdebugx(1, "Checksum Calc: %u", data.checksum_calc); - upsdebugx(1, "Checksum OK: %s", data.checksum_ok ? "true" : "false"); - upsdebugx(1, "End Marker: %u", data.end_marker); + upsdebugx(5, "-----"); + + upsdebugx(5, "Nominal Tension: %u", data.nominaltension); + upsdebugx(5, "Time Remain: %0.2f", data.timeremain); + upsdebugx(5, "Battery Mode: %s", data.s_battery_mode ? "true" : "false"); + upsdebugx(5, "Battery Low: %s", data.s_battery_low ? "true" : "false"); + upsdebugx(5, "Network Failure: %s", data.s_network_failure ? "true" : "false"); + upsdebugx(5, "Fast Network Failure: %s", data.s_fast_network_failure ? "true" : "false"); + upsdebugx(5, "220 In: %s", data.s_220_in ? "true" : "false"); + upsdebugx(5, "220 Out: %s", data.s_220_out ? "true" : "false"); + upsdebugx(5, "Bypass On: %s", data.s_bypass_on ? "true" : "false"); + upsdebugx(5, "Charger On: %s", data.s_charger_on ? "true" : "false"); + upsdebugx(5, "Checksum: %u", data.checksum); + upsdebugx(5, "Checksum Calc: %u", data.checksum_calc); + upsdebugx(5, "Checksum OK: %s", data.checksum_ok ? "true" : "false"); + upsdebugx(5, "End Marker: %u", data.end_marker); } /* FIXME: Replace with NUT ser_open() and ser_set_speed() */ @@ -617,9 +621,11 @@ static void pdatapacket(unsigned char * datapkt, int size) { return; if (datapkt != NULL) { - upsdebugx(1, "Received Datapacket: "); + /* FIXME: convert to upsdebug_hex()? */ + upsdebugx(1, "%s: logging received data packet bytes at debug verbosity 5 or more", __func__); + for (i = 0; i < size; i++) { - upsdebugx(1, "\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapkt[i], datapkt[i], datapkt[i]); + upsdebugx(5, "\tPosition %d -- 0x%02X -- Decimal %d -- Char %c", i, datapkt[i], datapkt[i], datapkt[i]); } } } @@ -921,7 +927,7 @@ static int write_serial_int(int fd, const unsigned int * data, int size) { message = xcalloc(size, sizeof(uint8_t)); for (i = 0; i < size; i++) { message[i] = (uint8_t)data[i]; - /* //upsdebugx(1, "%d %c %u %d %c %u", message[i], message[i], data[i], data[i]); */ + /* //upsdebugx(5, "%d %c %u %d %c %u", message[i], message[i], data[i], data[i]); */ } bytes_written = write(fd, message, size); free(message); From 3c6df5b6a9a0c0a944f472cc44140a838164ae07 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 02:20:21 +0000 Subject: [PATCH 55/60] drivers/nhs_ser.c: keep debug log of main milestones and errors at verbosity 1, add __func__ [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index 0c2fd42fdf..d7fbb288c0 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -522,17 +522,17 @@ static int openfd(const char * portarg, int BAUDRATE) { int fd = open(portarg, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { - upsdebugx(1, "Error on open %s", portarg); + upsdebugx(1, "%s: Error on open %s", __func__, portarg); return -1; } if (tcflush(fd, TCIOFLUSH) != 0) { - upsdebugx(1, "Error on flush data on %s", portarg); + upsdebugx(1, "%s: Error on flush data on %s", __func__, portarg); return -1; } if (tcgetattr(fd, &tty) != 0) { - upsdebugx(1, "Error on set termios values to %s", portarg); + upsdebugx(1, "%s: Error on set termios values to %s", __func__, portarg); close(fd); return -1; } @@ -545,7 +545,10 @@ static int openfd(const char * portarg, int BAUDRATE) { while ((i < NUM_BAUD_RATES) && (done == 0)) { if (baud_rates[i].speed == BAUDRATE) { done = baud_rates[i].rate; - upsdebugx(1, "Baud selecionado: %d -- %s", baud_rates[i].speed, baud_rates[i].description); + upsdebugx(1, "%s: Baud rate selected by user: %d -- %s", + __func__, + baud_rates[i].speed, + baud_rates[i].description); } i++; } @@ -555,7 +558,10 @@ static int openfd(const char * portarg, int BAUDRATE) { while ((i < NUM_BAUD_RATES) && (done == 0)) { if (baud_rates[i].speed == DEFAULTBAUD) { done = baud_rates[i].rate; - upsdebugx(1, "Baud selecionado: %d -- %s", baud_rates[i].speed, baud_rates[i].description); + upsdebugx(1, "%s: Baud rate selected by default: %d -- %s", + __func__, + baud_rates[i].speed, + baud_rates[i].description); } i++; } @@ -563,7 +569,7 @@ static int openfd(const char * portarg, int BAUDRATE) { /* Wrong macro? */ if (done == 0) { - upsdebugx(1, "Baud rate not found, using default %d", DEFAULTBAUD); + upsdebugx(1, "%s: Baud rate not found, using default %d", __func__, DEFAULTBAUD); done = B2400; } @@ -598,7 +604,7 @@ static int openfd(const char * portarg, int BAUDRATE) { cfsetospeed(&tty, done); if (tcsetattr(fd, TCSANOW, &tty) != 0) { - upsdebugx(1, "Error on tcsetattr on port %s", portarg); + upsdebugx(1, "%s: Error on tcsetattr on port %s", __func__, portarg); close(fd); return -1; } @@ -1653,9 +1659,12 @@ static float get_vin_perc(char * var) { void upsdrv_initinfo(void) { char *b = getval("baud"); - upsdebugx(1, "Port is %s and baud_rate is %s", device_path, b); - baudrate = DEFAULTBAUD; upsdebugx(3, "%s: starting...", __func__); + + baudrate = DEFAULTBAUD; + + upsdebugx(1, "%s: Port is %s and baud_rate is %s", __func__, device_path, b); + if (b) baudrate = atoi(b); if (device_path) { @@ -1667,7 +1676,7 @@ void upsdrv_initinfo(void) { if (serial_fd == -1) fatalx(EXIT_FAILURE, "Unable to open port %s with baud %d", porta, baudrate); else { - upsdebugx(1, "Communication started on port %s, baud rate %d. Calling updateinfo()", porta, baudrate); + upsdebugx(1, "%s: Communication started on port %s, baud rate %d. Calling updateinfo()", __func__, porta, baudrate); } } else @@ -1719,10 +1728,10 @@ void upsdrv_updateinfo(void) { upsdebugx(3, "%s: starting...", __func__); if ((serial_fd <= 0) && (i < retries)) { - upsdebugx(1, "Serial problem..."); + upsdebugx(1, "%s: Serial port communications problem", __func__); while (serial_fd <= 0) { serial_fd = openfd(porta, baudrate); - upsdebugx(1, "Trying to reopen serial..."); + upsdebugx(1, "%s: Trying to reopen serial...", __func__); usleep(checktime); retries++; } @@ -2162,12 +2171,12 @@ void upsdrv_updateinfo(void) { } /* end else */ } /* end else */ if (bwritten < 0) { - upsdebugx(1, "Problem to write data to %s", porta); + upsdebugx(1, "%s: Problem to write data to %s", __func__, porta); if (bwritten == -1) { - upsdebugx(1, "Data problem"); + upsdebugx(1, "%s: Data problem", __func__); } if (bwritten == -2) { - upsdebugx(1, "Flush problem"); + upsdebugx(1, "%s: Flush problem", __func__); } close(serial_fd); serial_fd = -1; From c3758637c2652150ab35ce50d2995755036d4537 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 02:21:12 +0000 Subject: [PATCH 56/60] drivers/nhs_ser.c: hide upsdrv_updateinfo() debug log of processing at verbosity 3-4_ [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index d7fbb288c0..a88edc7744 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -1752,7 +1752,7 @@ void upsdrv_updateinfo(void) { datapacket_index++; if (chr == 0xFE) { /* DataPacket */ time_t now = time(NULL); - upsdebugx(1, "DATAPACKET INDEX IS %d", datapacket_index); + upsdebugx(4, "DATAPACKET INDEX IS %d", datapacket_index); if (lastdp != 0) { tempodecorrido = difftime(now, lastdp); } @@ -1774,17 +1774,17 @@ void upsdrv_updateinfo(void) { datapacketstart = false; if (lastpktdata.checksum_ok) { /* checksum is OK, then use it to set values */ - upsdebugx(1, "Data Packet seems be OK"); + upsdebugx(4, "Data Packet seems be OK"); if (lastpkthwinfo.size == 0) - upsdebugx(1, "Pkt HWINFO is not OK. See if will be requested next time!"); + upsdebugx(2, "Pkt HWINFO is not OK. See if will be requested next time!"); else { if (lastpkthwinfo.checksum_ok) { - upsdebugx(1, "Pkt HWINFO is OK. Model is %d, hwversion is %d and swversion is %d", lastpkthwinfo.model, lastpkthwinfo.hardwareversion, lastpkthwinfo.softwareversion); + upsdebugx(4, "Pkt HWINFO is OK. Model is %d, hwversion is %d and swversion is %d", lastpkthwinfo.model, lastpkthwinfo.hardwareversion, lastpkthwinfo.softwareversion); /* We need to set data on NUT with data * that I believe that I can calculate. * Now setting data on NUT */ ups = getupsinfo(lastpkthwinfo.model); - upsdebugx(1, "UPS Struct data: Code %d Model %s VA %d", ups.upscode, ups.upsdesc, ups.VA); + upsdebugx(4, "UPS Struct data: Code %d Model %s VA %d", ups.upscode, ups.upsdesc, ups.VA); dstate_setinfo("device.model", "%s", ups.upsdesc); dstate_setinfo("device.mfr", "%s", MANUFACTURER); dstate_setinfo("device.serial", "%s", lastpkthwinfo.serial); @@ -1810,22 +1810,22 @@ void upsdrv_updateinfo(void) { /* Decision Chain commented below */ /* First we check if system is on battery or not */ - upsdebugx(1, "Set UPS status as OFF and start checking. s_battery_mode is %d", lastpktdata.s_battery_mode); + upsdebugx(4, "Set UPS status as OFF and start checking. s_battery_mode is %d", lastpktdata.s_battery_mode); if (lastpkthwinfo.s_220V_in) { - upsdebugx(1, "I'm on 220v IN!. My overvoltage is %d", lastpkthwinfo.undervoltagein220V); + upsdebugx(4, "I'm on 220v IN!. My overvoltage is %d", lastpkthwinfo.undervoltagein220V); min_input_power = lastpkthwinfo.undervoltagein220V; } else { - upsdebugx(1, "I'm on 120v IN!. My overvoltage is %d", lastpkthwinfo.undervoltagein120V); + upsdebugx(4, "I'm on 120v IN!. My overvoltage is %d", lastpkthwinfo.undervoltagein120V); min_input_power = lastpkthwinfo.undervoltagein120V; } if (lastpktdata.s_battery_mode) { /* ON BATTERY */ - upsdebugx(1, "UPS is on Battery Mode"); + upsdebugx(4, "UPS is on Battery Mode"); dstate_setinfo("ups.status", "%s", "OB"); if (lastpktdata.s_battery_low) { /* If battery is LOW, warn user! */ - upsdebugx(1, "UPS is on Battery Mode and in Low Battery State"); + upsdebugx(4, "UPS is on Battery Mode and in Low Battery State"); dstate_setinfo("ups.status", "%s", "LB"); } /* end if */ } /* end if */ @@ -1833,7 +1833,7 @@ void upsdrv_updateinfo(void) { /* Check if MAINS (power) is not preset. * Well, we can check pkt_data.s_network_failure too... */ if ((lastpktdata.vacinrms <= min_input_power) || (lastpktdata.s_network_failure)) { - upsdebugx(1, "UPS has power-in value %0.2f " + upsdebugx(4, "UPS has power-in value %0.2f " "and min_input_power is %d, " "or network is in failure. Network failure is %d", lastpktdata.vacinrms, @@ -1847,18 +1847,18 @@ void upsdrv_updateinfo(void) { * If MAINS is less than or equal to min_input_power, * then the UPS goes to BATTERY */ if (lastpktdata.vacinrms > min_input_power) { - upsdebugx(1, "UPS is on MAINS"); + upsdebugx(4, "UPS is on MAINS"); if (lastpktdata.s_charger_on) { - upsdebugx(1, "UPS Charging..."); + upsdebugx(4, "UPS Charging..."); dstate_setinfo("ups.status", "%s", "CHRG"); } else { if ((lastpktdata.s_network_failure) || (lastpktdata.s_fast_network_failure)) { - upsdebugx(1, "UPS is on battery mode because network failure or fast network failure"); + upsdebugx(4, "UPS is on battery mode because network failure or fast network failure"); dstate_setinfo("ups.status", "%s", "OB"); } /* end if */ else { - upsdebugx(1, "All is OK. UPS is on ONLINE!"); + upsdebugx(4, "All is OK. UPS is on ONLINE!"); dstate_setinfo("ups.status", "%s", "OL"); } /* end else */ } /* end else */ @@ -1880,7 +1880,7 @@ void upsdrv_updateinfo(void) { if (numbat == 0) numbat = lastpkthwinfo.numbatteries; else - upsdebugx(1, "Number of batteries is set to %d", numbat); + upsdebugx(4, "Number of batteries is set to %d", numbat); vbat = get_vbat(); ah = get_ah(); @@ -2135,7 +2135,7 @@ void upsdrv_updateinfo(void) { dstate_dataok(); } /* end if */ else - upsdebugx(1, "Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request..."); + upsdebugx(4, "Checksum of pkt_hwinfo is corrupted or not initialized. Waiting for new request..."); } /* end else */ } /* end if */ } /* end if */ @@ -2148,25 +2148,25 @@ void upsdrv_updateinfo(void) { * FIXME: move (semi)static info discovery to upsdrv_initinfo() or so */ if (!lastpkthwinfo.checksum_ok) { - upsdebugx(1, "pkt_hwinfo loss -- Requesting"); + upsdebugx(4, "pkt_hwinfo loss -- Requesting"); /* If size == 0, packet maybe not initizated, * then send an initialization packet to obtain data. * Send two times the extended initialization string, * but, on fail, try randomly send extended or normal. */ if (send_extended < 6) { - upsdebugx(1, "Sending extended initialization packet. Try %d", send_extended+1); + upsdebugx(4, "Sending extended initialization packet. Try %d", send_extended+1); bwritten = write_serial_int(serial_fd, string_initialization_long, 9); send_extended++; } /* end if */ else { /* randomly send */ if (rand() % 2 == 0) { - upsdebugx(1, "Sending long initialization packet"); + upsdebugx(4, "Sending long initialization packet"); bwritten = write_serial_int(serial_fd, string_initialization_long, 9); } /* end if */ else { - upsdebugx(1, "Sending short initialization packet"); + upsdebugx(4, "Sending short initialization packet"); bwritten = write_serial_int(serial_fd, string_initialization_short, 9); } /* end else */ } /* end else */ @@ -2185,7 +2185,7 @@ void upsdrv_updateinfo(void) { if (checktime > max_checktime) checktime = max_checktime; else { - upsdebugx(1, "Increase checktime to %d", checktime + 100000); + upsdebugx(3, "Increase checktime to %d", checktime + 100000); checktime = checktime + 100000; } usleep(checktime); From c857014d62c7e0a4a5c4675d78294386e1be0bb0 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Fri, 29 Nov 2024 04:05:02 +0000 Subject: [PATCH 57/60] configure.ac, drivers/Makefile.am, docs/man/Makefile.am, docs/man/nhs_ser.txt, NEWS.adoc: temporarily constrain nhs_ser to Linux-only NUT builds [#2692] Signed-off-by: Jim Klimov --- NEWS.adoc | 2 +- configure.ac | 4 ++++ docs/man/Makefile.am | 24 +++++++++++++++++++++--- docs/man/nhs_ser.txt | 3 +++ docs/nut.dict | 3 ++- drivers/Makefile.am | 6 +++++- 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index 429b137863..b1ebfb1d9f 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -151,7 +151,7 @@ https://github.com/networkupstools/nut/milestone/11 - nhs_ser: added new driver for numerous NHS Nobreaks, senoidal line -- UPS models with serial port, made by NHS Sistemas Eletronicos LTDA and popular - in Brazil. [#2692] + in Brazil. Currently this driver only builds on Linux. [#2692] - usbhid-ups updates: * Support of the `onlinedischarge_log_throttle_hovercharge` in the NUT diff --git a/configure.ac b/configure.ac index 699370b1ce..f69bce4b19 100644 --- a/configure.ac +++ b/configure.ac @@ -795,6 +795,10 @@ CODE_TIMEINCL=" #endif " +dnl TEMPORARY to allow certain linux-only buildable drivers +AC_CHECK_HEADERS_ONCE([linux/serial.h]) +AM_CONDITIONAL(HAVE_LINUX_SERIAL_H, test x"${ac_cv_header_linux_serial_h}" = xyes) + AC_CHECK_HEADERS_ONCE([fcntl.h sys/stat.h sys/socket.h netdb.h]) AC_CHECK_FUNCS(flock lockf fcvt fcvtl dup dup2 abs_val abs) diff --git a/docs/man/Makefile.am b/docs/man/Makefile.am index 53c2eb0413..eaa80fb5ab 100644 --- a/docs/man/Makefile.am +++ b/docs/man/Makefile.am @@ -512,7 +512,6 @@ SRC_SERIAL_PAGES = \ powerpanel.txt \ rhino.txt \ riello_ser.txt \ - nhs_ser.txt \ sms_ser.txt \ safenet.txt \ solis.txt \ @@ -522,6 +521,12 @@ SRC_SERIAL_PAGES = \ victronups.txt \ apcupsd-ups.txt +if HAVE_LINUX_SERIAL_H +# Temporary, until ported to more OSes +SRC_SERIAL_PAGES += \ + nhs_ser.txt +endif HAVE_LINUX_SERIAL_H + if ! SOME_DRIVERS if WITH_MANS MAN_SERIAL_PAGES = \ @@ -562,7 +567,6 @@ MAN_SERIAL_PAGES = \ powerpanel.8 \ rhino.8 \ riello_ser.8 \ - nhs_ser.8 \ sms_ser.8 \ safenet.8 \ solis.8 \ @@ -571,8 +575,16 @@ MAN_SERIAL_PAGES = \ upscode2.8 \ victronups.8 \ apcupsd-ups.8 + +if HAVE_LINUX_SERIAL_H +# Temporary, until ported to more OSes +MAN_SERIAL_PAGES += \ + nhs_ser.8 +endif HAVE_LINUX_SERIAL_H + endif WITH_MANS + if WITH_SERIAL man8_MANS += $(MAN_SERIAL_PAGES) endif WITH_SERIAL @@ -615,7 +627,6 @@ HTML_SERIAL_MANS = \ powerpanel.html \ rhino.html \ riello_ser.html \ - nhs_ser.html \ sms_ser.html \ safenet.html \ solis.html \ @@ -624,6 +635,13 @@ HTML_SERIAL_MANS = \ upscode2.html \ victronups.html \ apcupsd-ups.html + +if HAVE_LINUX_SERIAL_H +# Temporary, until ported to more OSes +HTML_SERIAL_MANS += \ + nhs_ser.html +endif HAVE_LINUX_SERIAL_H + endif ! SOME_DRIVERS # (--with-snmp) diff --git a/docs/man/nhs_ser.txt b/docs/man/nhs_ser.txt index c87627d9a0..b998906361 100644 --- a/docs/man/nhs_ser.txt +++ b/docs/man/nhs_ser.txt @@ -23,6 +23,9 @@ SUPPORTED HARDWARE *nhs_ser* supports numerous UPS models made by NHS Sistemas Eletronicos LTDA and marketed in Brazil. They feature a serial port and a binary wire protocol. +NOTE: Currently this driver only builds on Linux. This is expected to change +in future revisions of the code. + EXTRA ARGUMENTS --------------- diff --git a/docs/nut.dict b/docs/nut.dict index f31f67b641..17ac8e6783 100644 --- a/docs/nut.dict +++ b/docs/nut.dict @@ -1,4 +1,4 @@ -personal_ws-1.1 en 3256 utf-8 +personal_ws-1.1 en 3257 utf-8 AAC AAS ABI @@ -2051,6 +2051,7 @@ huawei hudson hunnox hwdb +hwinfo hwmon hwmonX hypervisor diff --git a/drivers/Makefile.am b/drivers/Makefile.am index bfa2638954..91cb8ff717 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -55,9 +55,13 @@ NUTSW_DRIVERLIST = dummy-ups clone clone-outlet apcupsd-ups skel SERIAL_DRIVERLIST = al175 bcmxcp belkin belkinunv bestfcom \ bestfortress bestuferrups bestups etapro everups \ gamatronic genericups isbmex liebert liebert-esp2 liebert-gxe masterguard metasys \ - mge-utalk microdowell microsol-apc mge-shut nhs_ser oneac optiups powercom rhino \ + mge-utalk microdowell microsol-apc mge-shut oneac optiups powercom rhino \ safenet nutdrv_siemens-sitop solis tripplite tripplitesu upscode2 victronups powerpanel \ blazer_ser ivtscd apcsmart apcsmart-old riello_ser sms_ser bicker_ser +if HAVE_LINUX_SERIAL_H +# Temporary, until ported to more OSes +SERIAL_DRIVERLIST += nhs_ser +endif HAVE_LINUX_SERIAL_H SNMP_DRIVERLIST = snmp-ups USB_LIBUSB_DRIVERLIST = usbhid-ups bcmxcp_usb tripplite_usb \ blazer_usb richcomm_usb riello_usb \ From 112dca3f660c15e501e60aebce56f5eceaf50501 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 30 Nov 2024 18:02:45 +0100 Subject: [PATCH 58/60] drivers/nhs_ser.c: populate missed explicit method parameter [#2692] Signed-off-by: Jim Klimov --- drivers/nhs_ser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nhs_ser.c b/drivers/nhs_ser.c index a88edc7744..30d181b079 100644 --- a/drivers/nhs_ser.c +++ b/drivers/nhs_ser.c @@ -642,7 +642,7 @@ static float createfloat(int integer, int decimal) { return atof(flt); } -static unsigned int get_vbat() { +static unsigned int get_vbat(void) { char *v = getval("vbat"); if (v) { return atoi(v); From 30e4ea69d02fb1ef3137a19f26292ea5f8b3cfce Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Mon, 2 Dec 2024 09:45:56 -0500 Subject: [PATCH 59/60] core ipc: Handle select returning EINTR Signed-off-by: Greg Troxel --- include/nutipc.hpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/include/nutipc.hpp b/include/nutipc.hpp index 56618d6200..6cc29e67c7 100644 --- a/include/nutipc.hpp +++ b/include/nutipc.hpp @@ -600,13 +600,22 @@ void * Signal::HandlerThread::main(void * comm_pipe_read_end) { FD_SET(rfd, &rfds); // Poll on signal pipe - // Note that direct blocking read could be also used; - // however, select allows timeout specification - // which might come handy... + // Note that a straightforward blocking read could be + // also used. However, select allows specifying a + // timeout, which could be useful in the future (but + // is not used in the current code). int fdno = ::select(FD_SETSIZE, &rfds, nullptr, nullptr, nullptr); - // TBD: Die or recover on error? + // -1 is an error, but EINTR means the system call was + // interrupted. System calls are expected to be + // interrupted on signal delivery; some systems + // restart them, and some don't. Getting EINTR is + // therefore not actually an error, and the standard + // approach is to retry. if (-1 == fdno) { + if (errno == EINTR) + continue; + std::stringstream e; e << "Poll on communication pipe read end "; @@ -633,6 +642,12 @@ void * Signal::HandlerThread::main(void * comm_pipe_read_end) { throw std::runtime_error(e.str()); } + // POSIX probably does not prohibit reading some but + // not all of the multibyte message. However, it is + // unlikely that an implementation using write and + // read on int-sized or smaller objects will split + // them. For now our strategy is to hope this does + // not happen. assert(sizeof(word) == read_out); command_t command = static_cast(word); From 9d0c2e89c8f845d3f57f8208a247db081eb66a1c Mon Sep 17 00:00:00 2001 From: Greg Troxel Date: Mon, 2 Dec 2024 09:46:14 -0500 Subject: [PATCH 60/60] tests: Do not expect signals to be messages POSIX does not require 1:1 delivery per kill() call. Adjust the test to not require behavior that 1) POSIX does not require and 2) is only probabalistically observed to happen, even if "most of the time". Signed-off-by: Greg Troxel --- tests/nutipc_ut.cpp | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/tests/nutipc_ut.cpp b/tests/nutipc_ut.cpp index 16bfce9696..bdfaf01d91 100644 --- a/tests/nutipc_ut.cpp +++ b/tests/nutipc_ut.cpp @@ -226,6 +226,7 @@ class TestSignalHandler: public nut::Signal::Handler { virtual ~TestSignalHandler() override; }; // end of class TestSignalHandler +// \todo Describe the point of this test. void NutIPCUnitTest::testSignalRecvQuick() { #ifdef WIN32 /* FIXME: Needs implementation for signals via pipes */ @@ -242,22 +243,52 @@ void NutIPCUnitTest::testSignalRecvQuick() { pid_t my_pid = nut::Process::getPID(); - /* NOTE: The signal order delivery is not specified by POSIX if several - * ones arrive nearly simultaneously (and/or get confused by multi-CPU - * routing). In this test we only verify that after sending several copies - * of several signals, the expected counts of events were received. + /* + * POSIX does not require signals to be delivered in order. + * It does not require that signals are like messages, but + * rather views them as a software version of hardware + * interrupts. Two sent signals might result in only one + * handler invocation. However, we (and most other signal + * users) expect that signals are usually in order and usually + * relatively promptly. + * + * For now, insist on beyond-POSIX behavior, as a canary that + * if triggered, we should examine nut's use of signals. */ + + /* Send two signals, and pause briefly to allow delivery. */ CPPUNIT_ASSERT(0 == nut::Signal::send(nut::Signal::USER1, my_pid)); CPPUNIT_ASSERT(0 == nut::Signal::send(nut::Signal::USER2, my_pid)); + ::sleep(1); + + /* Send two signals in the other order, and again pause briefly. */ CPPUNIT_ASSERT(0 == nut::Signal::send(nut::Signal::USER2, my_pid)); CPPUNIT_ASSERT(0 == nut::Signal::send(nut::Signal::USER1, my_pid)); + ::sleep(1); + + /* Send a single signal. */ CPPUNIT_ASSERT(0 == nut::Signal::send(nut::Signal::USER1, my_pid)); - // Let the sig. handler thread finish... + /* + * Sleep 1s, assuming that is long enough for all signals to + * be delivered (really, the last one) and the handler to have + * run to completion. + */ ::sleep(1); + /* + * Check that all 5 sent were received. Note that strictly, + * an OS on which USER1 and USER2 are each received once is + * not a failure to conform. But a delay of 1s in signal + * delivery would generally be seen as not ok. + */ CPPUNIT_ASSERT(caught_signals.size() == 5); + /* + * Loop over the received signal records. Count the number of + * USER1 and USER2, and assert that no signals other than + * those two were received. + */ int countUSER1 = 0; int countUSER2 = 0; while (!caught_signals.empty()) { @@ -275,6 +306,7 @@ void NutIPCUnitTest::testSignalRecvQuick() { } } + /* Check that received count matches sent count from code above. */ CPPUNIT_ASSERT(countUSER1 == 3); CPPUNIT_ASSERT(countUSER2 == 2); #endif /* WIN32 */