Skip to content

Commit 50ec847

Browse files
committed
apc_modbus: Add outlet group timers
Values of SOG[0..2].TurnOffCountdown_EN for easier diagnostics. Signed-off-by: Axel Gembe <axel@gembe.net>
1 parent d17abdc commit 50ec847

2 files changed

Lines changed: 52 additions & 6 deletions

File tree

NEWS.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ but the `nutshutdown` script would bail out quickly and quietly. [PR #3008]
180180

181181
- `apc_modbus` driver updates:
182182
* Fixed register range in a logging string.
183+
* Add outlet group timers.
183184

184185
- Introduced a new NUT driver named `meanwell_ntu` which provides support for
185186
the Mean Well NTU series hybrid inverter and UPS units. [PR #3206]

drivers/apc_modbus.c

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,42 @@ static int _apc_modbus_date_from_nut(const char *value, uint16_t *output, size_t
820820

821821
static apc_modbus_converter_t _apc_modbus_date_conversion = { _apc_modbus_date_to_nut, _apc_modbus_date_from_nut };
822822

823+
/*
824+
* Timer countdown conversion:
825+
* -1: NotActive - No countdown in progress
826+
* 0: CountdownExpired - Countdown has ended
827+
* 1-2147483647: Seconds remaining
828+
*/
829+
static int _apc_modbus_timer_to_nut(const apc_modbus_value_t *value, char *output, size_t output_len)
830+
{
831+
int res;
832+
833+
if (value == NULL || output == NULL || output_len == 0) {
834+
/* Invalid parameters */
835+
return 0;
836+
}
837+
838+
if (value->type != APC_VT_INT) {
839+
return 0;
840+
}
841+
842+
if (value->data.int_value == -1) {
843+
res = snprintf(output, output_len, "NotActive");
844+
} else if (value->data.int_value == 0) {
845+
res = snprintf(output, output_len, "CountdownExpired");
846+
} else {
847+
res = snprintf(output, output_len, "%" PRIi64, value->data.int_value);
848+
}
849+
850+
if (res < 0 || (size_t)res >= output_len) {
851+
return 0;
852+
}
853+
854+
return 1;
855+
}
856+
857+
static apc_modbus_converter_t _apc_modbus_timer_conversion = { _apc_modbus_timer_to_nut, NULL };
858+
823859
typedef struct {
824860
const char *nut_variable_name;
825861
size_t modbus_addr;
@@ -870,9 +906,18 @@ static apc_modbus_register_t apc_modbus_register_map_dynamic[] = {
870906
{ "experimental.output.energy", 145, 2, APC_VT_UINT, APC_VF_NONE, NULL, "%" PRIu64, 0, NULL },
871907
{ "input.voltage", 151, 1, APC_VT_UINT, APC_VF_NONE, &_apc_modbus_voltage_conversion, "%.2f", 6, NULL },
872908
{ "ups.efficiency", 154, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_efficiency_conversion, "%.1f", 7, NULL },
873-
{ "ups.timer.shutdown", 155, 1, APC_VT_INT, APC_VF_NONE, NULL, "%" PRIi64, 0, NULL },
874-
{ "ups.timer.start", 156, 1, APC_VT_INT, APC_VF_NONE, NULL, "%" PRIi64, 0, NULL },
875-
{ "ups.timer.reboot", 157, 2, APC_VT_INT, APC_VF_NONE, NULL, "%" PRIi64, 0, NULL },
909+
{ "ups.timer.shutdown", 155, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
910+
{ "ups.timer.start", 156, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
911+
{ "ups.timer.reboot", 157, 2, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
912+
{ "outlet.group.1.timer.shutdown", 159, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
913+
{ "outlet.group.1.timer.start", 160, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
914+
{ "outlet.group.1.timer.reboot", 161, 2, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
915+
{ "outlet.group.2.timer.shutdown", 163, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
916+
{ "outlet.group.2.timer.start", 164, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
917+
{ "outlet.group.2.timer.reboot", 165, 2, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
918+
{ "outlet.group.3.timer.shutdown", 167, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
919+
{ "outlet.group.3.timer.start", 168, 1, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
920+
{ "outlet.group.3.timer.reboot", 169, 2, APC_VT_INT, APC_VF_NONE, &_apc_modbus_timer_conversion, NULL, 0, NULL },
876921
{ NULL, 0, 0, APC_VT_INT, APC_VF_NONE, NULL, NULL, 0.0f, NULL }
877922
};
878923

@@ -1466,7 +1511,7 @@ void upsdrv_initinfo(void)
14661511

14671512
void upsdrv_updateinfo(void)
14681513
{
1469-
uint16_t regbuf[32];
1514+
uint16_t regbuf[44];
14701515
uint64_t value;
14711516

14721517
if (!is_open) {
@@ -1538,7 +1583,7 @@ void upsdrv_updateinfo(void)
15381583
}
15391584

15401585
/* Dynamic Data */
1541-
if (_apc_modbus_read_registers(modbus_ctx, 128, 32, regbuf)) {
1586+
if (_apc_modbus_read_registers(modbus_ctx, 128, 44, regbuf)) {
15421587
/* InputStatus_BF, 1 register */
15431588
_apc_modbus_to_uint64(&regbuf[22], 1, &value);
15441589
if (value & (1 << 5)) {
@@ -1548,7 +1593,7 @@ void upsdrv_updateinfo(void)
15481593
status_set("TRIM");
15491594
}
15501595

1551-
_apc_modbus_process_registers(apc_modbus_register_map_dynamic, regbuf, 32, 128);
1596+
_apc_modbus_process_registers(apc_modbus_register_map_dynamic, regbuf, 44, 128);
15521597
} else {
15531598
dstate_datastale();
15541599
return;

0 commit comments

Comments
 (0)