From f4126194bff17eaa0d7c70bfcff7c141b81a648a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Sat, 9 Apr 2022 09:19:21 +0300 Subject: [PATCH 1/6] inverter.cpp: Remove duplicated #include --- sources/inverter-cli/inverter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sources/inverter-cli/inverter.cpp b/sources/inverter-cli/inverter.cpp index 45711f4..cf8a872 100644 --- a/sources/inverter-cli/inverter.cpp +++ b/sources/inverter-cli/inverter.cpp @@ -6,7 +6,6 @@ #include "tools.h" #include "main.h" -#include #include cInverter::cInverter(std::string devicename, int qpiri, int qpiws, int qmod, int qpigs) { From c32e50965b44f4989206a532b1017cbd8b384938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Sat, 9 Apr 2022 11:54:16 +0300 Subject: [PATCH 2/6] inverter_poller: Add more commands for -r flag Accept the QPI, QID, QVFW, QVFW2, QFLAG, QBOOT, and QOPM commands. --- sources/inverter-cli/inverter.cpp | 4 ++-- sources/inverter-cli/inverter.h | 2 +- sources/inverter-cli/main.cpp | 19 ++++++++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/sources/inverter-cli/inverter.cpp b/sources/inverter-cli/inverter.cpp index cf8a872..407421f 100644 --- a/sources/inverter-cli/inverter.cpp +++ b/sources/inverter-cli/inverter.cpp @@ -202,9 +202,9 @@ void cInverter::poll() { } } -void cInverter::ExecuteCmd(const string cmd) { +void cInverter::ExecuteCmd(const string cmd, int replylen) { // Sending any command raw - if (query(cmd.data(), 7)) { + if (query(cmd.data(), replylen)) { m.lock(); strcpy(status2, (const char*)buf+1); m.unlock(); diff --git a/sources/inverter-cli/inverter.h b/sources/inverter-cli/inverter.h index 3501b6b..6b47c62 100644 --- a/sources/inverter-cli/inverter.h +++ b/sources/inverter-cli/inverter.h @@ -35,7 +35,7 @@ class cInverter { string *GetWarnings(); int GetMode(); - void ExecuteCmd(const std::string cmd); + void ExecuteCmd(const std::string cmd, int); }; #endif // ___INVERTER_H diff --git a/sources/inverter-cli/main.cpp b/sources/inverter-cli/main.cpp index 3632e7b..6cb2a58 100644 --- a/sources/inverter-cli/main.cpp +++ b/sources/inverter-cli/main.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -182,7 +183,23 @@ int main(int argc, char* argv[]) { // Logic to send 'raw commands' to the inverter.. if (!rawcmd.empty()) { - ups->ExecuteCmd(rawcmd); + int replylen; + if (!strcmp(rawcmd.c_str(), "QPI")) + replylen = 8; + else if (!strcmp(rawcmd.c_str(), "QID")) + replylen = 18; + else if (!strcmp(rawcmd.c_str(), "QVFW")) + replylen = 18; + else if (!strcmp(rawcmd.c_str(), "QVFW2")) + replylen = 19; + else if (!strcmp(rawcmd.c_str(), "QFLAG")) + replylen = 15; + else if (!strcmp(rawcmd.c_str(), "QBOOT")) + replylen = 5; + else if (!strcmp(rawcmd.c_str(), "QOPM")) + replylen = 6; + else replylen = 7; + ups->ExecuteCmd(rawcmd, replylen); // We're piggybacking off the qpri status response... printf("Reply: %s\n", ups->GetQpiriStatus()->c_str()); exit(0); From ba2374bba9f75b9bd7caa2faef93d32240b9d89f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Sun, 13 Mar 2022 14:46:40 +0200 Subject: [PATCH 3/6] inverter-cli/mail.cpp: align the implementation to the protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HS_MS_MSX protocol specification in the repository says for the QPIRI command value R is “Parallel max num”. On my system R returns 9, while the source code expected "-" in scanf(). This change alters the input of scanf() to accept any character in the position for R. Closes https://github.com/ned-kelly/docker-voltronic-homeassistant/issues/71 --- sources/inverter-cli/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sources/inverter-cli/main.cpp b/sources/inverter-cli/main.cpp index 6cb2a58..d5799f7 100644 --- a/sources/inverter-cli/main.cpp +++ b/sources/inverter-cli/main.cpp @@ -232,7 +232,9 @@ int main(int argc, char* argv[]) { // Parse and display values sscanf(reply1->c_str(), "%f %f %f %f %d %d %d %d %f %d %d %d %f %f %f %d %s", &voltage_grid, &freq_grid, &voltage_out, &freq_out, &load_va, &load_watt, &load_percent, &voltage_bus, &voltage_batt, &batt_charge_current, &batt_capacity, &temp_heatsink, &pv_input_current, &pv_input_voltage, &scc_voltage, &batt_discharge_current, &device_status); - sscanf(reply2->c_str(), "%f %f %f %f %f %d %d %f %f %f %f %f %d %d %d %d %d %d - %d %d %d %f", &grid_voltage_rating, &grid_current_rating, &out_voltage_rating, &out_freq_rating, &out_current_rating, &out_va_rating, &out_watt_rating, &batt_rating, &batt_recharge_voltage, &batt_under_voltage, &batt_bulk_voltage, &batt_float_voltage, &batt_type, &max_grid_charge_current, &max_charge_current, &in_voltage_range, &out_source_priority, &charger_source_priority, &machine_type, &topology, &out_mode, &batt_redischarge_voltage); + char parallel_max_num; + sscanf(reply2->c_str(), "%f %f %f %f %f %d %d %f %f %f %f %f %d %d %d %d %d %d %c %d %d %d %f", + &grid_voltage_rating, &grid_current_rating, &out_voltage_rating, &out_freq_rating, &out_current_rating, &out_va_rating, &out_watt_rating, &batt_rating, &batt_recharge_voltage, &batt_under_voltage, &batt_bulk_voltage, &batt_float_voltage, &batt_type, &max_grid_charge_current, &max_charge_current, &in_voltage_range, &out_source_priority, &charger_source_priority, ¶llel_max_num, &machine_type, &topology, &out_mode, &batt_redischarge_voltage); // There appears to be a discrepancy in actual DMM measured current vs what the meter is // telling me it's getting, so lets add a variable we can multiply/divide by to adjust if From 0dac2e9b82f02154806e8a6a5b48bf583e5486ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Sat, 9 Apr 2022 10:12:48 +0300 Subject: [PATCH 4/6] inverter.cpp: avoid mess with simultaneous read/write operations When many inverter_poller at the same time send commands, the result is undefined. This locks exclusively the configuration file, while the process is running, so that simultaneous instances have to wait until the file is released. For some reason locking the device /dev/hidraw0 does not work for me, I get sometimes the output from previous runs. I suspect that when cInverter::query() does exceed the 2s timeout, it quits, and leaves the response of its commands on the wire. For fd = /dev/hidraw0 tcflush(fd, TCOFLUSH); has no effect. As a matter of fact, on my system I have increased the timeout in cInverter::query() to 15s and now it does always work correctly. Also the program, when called with -1, could exit, while the thread is receiving data, this leaves the next invocation with some ready-data, which it is not expecting. --- sources/inverter-cli/inverter.cpp | 1 + sources/inverter-cli/inverter.h | 10 ++++++++-- sources/inverter-cli/main.cpp | 14 +++++++++++--- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/sources/inverter-cli/inverter.cpp b/sources/inverter-cli/inverter.cpp index 407421f..81de0ac 100644 --- a/sources/inverter-cli/inverter.cpp +++ b/sources/inverter-cli/inverter.cpp @@ -197,6 +197,7 @@ void cInverter::poll() { ups_qpiws_changed = true; } } + if (quit_thread) return; sleep(5); } diff --git a/sources/inverter-cli/inverter.h b/sources/inverter-cli/inverter.h index 6b47c62..dcaf10c 100644 --- a/sources/inverter-cli/inverter.h +++ b/sources/inverter-cli/inverter.h @@ -1,6 +1,7 @@ #ifndef ___INVERTER_H #define ___INVERTER_H +#include #include #include @@ -16,6 +17,8 @@ class cInverter { std::string device; std::mutex m; + std::thread t1; + std::atomic_bool quit_thread{false}; void SetMode(char newmode); bool CheckCRC(unsigned char *buff, int len); @@ -26,8 +29,11 @@ class cInverter { cInverter(std::string devicename, int qpiri, int qpiws, int qmod, int qpigs); void poll(); void runMultiThread() { - std::thread t1(&cInverter::poll, this); - t1.detach(); + t1 = std::thread(&cInverter::poll, this); + } + void terminateThread() { + quit_thread = true; + t1.join(); } string *GetQpiriStatus(); diff --git a/sources/inverter-cli/main.cpp b/sources/inverter-cli/main.cpp index d5799f7..527a121 100644 --- a/sources/inverter-cli/main.cpp +++ b/sources/inverter-cli/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "main.h" #include "tools.h" @@ -170,13 +171,17 @@ int main(int argc, char* argv[]) { runOnce = true; } lprintf("INVERTER: Debug set"); + const char *settings; // Get the rest of the settings from the conf file if( access( "./inverter.conf", F_OK ) != -1 ) { // file exists - getSettingsFile("./inverter.conf"); + settings = "./inverter.conf"; } else { // file doesn't exist - getSettingsFile("/etc/inverter/inverter.conf"); + settings = "/etc/inverter/inverter.conf"; } + getSettingsFile(settings); + int fd = open(settings, O_RDWR); + while (flock(fd, LOCK_EX)) sleep(1); bool ups_status_changed(false); ups = new cInverter(devicename,qpiri,qpiws,qmod,qpigs); @@ -299,6 +304,7 @@ int main(int argc, char* argv[]) { delete reply2; if(runOnce) { + ups->terminateThread(); // Do once and exit instead of loop endlessly lprintf("INVERTER: All queries complete, exiting loop."); exit(0); @@ -309,7 +315,9 @@ int main(int argc, char* argv[]) { sleep(1); } - if (ups) + if (ups) { + ups->terminateThread(); delete ups; + } return 0; } From f2882b76b5d2f0cec069140c36ff6dd957bc5e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Sun, 13 Mar 2022 11:52:28 +0200 Subject: [PATCH 5/6] inverter-mqtt/mqtt-push.sh: optimize On Raspberry Pi 3B executing the original code, with Influx disabled, takes: real 0m57,753s user 0m54,679s sys 0m2,214s With the modification the time is: real 0m10,733s user 0m8,338s sys 0m0,759s For the record, I run the code outside of containers. --- sources/inverter-mqtt/mqtt-push.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sources/inverter-mqtt/mqtt-push.sh b/sources/inverter-mqtt/mqtt-push.sh index e931de0..4becac6 100755 --- a/sources/inverter-mqtt/mqtt-push.sh +++ b/sources/inverter-mqtt/mqtt-push.sh @@ -1,14 +1,15 @@ #!/bin/bash INFLUX_ENABLED=`cat /etc/inverter/mqtt.json | jq '.influx.enabled' -r` +MQTT_SERVER=`cat /etc/inverter/mqtt.json | jq '.server' -r` +MQTT_PORT=`cat /etc/inverter/mqtt.json | jq '.port' -r` +MQTT_TOPIC=`cat /etc/inverter/mqtt.json | jq '.topic' -r` +MQTT_DEVICENAME=`cat /etc/inverter/mqtt.json | jq '.devicename' -r` +MQTT_USERNAME=`cat /etc/inverter/mqtt.json | jq '.username' -r` +MQTT_PASSWORD=`cat /etc/inverter/mqtt.json | jq '.password' -r` +MQTT_CLIENTID=`cat /etc/inverter/mqtt.json | jq '.clientid' -r` + pushMQTTData () { - MQTT_SERVER=`cat /etc/inverter/mqtt.json | jq '.server' -r` - MQTT_PORT=`cat /etc/inverter/mqtt.json | jq '.port' -r` - MQTT_TOPIC=`cat /etc/inverter/mqtt.json | jq '.topic' -r` - MQTT_DEVICENAME=`cat /etc/inverter/mqtt.json | jq '.devicename' -r` - MQTT_USERNAME=`cat /etc/inverter/mqtt.json | jq '.username' -r` - MQTT_PASSWORD=`cat /etc/inverter/mqtt.json | jq '.password' -r` - MQTT_CLIENTID=`cat /etc/inverter/mqtt.json | jq '.clientid' -r` mosquitto_pub \ -h $MQTT_SERVER \ From 280d157eeacf3c10f5790d5ec5714df8deef07d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B8=D0=BB=D1=8F=D0=BD=20=D0=9F=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=83=D0=B7=D0=BE=D0=B2?= Date: Wed, 16 Mar 2022 15:23:45 +0200 Subject: [PATCH 6/6] mqtt-push.sh: further optimizations Here more jq-calls are replaced with sed. The time on Raspberry Pi is now real 0m4,965s user 0m2,595s sys 0m0,726s I do not use Influx. This allows updating the data in OpenHab (I read the MQTT stream from OpenHAB) every five seconds, once all jq calls are removed. --- sources/inverter-mqtt/mqtt-push.sh | 118 ++++------------------------- 1 file changed, 13 insertions(+), 105 deletions(-) diff --git a/sources/inverter-mqtt/mqtt-push.sh b/sources/inverter-mqtt/mqtt-push.sh index 4becac6..1b2cb72 100755 --- a/sources/inverter-mqtt/mqtt-push.sh +++ b/sources/inverter-mqtt/mqtt-push.sh @@ -10,6 +10,12 @@ MQTT_PASSWORD=`cat /etc/inverter/mqtt.json | jq '.password' -r` MQTT_CLIENTID=`cat /etc/inverter/mqtt.json | jq '.clientid' -r` pushMQTTData () { + param=$1 + value=`echo $INVERTER_DATA| sed --expression "sK.*\"$param\":\([^,}]*\).*K\1K"` + + if test -z $value; then + return + fi mosquitto_pub \ -h $MQTT_SERVER \ @@ -17,11 +23,11 @@ pushMQTTData () { -u "$MQTT_USERNAME" \ -P "$MQTT_PASSWORD" \ -i $MQTT_CLIENTID \ - -t "$MQTT_TOPIC/sensor/"$MQTT_DEVICENAME"_$1" \ - -m "$2" + -t "$MQTT_TOPIC/sensor/"$MQTT_DEVICENAME"_$param" \ + -m "$value" if [[ $INFLUX_ENABLED == "true" ]] ; then - pushInfluxData $1 $2 + pushInfluxData $param $value fi } @@ -40,106 +46,8 @@ pushInfluxData () { INVERTER_DATA=`timeout 10 /opt/inverter-cli/bin/inverter_poller -1` ##################################################################################### +# Inverter_Mode: 1 = Power_On, 2 = Standby, 3 = Line, 4 = Battery, 5 = Fault, 6 = Power_Saving, 7 = Unknown -Inverter_mode=`echo $INVERTER_DATA | jq '.Inverter_mode' -r` - - # 1 = Power_On, 2 = Standby, 3 = Line, 4 = Battery, 5 = Fault, 6 = Power_Saving, 7 = Unknown - -[ ! -z "$Inverter_mode" ] && pushMQTTData "Inverter_mode" "$Inverter_mode" - -AC_grid_voltage=`echo $INVERTER_DATA | jq '.AC_grid_voltage' -r` -[ ! -z "$AC_grid_voltage" ] && pushMQTTData "AC_grid_voltage" "$AC_grid_voltage" - -AC_grid_frequency=`echo $INVERTER_DATA | jq '.AC_grid_frequency' -r` -[ ! -z "$AC_grid_frequency" ] && pushMQTTData "AC_grid_frequency" "$AC_grid_frequency" - -AC_out_voltage=`echo $INVERTER_DATA | jq '.AC_out_voltage' -r` -[ ! -z "$AC_out_voltage" ] && pushMQTTData "AC_out_voltage" "$AC_out_voltage" - -AC_out_frequency=`echo $INVERTER_DATA | jq '.AC_out_frequency' -r` -[ ! -z "$AC_out_frequency" ] && pushMQTTData "AC_out_frequency" "$AC_out_frequency" - -PV_in_voltage=`echo $INVERTER_DATA | jq '.PV_in_voltage' -r` -[ ! -z "$PV_in_voltage" ] && pushMQTTData "PV_in_voltage" "$PV_in_voltage" - -PV_in_current=`echo $INVERTER_DATA | jq '.PV_in_current' -r` -[ ! -z "$PV_in_current" ] && pushMQTTData "PV_in_current" "$PV_in_current" - -PV_in_watts=`echo $INVERTER_DATA | jq '.PV_in_watts' -r` -[ ! -z "$PV_in_watts" ] && pushMQTTData "PV_in_watts" "$PV_in_watts" - -PV_in_watthour=`echo $INVERTER_DATA | jq '.PV_in_watthour' -r` -[ ! -z "$PV_in_watthour" ] && pushMQTTData "PV_in_watthour" "$PV_in_watthour" - -SCC_voltage=`echo $INVERTER_DATA | jq '.SCC_voltage' -r` -[ ! -z "$SCC_voltage" ] && pushMQTTData "SCC_voltage" "$SCC_voltage" - -Load_pct=`echo $INVERTER_DATA | jq '.Load_pct' -r` -[ ! -z "$Load_pct" ] && pushMQTTData "Load_pct" "$Load_pct" - -Load_watt=`echo $INVERTER_DATA | jq '.Load_watt' -r` -[ ! -z "$Load_watt" ] && pushMQTTData "Load_watt" "$Load_watt" - -Load_watthour=`echo $INVERTER_DATA | jq '.Load_watthour' -r` -[ ! -z "$Load_watthour" ] && pushMQTTData "Load_watthour" "$Load_watthour" - -Load_va=`echo $INVERTER_DATA | jq '.Load_va' -r` -[ ! -z "$Load_va" ] && pushMQTTData "Load_va" "$Load_va" - -Bus_voltage=`echo $INVERTER_DATA | jq '.Bus_voltage' -r` -[ ! -z "$Bus_voltage" ] && pushMQTTData "Bus_voltage" "$Bus_voltage" - -Heatsink_temperature=`echo $INVERTER_DATA | jq '.Heatsink_temperature' -r` -[ ! -z "$Heatsink_temperature" ] && pushMQTTData "Heatsink_temperature" "$Heatsink_temperature" - -Battery_capacity=`echo $INVERTER_DATA | jq '.Battery_capacity' -r` -[ ! -z "$Battery_capacity" ] && pushMQTTData "Battery_capacity" "$Battery_capacity" - -Battery_voltage=`echo $INVERTER_DATA | jq '.Battery_voltage' -r` -[ ! -z "$Battery_voltage" ] && pushMQTTData "Battery_voltage" "$Battery_voltage" - -Battery_charge_current=`echo $INVERTER_DATA | jq '.Battery_charge_current' -r` -[ ! -z "$Battery_charge_current" ] && pushMQTTData "Battery_charge_current" "$Battery_charge_current" - -Battery_discharge_current=`echo $INVERTER_DATA | jq '.Battery_discharge_current' -r` -[ ! -z "$Battery_discharge_current" ] && pushMQTTData "Battery_discharge_current" "$Battery_discharge_current" - -Load_status_on=`echo $INVERTER_DATA | jq '.Load_status_on' -r` -[ ! -z "$Load_status_on" ] && pushMQTTData "Load_status_on" "$Load_status_on" - -SCC_charge_on=`echo $INVERTER_DATA | jq '.SCC_charge_on' -r` -[ ! -z "$SCC_charge_on" ] && pushMQTTData "SCC_charge_on" "$SCC_charge_on" - -AC_charge_on=`echo $INVERTER_DATA | jq '.AC_charge_on' -r` -[ ! -z "$AC_charge_on" ] && pushMQTTData "AC_charge_on" "$AC_charge_on" - -Battery_recharge_voltage=`echo $INVERTER_DATA | jq '.Battery_recharge_voltage' -r` -[ ! -z "$Battery_recharge_voltage" ] && pushMQTTData "Battery_recharge_voltage" "$Battery_recharge_voltage" - -Battery_under_voltage=`echo $INVERTER_DATA | jq '.Battery_under_voltage' -r` -[ ! -z "$Battery_under_voltage" ] && pushMQTTData "Battery_under_voltage" "$Battery_under_voltage" - -Battery_bulk_voltage=`echo $INVERTER_DATA | jq '.Battery_bulk_voltage' -r` -[ ! -z "$Battery_bulk_voltage" ] && pushMQTTData "Battery_bulk_voltage" "$Battery_bulk_voltage" - -Battery_float_voltage=`echo $INVERTER_DATA | jq '.Battery_float_voltage' -r` -[ ! -z "$Battery_float_voltage" ] && pushMQTTData "Battery_float_voltage" "$Battery_float_voltage" - -Max_grid_charge_current=`echo $INVERTER_DATA | jq '.Max_grid_charge_current' -r` -[ ! -z "$Max_grid_charge_current" ] && pushMQTTData "Max_grid_charge_current" "$Max_grid_charge_current" - -Max_charge_current=`echo $INVERTER_DATA | jq '.Max_charge_current' -r` -[ ! -z "$Max_charge_current" ] && pushMQTTData "Max_charge_current" "$Max_charge_current" - -Out_source_priority=`echo $INVERTER_DATA | jq '.Out_source_priority' -r` -[ ! -z "$Out_source_priority" ] && pushMQTTData "Out_source_priority" "$Out_source_priority" - -Charger_source_priority=`echo $INVERTER_DATA | jq '.Charger_source_priority' -r` -[ ! -z "$Charger_source_priority" ] && pushMQTTData "Charger_source_priority" "$Charger_source_priority" - -Battery_redischarge_voltage=`echo $INVERTER_DATA | jq '.Battery_redischarge_voltage' -r` -[ ! -z "$Battery_redischarge_voltage" ] && pushMQTTData "Battery_redischarge_voltage" "$Battery_redischarge_voltage" - -Warnings=`echo $INVERTER_DATA | jq '.Warnings' -r` -[ ! -z "$Warnings" ] && pushMQTTData "Warnings" "$Warnings" - +for w in Inverter_mode AC_grid_voltage AC_grid_frequency AC_out_voltage AC_out_frequency PV_in_voltage PV_in_current PV_in_watts PV_in_watthour SCC_voltage Load_pct Load_watt Load_watthour Load_va Bus_voltage Heatsink_temperature Battery_capacity Battery_voltage Battery_charge_current Battery_discharge_current Load_status_on SCC_charge_on AC_charge_on Battery_recharge_voltage Battery_under_voltage Battery_bulk_voltage Battery_float_voltage Max_grid_charge_current Max_charge_current Out_source_priority Charger_source_priority Battery_redischarge_voltage Warnings; do + pushMQTTData $w +done