From 27ed068d3d9482b0ab3e5f9949ae2adb0cb76788 Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Mon, 23 Aug 2021 14:38:08 +0200 Subject: [PATCH] snmp-ups: Add a generic function to convert date This provides conversion from US date (mm/dd/yyyy) to ISO Calendar date (yyyy-mm-dd). Also adapt the function callback mechanism to make it more generic, and only char* to char* reformating, beside from the int to char* value lookup. Signed-off-by: Arnaud Quette --- drivers/eaton-pdu-marlin-mib.c | 3 +- drivers/powerware-mib.c | 6 ++-- drivers/snmp-ups.c | 64 ++++++++++++++++++++++++++++++---- drivers/snmp-ups.h | 9 +++-- 4 files changed, 69 insertions(+), 13 deletions(-) diff --git a/drivers/eaton-pdu-marlin-mib.c b/drivers/eaton-pdu-marlin-mib.c index cd691283c5..9d1d12c4dd 100644 --- a/drivers/eaton-pdu-marlin-mib.c +++ b/drivers/eaton-pdu-marlin-mib.c @@ -198,8 +198,9 @@ static char marlin_scratch_buf[20]; * WRT the number of phase(s) and the outlet group number. * Note that the group type (marlin_outlet_group_type_info) is * not considered since this applies to any kind of group */ -static const char *marlin_outlet_group_phase_fun(int outlet_group_nb) +static const char *marlin_outlet_group_phase_fun(void *raw_outlet_group_nb) { + int outlet_group_nb = *((int *)raw_outlet_group_nb); const char* str_phases_nb = dstate_getinfo("input.phases"); int phases_nb = 1; if (str_phases_nb && (outlet_group_nb >= 0) ) { diff --git a/drivers/powerware-mib.c b/drivers/powerware-mib.c index 2c23354887..c99b8e2906 100644 --- a/drivers/powerware-mib.c +++ b/drivers/powerware-mib.c @@ -4,7 +4,7 @@ * Copyright (C) * 2005-2006 Olli Savia * 2005-2006 Niels Baggesen - * 2015-2016 Arnaud Quette + * 2015-2021 Eaton (author: Arnaud Quette ) * * 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 @@ -25,7 +25,7 @@ #include "powerware-mib.h" -#define PW_MIB_VERSION "0.92" +#define PW_MIB_VERSION "0.93" /* TODO: more sysOID and MIBs support: * @@ -254,7 +254,7 @@ static snmp_info_t pw_mib[] = { 0, NULL }, { "battery.runtime.low", 0, 60.0, IETF_OID_CONF_RUNTIME_LOW, "", 0, NULL }, - { "battery.date", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.1.2.6.0", NULL, SU_FLAG_OK, NULL }, + { "battery.date", ST_FLAG_RW | ST_FLAG_STRING, SU_INFOSIZE, ".1.3.6.1.4.1.534.1.2.6.0", NULL, SU_FLAG_OK, &su_convert_to_iso_date_info[0] }, /* Output page */ { "output.phases", 0, 1.0, PW_OID_OUT_LINES, "", 0, NULL }, diff --git a/drivers/snmp-ups.c b/drivers/snmp-ups.c index 0fe6f1a291..7678c680d0 100644 --- a/drivers/snmp-ups.c +++ b/drivers/snmp-ups.c @@ -150,7 +150,7 @@ static const char *mibname; static const char *mibvers; #define DRIVER_NAME "Generic SNMP UPS driver" -#define DRIVER_VERSION "1.15" +#define DRIVER_VERSION "1.16" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -187,6 +187,36 @@ bool_t get_and_process_data(int mode, snmp_info_t *su_info_p); int extract_template_number(int template_type, const char* varname); int get_template_type(const char* varname); +/* common value post-processing functions */ + +static char su_scratch_buf[255]; + +/* Convert a US formated date (mm/dd/yyyy) to an ISO 8601 Calendar date (yyyy-mm-dd) */ +const char *su_usdate_to_isodate_info_fun(void *raw_date) +{ + const char *usdate = (char *)raw_date; + struct tm tm; + memset(&tm, 0, sizeof(struct tm)); + memset(&su_scratch_buf, 0, sizeof(su_scratch_buf)); + + upsdebugx(3, "%s: US date = %s", __func__, usdate); + + /* Try to convert from US date string to time */ + /* Note strptime returns NULL upon failure, and a ptr to the last + null char of the string upon success. Just try blindly the conversion! */ + strptime(usdate, "%m/%d/%Y", &tm); + if (strftime(su_scratch_buf, 254, "%F", &tm) != 0) { + upsdebugx(3, "%s: successfully reformated: %s", __func__, su_scratch_buf); + return su_scratch_buf; + } + + return NULL; +} +info_lkp_t su_convert_to_iso_date_info[] = { + { 1, "dummy", su_usdate_to_isodate_info_fun, NULL }, + { 0, NULL, NULL, NULL } +}; + /* --------------------------------------------- * driver functions implementations * --------------------------------------------- */ @@ -840,7 +870,7 @@ static bool_t decode_str(struct snmp_pdu *pdu, char *buf, size_t buf_len, info_l case ASN_GAUGE: if(oid2info) { const char *str; - if((str=su_find_infoval(oid2info, *pdu->variables->val.integer))) { + if((str=su_find_infoval(oid2info, pdu->variables->val.integer))) { strncpy(buf, str, buf_len-1); } /* when oid2info returns NULL, don't publish the variable! */ @@ -1215,7 +1245,7 @@ void su_status_set(snmp_info_t *su_info_p, long value) upsdebugx(2, "SNMP UPS driver: entering %s()", __func__); - if ((info_value = su_find_infoval(su_info_p->oid2info, value)) != NULL) + if ((info_value = su_find_infoval(su_info_p->oid2info, &value)) != NULL) { if (strcmp(info_value, "")) { status_set(info_value); @@ -1246,7 +1276,7 @@ void su_alarm_set(snmp_info_t *su_info_p, long value) upsdebugx(2, "%s: using definition %s", __func__, info_type); - if ((info_value = su_find_infoval(su_info_p->oid2info, value)) != NULL + if ((info_value = su_find_infoval(su_info_p->oid2info, &value)) != NULL && info_value[0] != 0) { /* Special handling for outlet & outlet groups alarms */ @@ -1529,15 +1559,30 @@ long su_find_valinfo(info_lkp_t *oid2info, const char* value) return -1; } +/* String reformating function */ +const char *su_find_strval(info_lkp_t *oid2info, void *value) +{ + /* First test if we have a generic lookup function */ + if ( (oid2info != NULL) && (oid2info->fun != NULL) ) { + upsdebugx(2, "%s: using generic lookup function (string reformating)", __func__); + const char * retvalue = oid2info->fun(value); + upsdebugx(2, "%s: got value '%s'", __func__, retvalue); + return retvalue; + } + upsdebugx(1, "%s: no result value for this OID string value (%s)", __func__, (char*)value); + return NULL; +} + /* find the INFO_* value matching that OID value */ -const char *su_find_infoval(info_lkp_t *oid2info, long value) +const char *su_find_infoval(info_lkp_t *oid2info, void *raw_value) { info_lkp_t *info_lkp; + long value = *((long *)raw_value); /* First test if we have a generic lookup function */ if ( (oid2info != NULL) && (oid2info->fun != NULL) ) { upsdebugx(2, "%s: using generic lookup function", __func__); - const char * retvalue = oid2info->fun(value); + const char * retvalue = oid2info->fun(raw_value); upsdebugx(2, "%s: got value '%s'", __func__, retvalue); return retvalue; } @@ -2712,6 +2757,11 @@ bool_t su_ups_get(snmp_info_t *su_info_p) snprintf(buf, sizeof(buf), "%.2f", tmp_dvalue); } } + /* Check if there is a string reformating function */ + const char *fmt_buf = NULL; + if ((fmt_buf = su_find_strval(su_info_p->oid2info, buf)) != NULL) { + snprintf(buf, sizeof(buf), "%s", fmt_buf); + } } } else { status = nut_snmp_get_int(su_info_p->OID, &value); @@ -2727,7 +2777,7 @@ bool_t su_ups_get(snmp_info_t *su_info_p) return FALSE; } /* Check if there is a value to be looked up */ - if ((strValue = su_find_infoval(su_info_p->oid2info, value)) != NULL) + if ((strValue = su_find_infoval(su_info_p->oid2info, &value)) != NULL) snprintf(buf, sizeof(buf), "%s", strValue); else { /* Check if there is a need to publish decimal too, diff --git a/drivers/snmp-ups.h b/drivers/snmp-ups.h index f6a6ee51fb..900288a639 100644 --- a/drivers/snmp-ups.h +++ b/drivers/snmp-ups.h @@ -107,7 +107,7 @@ typedef int bool_t; typedef struct { int oid_value; /* SNMP OID value */ const char *info_value; /* NUT INFO_* value */ - const char *(*fun)(int snmp_value); /* optional SNMP to NUT mapping function */ + const char *(*fun)(void *snmp_value); /* optional SNMP to NUT mapping function */ int (*nuf)(const char *nut_value); /* optional NUT to SNMP mapping function */ } info_lkp_t; @@ -271,8 +271,13 @@ bool_t su_ups_get(snmp_info_t *su_info_p); bool_t load_mib2nut(const char *mib); -const char *su_find_infoval(info_lkp_t *oid2info, long value); +const char *su_find_infoval(info_lkp_t *oid2info, void *value); long su_find_valinfo(info_lkp_t *oid2info, const char* value); +const char *su_find_strval(info_lkp_t *oid2info, void *value); + +/* Common conversion structs (functions) */ +const char *su_usdate_to_isodate_info_fun(void *raw_date); +extern info_lkp_t su_convert_to_iso_date_info[]; int su_setvar(const char *varname, const char *val); int su_instcmd(const char *cmdname, const char *extradata);