diff --git a/INFLUXDB.md b/INFLUXDB.md index 27c5d2d..fb6a021 100644 --- a/INFLUXDB.md +++ b/INFLUXDB.md @@ -18,6 +18,7 @@ INFLUXDB_1_AUTH=false INFLUXDB_1_USER= INFLUXDB_1_PASSWORD= INFLUXDB_TOPIC=e3dc/[a-z]+/power +INFLUXDB_TOPIC=e3dc/day/.* ``` You can configure the topics to be transferred to the InfluxDB by setting the parameter INFLUXDB_TOPIC. INFLUXDB_TOPIC can occur several times. diff --git a/README.md b/README.md index d6a9978..861afa5 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,10 @@ [![GitHub](https://img.shields.io/github/license/pvtom/rscp2mqtt)](https://github.com/pvtom/rscp2mqtt/blob/main/LICENSE) This software module connects a home power station from E3/DC to an MQTT broker. -It uses the RSCP interface of the device. -The solution is based on the RSCP sample application provided by E3/DC and was developed and tested with a Raspberry Pi and a Linux PC (x86_64). +It uses the RSCP interface of the device. The solution is based on the RSCP sample application provided by E3/DC and was developed and tested with a Raspberry Pi and a Linux PC (x86_64). -The tool fetches data cyclically and publishes it to the MQTT broker under certain [topics](TOPICS.md). +The tool cyclically queries data from the home power station and publishes it to an MQTT broker using these [topics](TOPICS.md). Supported topic areas are: @@ -47,9 +46,9 @@ For continuous provision of values, you can configure several topics that are pu - Configuration of the topics that will be published to InfluxDB (INFLUXDB_TOPIC) - MQTT Client ID can be configured - More detailled [TOPIC](TOPICS.md) overview -- (new) Multiple battery strings are supported (BATTERY_STRINGS parameter) -- (new) Automatic detection of the number of PVI trackers -- (new) Additional topics +- Multiple battery strings are supported (BATTERY_STRINGS parameter) +- Automatic detection of the number of PVI trackers +- (new) Query of historical daily values ## Docker @@ -142,7 +141,7 @@ or in verbose mode If everything works properly, you will see something like this: ``` -rscp2mqtt [v3.10] +rscp2mqtt [v3.11] E3DC system >192.168.178.111:5033< user: >your E3DC user< MQTT broker >localhost:1883< qos = >0< retain = >false< client id >✗< prefix >e3dc< Fetching data every second. @@ -151,11 +150,11 @@ Log level = 0 Stdout to terminal ... -[2024-01-03 10:00:00] pid=30100 ppid=1 RscpMqttMain.cpp(2185) Connecting to server 192.168.178.111:5033 -[2024-01-03 10:00:00] pid=30100 ppid=1 RscpMqttMain.cpp(2192) Success: E3DC connected. -[2024-01-03 10:00:00] pid=30100 ppid=1 RscpMqttMain.cpp(1283) RSCP authentication level 10 -[2024-01-03 10:00:00] pid=30100 ppid=1 RscpMqttMain.cpp(1796) Connecting to broker localhost:1883 -[2024-01-03 10:00:00] pid=30100 ppid=1 RscpMqttMain.cpp(289) Success: MQTT broker connected. +[2024-01-13 10:50:00] pid=30110 ppid=1 RscpMqttMain.cpp(2294) Connecting to server 192.168.178.111:5033 +[2024-01-13 10:50:00] pid=30110 ppid=1 RscpMqttMain.cpp(2301) Success: E3DC connected. +[2024-01-13 10:50:00] pid=30110 ppid=1 RscpMqttMain.cpp(1379) RSCP authentication level 10 +[2024-01-13 10:50:00] pid=30110 ppid=1 RscpMqttMain.cpp(1905) Connecting to broker localhost:1883 +[2024-01-13 10:50:00] pid=30110 ppid=1 RscpMqttMain.cpp(1914) Success: MQTT broker connected. ... ``` @@ -198,7 +197,7 @@ sudo systemctl start rscp2mqtt ## Device Control -rscp2mqtt subscribes to the root topic "prefix/set/#" and forwards incoming requests to the home power station. In this way, the device can be controlled and changes made to its configuration. +rscp2mqtt subscribes to the root topic "e3dc/set/#" and forwards incoming requests to the home power station. In this way, the device can be controlled, additional data can be queried and changes can be made to its configuration. ### Battery Charging @@ -379,6 +378,18 @@ Set number of phases (1/3) mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/number_phases" -m 1 ``` +## Historical daily data + +Historical data for a specific day (format "YYYY-MM-DD") can be queried by +``` +mosquitto_pub -h localhost -p 1883 -t "e3dc/set/request/day" -m "2024-01-01" +``` + +Please use the script `request_days.sh` to request data for a time span. +``` +./request_days.sh localhost 1883 e3dc 2024-01-01 2024-01-13 +``` + ## System Commands Refresh all topics diff --git a/RELEASE.md b/RELEASE.md index 139e1c7..68a2fde 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,10 @@ ## Release Notes +### Release v3.11 (13.01.2024) + +- Query of historical daily values (Issue #40) +- Issue #41: Enables the reserve to be set to 100% + ### Release v3.10 (03.01.2024) - Issue #30: Multiple battery strings are supported (e.g. S10 Pro) diff --git a/RscpMqttMain.cpp b/RscpMqttMain.cpp index 7bff043..3802cd5 100644 --- a/RscpMqttMain.cpp +++ b/RscpMqttMain.cpp @@ -19,7 +19,7 @@ #include #include -#define RSCP2MQTT "v3.10" +#define RSCP2MQTT "v3.11" #define AES_KEY_SIZE 32 #define AES_BLOCK_SIZE 32 @@ -44,6 +44,7 @@ #define DISCHARGE_LOCK_TRUE "today:discharge:true:00:00-23:59" #define DISCHARGE_LOCK_FALSE "today:discharge:false:00:00-23:59" #define PV_SOLAR_MIN 200 +#define MAX_DAYS_PER_ITERATION 12 static int iSocket = -1; static int iAuthenticated = 0; @@ -57,9 +58,10 @@ static time_t e3dc_ts = 0; static time_t e3dc_diff = 0; static int gmt_diff = 0; static config_t cfg; -static int day, year, curr_year, battery_nr; +static int day, leap_day, year, curr_year, battery_nr; static uint8_t period_change_nr = 0; static bool period_trigger = false; +static bool history_init = true; std::mutex mtx; @@ -96,7 +98,14 @@ int storeMQTTReceivedValue(std::vector & c, char *topic_ if (std::regex_match(payload, std::regex(it->regex_true))) { if (strcmp(it->value_true, "")) strncpy(it->payload, it->value_true, PAYLOAD_SIZE); else strncpy(it->payload, payload, PAYLOAD_SIZE); - it->done = false; + if (it->queue) { + if (!strcmp(it->topic, "set/request/day")) { + int year, month, day; + if (sscanf(it->payload, "%d-%d-%d", &year, &month, &day)) { + RSCP_MQTT::requestQ.push({day, month, year}); + } + } + } else it->done = false; break; } else if (std::regex_match(payload, std::regex(it->regex_false))) { if (strcmp(it->value_false, "")) strncpy(it->payload, it->value_false, PAYLOAD_SIZE); @@ -226,13 +235,22 @@ int handleSetIdlePeriod(RscpProtocol *protocol, SRscpValue *rootContainer, char return(0); } -void addTemplTopics(uint32_t container, int index, int start, int n, int inc) { +void addTemplTopics(uint32_t container, int index, char *seg, int start, int n, int inc) { for (int c = start; c < n; c++) { for (std::vector::iterator it = RSCP_MQTT::RscpMqttCacheTempl.begin(); it != RSCP_MQTT::RscpMqttCacheTempl.end(); ++it) { - if ((it->container == container) && (it->index == index)) { + if (it->container == container) { RSCP_MQTT::cache_t cache = { it->container, it->tag, c, "", "", it->format, "", it->divisor, it->bit_to_bool, it->history_log, it->changed, it->influx, it->forced }; - if (index) snprintf(cache.topic, TOPIC_SIZE, it->topic, c + inc); - else strcpy(cache.topic, it->topic); + if ((seg == NULL) && (index == 0)) { // no args + strcpy(cache.topic, it->topic); + } else if ((seg == NULL) && (index == 1)) { // "%d" + snprintf(cache.topic, TOPIC_SIZE, it->topic, c + inc); + } else if ((seg != NULL) && (index == 0)) { // "%s" + snprintf(cache.topic, TOPIC_SIZE, it->topic, seg); + } else { // "%s" with "%s/%d" + char buffer[TOPIC_SIZE]; + snprintf(buffer, TOPIC_SIZE, "%s/%d", seg, c + inc); + snprintf(cache.topic, TOPIC_SIZE, it->topic, buffer); + } strcpy(cache.unit, it->unit); for (std::vector::iterator it2 = RSCP_MQTT::TopicStore.begin(); it2 != RSCP_MQTT::TopicStore.end(); ++it2) { switch (it2->type) { @@ -303,7 +321,7 @@ int insertInfluxDb(char *buffer) { return(res); } -void handleInfluxDb(char *buffer, char *topic, char *payload, char *unit) { +void handleInfluxDb(char *buffer, char *topic, char *payload, char *unit, char *timestamp) { char line[CURL_BUFFER_SIZE]; if (topic == NULL) { @@ -313,6 +331,7 @@ void handleInfluxDb(char *buffer, char *topic, char *payload, char *unit) { if (!strcmp(payload, "true")) sprintf(line, "%s,topic=%s value=1", cfg.influxdb_measurement, topic); else if (!strcmp(payload, "false")) sprintf(line, "%s,topic=%s value=0", cfg.influxdb_measurement, topic); + else if (strcmp(unit, "") && timestamp) sprintf(line, "%s,topic=%s,unit=%s value=%s %s", cfg.influxdb_measurement, topic, unit, payload, timestamp); else if (strcmp(unit, "")) sprintf(line, "%s,topic=%s,unit=%s value=%s", cfg.influxdb_measurement, topic, unit, payload); else return; @@ -347,13 +366,13 @@ int handleMQTT(std::vector & v, int qos, bool retain) { if (it->history_log) logMessage(cfg.historyfile, (char *)__FILE__, __LINE__, (char *)"topic >%s< payload >%s< unit >%s<\n", it->topic, it->payload, it->unit); if (cfg.mqtt_pub && mosq) rc = mosquitto_publish(mosq, NULL, it->topic, strlen(it->payload), it->payload, qos, retain); #ifdef INFLUXDB - if (cfg.influxdb_on && curl && it->influx) handleInfluxDb(buffer, it->topic, it->payload, it->unit); + if (cfg.influxdb_on && curl && it->influx) handleInfluxDb(buffer, it->topic, it->payload, it->unit, NULL); #endif it->changed = false; } } #ifdef INFLUXDB - if (cfg.influxdb_on && curl) handleInfluxDb(buffer, NULL, NULL, NULL); + if (cfg.influxdb_on && curl) handleInfluxDb(buffer, NULL, NULL, NULL, NULL); #endif return(rc); } @@ -486,7 +505,9 @@ void copyCache(std::vector & to, std::vector & v) { std::vector TempCache({}); copyCache(TempCache, v, TAG_DB_HISTORY_DATA_YEAR); + copyCache(TempCache, v, TAG_DB_HISTORY_DATA_DAY); RSCP_MQTT::RscpMqttCacheTempl.clear(); + copyCache(v, TempCache, TAG_DB_HISTORY_DATA_DAY); copyCache(v, TempCache, TAG_DB_HISTORY_DATA_YEAR); return; } @@ -555,6 +576,49 @@ void setTopicsInflux(std::vector & v, char *regex) { } #endif +int handleImmediately(RscpProtocol *protocol, SRscpValue *response, uint32_t container, int year, int month, int day) { +#ifdef INFLUXDB + char buffer[CURL_BUFFER_SIZE]; + char ts[24]; + strcpy(buffer, ""); + time_t rawtime; + time(&rawtime); + struct tm *l = localtime(&rawtime); + l->tm_sec = 0; + l->tm_min = 0; + l->tm_hour = 0; + l->tm_isdst = -1; +#endif + char topic[TOPIC_SIZE]; + char payload[PAYLOAD_SIZE]; + int rc = 0; + + for (std::vector::iterator it = RSCP_MQTT::RscpMqttCacheTempl.begin(); it != RSCP_MQTT::RscpMqttCacheTempl.end(); ++it) { + if ((it->container == container) && (it->tag == response->tag)) { + snprintf(topic, TOPIC_SIZE, it->topic, year, month, day); + snprintf(payload, PAYLOAD_SIZE, "%0.2f", protocol->getValueAsFloat32(response) / it->divisor); + if (cfg.mqtt_pub && mosq) rc = mosquitto_publish(mosq, NULL, topic, strlen(payload), payload, cfg.mqtt_qos, cfg.mqtt_retain); +#ifdef INFLUXDB + l->tm_mday = day; + l->tm_mon = month - 1; + l->tm_year = year - 1900; + sprintf(ts, "%llu000000000", timegm(l) - gmt_diff); + if (cfg.influxdb_on && curl) { + for (std::vector::iterator store = RSCP_MQTT::TopicStore.begin(); store != RSCP_MQTT::TopicStore.end(); ++store) { + if ((store->type == INFLUXDB_TOPIC) && std::regex_match(topic, std::regex(store->topic))) { + handleInfluxDb(buffer, topic, payload, it->unit, ts); + } + } + } +#endif + } + } +#ifdef INFLUXDB + if (cfg.influxdb_on && curl) handleInfluxDb(buffer, NULL, NULL, NULL, NULL); +#endif + return(rc); +} + int storeIntegerValue(std::vector & c, uint32_t container, uint32_t tag, int value, int index) { char buf[PAYLOAD_SIZE]; for (std::vector::iterator it = c.begin(); it != c.end(); ++it) { @@ -650,7 +714,7 @@ int storeResponseValue(std::vector & c, RscpProtocol *protoc break; } case RSCP::eTypeUInt64: { - snprintf(buf, PAYLOAD_SIZE, "%llu", protocol->getValueAsUInt64(response)); + snprintf(buf, PAYLOAD_SIZE, "%lu", protocol->getValueAsUInt64(response)); if (strcmp(it->payload, buf)) { strcpy(it->payload, buf); it->changed = true; @@ -721,6 +785,12 @@ int storeResponseValue(std::vector & c, RscpProtocol *protoc } } rc = response->dataType; + if ((container == TAG_DB_HISTORY_DATA_DAY) && (index == 0) && (it->changed)) { + time_t rawtime; + time(&rawtime); + struct tm *l = localtime(&rawtime); + handleImmediately(protocol, response, TAG_DB_HISTORY_DATA_DAY, l->tm_year + 1900, l->tm_mon + 1, l->tm_mday); + } } } return(rc); @@ -809,6 +879,7 @@ int createRequest(SRscpFrameBuffer * frameBuffer) { time_t rawtime; time(&rawtime); struct tm *l = localtime(&rawtime); + int day_iteration; strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", l); @@ -820,7 +891,7 @@ int createRequest(SRscpFrameBuffer * frameBuffer) { l->tm_isdst = -1; if (curr_year < l->tm_year + 1900) { - addTemplTopics(TAG_DB_HISTORY_DATA_YEAR, 1, curr_year, l->tm_year + 1900, 0); + addTemplTopics(TAG_DB_HISTORY_DATA_YEAR, 1, NULL, curr_year, l->tm_year + 1900, 0); curr_year = l->tm_year + 1900; } @@ -1099,9 +1170,34 @@ int createRequest(SRscpFrameBuffer * frameBuffer) { protocol.destroyValueData(dbContainer); } } - - // handle incoming MQTT requests mtx.lock(); + day_iteration = 0; + while ((day_iteration++ < MAX_DAYS_PER_ITERATION) && (!RSCP_MQTT::requestQ.empty())) { + if (!RSCP_MQTT::requestQ.empty()) { + RSCP_MQTT::date_t x; + + x = RSCP_MQTT::requestQ.front(); + RSCP_MQTT::requestQ.pop(); + leap_day = ((x.month == 2) && (!(x.year%4) && ((x.year%100) || !(x.year%400))))?1:0; + if ((x.year > cfg.history_start_year) && (x.year <= curr_year) && (x.month > 0) && (x.month <= 12) && (x.day > 0) && (x.day <= (RSCP_MQTT::nr_of_days[x.month - 1] + leap_day))) { + RSCP_MQTT::paramQ.push({x.day, x.month, x.year}); + SRscpValue dbContainer; + l->tm_mday = x.day; + l->tm_mon = x.month - 1; + l->tm_year = x.year - 1900; + start.seconds = timegm(l) - gmt_diff - 15 * 60; + interval.seconds = 24 * 3600; + span.seconds = 24 * 3600; + protocol.createContainerValue(&dbContainer, TAG_DB_REQ_HISTORY_DATA_DAY); + protocol.appendValue(&dbContainer, TAG_DB_REQ_HISTORY_UTC_TIME_START, start); + protocol.appendValue(&dbContainer, TAG_DB_REQ_HISTORY_TIME_INTERVAL, interval); + protocol.appendValue(&dbContainer, TAG_DB_REQ_HISTORY_TIME_SPAN, span); + protocol.appendValue(&rootValue, dbContainer); + protocol.destroyValueData(dbContainer); + } + } + } + // handle incoming MQTT requests if (mqttRcvd || cfg.auto_refresh) { mqttRcvd = false; uint32_t container = 0; @@ -1254,6 +1350,8 @@ int createRequest(SRscpFrameBuffer * frameBuffer) { } int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { + RSCP_MQTT::date_t x; + // check if any of the response has the error flag set and react accordingly if (response->dataType == RSCP::eTypeError) { // handle error for example access denied errors @@ -1332,7 +1430,7 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { cfg.bat_dcb_count[battery_nr] = protocol->getValueAsUChar8(&containerData[i]); cfg.bat_dcb_start[battery_nr] = battery_nr?cfg.bat_dcb_count[battery_nr - 1]:0; storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag, 0); - addTemplTopics(TAG_BAT_DCB_INFO, 1, cfg.bat_dcb_start[battery_nr], cfg.bat_dcb_start[battery_nr] + cfg.bat_dcb_count[battery_nr], 1); + addTemplTopics(TAG_BAT_DCB_INFO, 1, NULL, cfg.bat_dcb_start[battery_nr], cfg.bat_dcb_start[battery_nr] + cfg.bat_dcb_count[battery_nr], 1); if (cfg.verbose) logMessage(cfg.logfile, (char *)__FILE__, __LINE__, (char *)"TAG_BAT_DCB_COUNT battery_nr = %d bat_dcb_count = %d bat_dcb_start = %d\n", battery_nr, cfg.bat_dcb_count[battery_nr], cfg.bat_dcb_start[battery_nr]); break; } @@ -1363,7 +1461,7 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { if (cfg.log_level) logMessage(cfg.logfile, (char *)__FILE__, __LINE__, (char *)"Error: Container 0x%08X Tag 0x%08X received error code %u.\n", response->tag, containerData[i].tag, uiErrorCode); if (uiErrorCode == 6) { // Wallbox not available if (cfg.verbose) logMessage(cfg.logfile, (char *)__FILE__, __LINE__, (char *)"Error: Wallbox not available.\n"); - cfg.wallbox = false; + //cfg.wallbox = false; pushNotSupportedTag(response->tag, containerData[i].tag); } } else if (containerData[i].tag == TAG_WB_EXTERN_DATA_ALG) { @@ -1436,15 +1534,15 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { case TAG_PVI_TEMPERATURE_COUNT: { cfg.pvi_temp_count = protocol->getValueAsUChar8(&containerData[i]); storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag, 0); - addTemplTopics(TAG_PVI_TEMPERATURE, 1, 0, cfg.pvi_temp_count, 1); + addTemplTopics(TAG_PVI_TEMPERATURE, 1, NULL, 0, cfg.pvi_temp_count, 1); break; } case TAG_PVI_USED_STRING_COUNT: { cfg.pvi_tracker = protocol->getValueAsUChar8(&containerData[i]); - addTemplTopics(TAG_PVI_DC_POWER, 1, 0, cfg.pvi_tracker, 1); - addTemplTopics(TAG_PVI_DC_VOLTAGE, 1, 0, cfg.pvi_tracker, 1); - addTemplTopics(TAG_PVI_DC_CURRENT, 1, 0, cfg.pvi_tracker, 1); - addTemplTopics(TAG_PVI_DC_STRING_ENERGY_ALL, 1, 0, cfg.pvi_tracker, 1); + addTemplTopics(TAG_PVI_DC_POWER, 1, NULL, 0, cfg.pvi_tracker, 1); + addTemplTopics(TAG_PVI_DC_VOLTAGE, 1, NULL, 0, cfg.pvi_tracker, 1); + addTemplTopics(TAG_PVI_DC_CURRENT, 1, NULL, 0, cfg.pvi_tracker, 1); + addTemplTopics(TAG_PVI_DC_STRING_ENERGY_ALL, 1, NULL, 0, cfg.pvi_tracker, 1); storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag, 0); break; } @@ -1567,7 +1665,14 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { protocol->destroyValueData(containerData); break; } - case TAG_DB_HISTORY_DATA_DAY: + case TAG_DB_HISTORY_DATA_DAY: { + if (day >= 2) { + if (!RSCP_MQTT::paramQ.empty()) { + x = RSCP_MQTT::paramQ.front(); + RSCP_MQTT::paramQ.pop(); + } + } + } case TAG_DB_HISTORY_DATA_WEEK: case TAG_DB_HISTORY_DATA_MONTH: case TAG_DB_HISTORY_DATA_YEAR: { @@ -1584,7 +1689,11 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { std::vector dbData = protocol->getValueAsContainer(&(historyData[i])); for (size_t j = 0; j < dbData.size(); ++j) { if (response->tag == TAG_DB_HISTORY_DATA_DAY) { - storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(dbData[j]), response->tag, day); + if (day >= 2) { + handleImmediately(protocol, &(dbData[j]), TAG_DB_HISTORY_DATA_DAY, x.year, x.month, x.day); + } else storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(dbData[j]), response->tag, day); + } else if (response->tag == TAG_DB_HISTORY_DATA_MONTH) { + storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(dbData[j]), response->tag, 0); } else if (response->tag == TAG_DB_HISTORY_DATA_YEAR) { if (year == curr_year) storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(dbData[j]), response->tag, 0); else storeResponseValue(RSCP_MQTT::RscpMqttCache, protocol, &(dbData[j]), response->tag, year); @@ -1595,8 +1704,10 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) { protocol->destroyValueData(dbData); break; } + case TAG_DB_VALUE_CONTAINER: { + break; + } default: - //if (!cfg.daemon) printf("Unknown db history tag %08X\n", historyData[i].tag); break; } } @@ -2049,7 +2160,7 @@ int main(int argc, char *argv[]){ // prepare RscpMqttReceiveCache for (uint8_t c = 0; c < IDLE_PERIOD_CACHE_SIZE; c++) { - RSCP_MQTT::rec_cache_t cache = { 0, 0, "set/idle_period", SET_IDLE_PERIOD_REGEX, "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }; + RSCP_MQTT::rec_cache_t cache = { 0, 0, "set/idle_period", SET_IDLE_PERIOD_REGEX, "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }; RSCP_MQTT::RscpMqttReceiveCache.push_back(cache); } sort(RSCP_MQTT::RscpMqttReceiveCache.begin(), RSCP_MQTT::RscpMqttReceiveCache.end(), RSCP_MQTT::compareRecCache); @@ -2090,11 +2201,11 @@ int main(int argc, char *argv[]){ // History year if (cfg.verbose) printf("History year range from %d to %d\n", cfg.history_start_year, curr_year); - if (cfg.history_start_year < curr_year) addTemplTopics(TAG_DB_HISTORY_DATA_YEAR, 1, cfg.history_start_year, curr_year, 0); + if (cfg.history_start_year < curr_year) addTemplTopics(TAG_DB_HISTORY_DATA_YEAR, 1, NULL, cfg.history_start_year, curr_year, 0); // Battery Strings - addTemplTopics(TAG_BAT_DATA, (cfg.battery_strings == 1)?0:1, 0, cfg.battery_strings, 1); - addTemplTopics(TAG_BAT_SPECIFICATION, (cfg.battery_strings == 1)?0:1, 0, cfg.battery_strings, 1); + addTemplTopics(TAG_BAT_DATA, (cfg.battery_strings == 1)?0:1, (char *)"battery", 0, cfg.battery_strings, 1); + addTemplTopics(TAG_BAT_SPECIFICATION, (cfg.battery_strings == 1)?0:1, (char *)"battery", 0, cfg.battery_strings, 1); #ifdef INFLUXDB if (cfg.influxdb_on && (cfg.influxdb_version == 1)) { diff --git a/RscpMqttMapping.h b/RscpMqttMapping.h index 0febe76..1e432a0 100644 --- a/RscpMqttMapping.h +++ b/RscpMqttMapping.h @@ -3,6 +3,7 @@ #include "RscpTags.h" #include "RscpTypes.h" +#include #define TOPIC_SIZE 128 #define PAYLOAD_SIZE 128 @@ -42,6 +43,7 @@ namespace RSCP_MQTT { std::string days[8] = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday", "today"}; +int nr_of_days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; typedef struct _topic_store_t { uint8_t type; @@ -79,6 +81,15 @@ typedef struct _not_supported_tags_t { std::vector NotSupportedTags; +typedef struct _date_t { + int day; + int month; + int year; +} date_t; + +std::queue requestQ; +std::queue paramQ; + typedef struct _cache_t { uint32_t container; uint32_t tag; @@ -133,11 +144,7 @@ cache_t cache[] = { { 0, TAG_EMS_COUPLING_MODE, 0, "coupling/mode", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, { 0, TAG_EMS_IDLE_PERIOD_CHANGE_MARKER, 0, "idle_period/change", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, { 0, TAG_PVI_INVERTER_COUNT, 0, "system/inverter_count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - -//DEV { 0, TAG_BAT_AVAILABLE_BATTERIES, 0, "system/battery_count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - - { 0, TAG_EMS_USED_CHARGE_LIMIT, 0, "ems/used_charge_limit", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, { 0, TAG_EMS_BAT_CHARGE_LIMIT, 0, "ems/battery_charge_limit", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, { 0, TAG_EMS_DCDC_CHARGE_LIMIT, 0, "ems/dcdc_charge_limit", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, @@ -229,6 +236,7 @@ cache_t cache[] = { { TAG_DB_HISTORY_DATA_DAY, TAG_DB_CONSUMPTION, 0, "home/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_DAY, TAG_DB_PM_0_POWER, 0, "pm_0/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_DAY, TAG_DB_PM_1_POWER, 0, "pm_1/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_BAT_CHARGE_LEVEL, 0, "battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_DAY, TAG_DB_CONSUMED_PRODUCTION, 0, "consumed", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_DAY, TAG_DB_AUTARKY, 0, "autarky", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, // YESTERDAY @@ -250,6 +258,9 @@ cache_t cache[] = { { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_GRID_POWER_IN, 0, "week/grid/energy/in", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_GRID_POWER_OUT, 0, "week/grid/energy/out", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_CONSUMPTION, 0, "week/home/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_PM_0_POWER, 0, "week/pm_0/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_PM_1_POWER, 0, "week/pm_1/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_BAT_CHARGE_LEVEL, 0, "week/battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_CONSUMED_PRODUCTION, 0, "week/consumed", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_WEEK, TAG_DB_AUTARKY, 0, "week/autarky", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, // MONTH @@ -259,6 +270,9 @@ cache_t cache[] = { { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_GRID_POWER_IN, 0, "month/grid/energy/in", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_GRID_POWER_OUT, 0, "month/grid/energy/out", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_CONSUMPTION, 0, "month/home/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_PM_0_POWER, 0, "month/pm_0/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_PM_1_POWER, 0, "month/pm_1/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_BAT_CHARGE_LEVEL, 0, "month/battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_CONSUMED_PRODUCTION, 0, "month/consumed", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_MONTH, TAG_DB_AUTARKY, 0, "month/autarky", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, // YEAR @@ -268,6 +282,9 @@ cache_t cache[] = { { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_GRID_POWER_IN, 0, "year/grid/energy/in", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_GRID_POWER_OUT, 0, "year/grid/energy/out", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_CONSUMPTION, 0, "year/home/energy", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_PM_0_POWER, 0, "year/pm_0/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_PM_1_POWER, 0, "year/pm_1/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_BAT_CHARGE_LEVEL, 0, "year/battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_CONSUMED_PRODUCTION, 0, "year/consumed", "", F_FLOAT_0, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_AUTARKY, 0, "year/autarky", "", F_FLOAT_0, UNIT_PERCENT, 1, 0, false, false, false }, // WALLBOX @@ -275,7 +292,7 @@ cache_t cache[] = { { 0, TAG_EMS_POWER_WB_SOLAR, 0, "wallbox/solar/power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, { 0, TAG_EMS_BATTERY_TO_CAR_MODE, 0, "wallbox/battery_to_car", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, { 0, TAG_EMS_BATTERY_BEFORE_CAR_MODE, 0, "wallbox/battery_before_car", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { 0, TAG_EMS_GET_WB_DISCHARGE_BAT_UNTIL, 0, "wallbox/battery_discharge_until", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { 0, TAG_EMS_GET_WB_DISCHARGE_BAT_UNTIL, 0, "wallbox/battery_discharge_until", "", F_AUTO, UNIT_PERCENT, 1, 0, false, false, false }, { 0, TAG_EMS_GET_WALLBOX_ENFORCE_POWER_ASSIGNMENT, 0, "wallbox/disable_battery_at_mix_mode", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, { TAG_WB_DATA, TAG_WB_DEVICE_STATE, 0, "wallbox/status", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, { TAG_WB_DATA, TAG_WB_PM_ACTIVE_PHASES, 0, "wallbox/active_phases", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, @@ -293,6 +310,18 @@ cache_t cache[] = { std::vector RscpMqttCache(cache, cache + sizeof(cache) / sizeof(cache_t)); cache_t templates[] = { + // DAY + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_BAT_POWER_IN, 1, "day/%d/%d/%d/battery/energy/charge", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_BAT_POWER_OUT, 1, "day/%d/%d/%d/battery/energy/discharge", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_DC_POWER, 1, "day/%d/%d/%d/solar/energy", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_GRID_POWER_IN, 1, "day/%d/%d/%d/grid/energy/in", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_GRID_POWER_OUT, 1, "day/%d/%d/%d/grid/energy/out", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_CONSUMPTION, 1, "day/%d/%d/%d/home/energy", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_PM_0_POWER, 1, "day/%d/%d/%d/pm_0/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_PM_1_POWER, 1, "day/%d/%d/%d/pm_1/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_BAT_CHARGE_LEVEL, 1, "day/%d/%d/%d/battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_CONSUMED_PRODUCTION, 1, "day/%d/%d/%d/consumed", "", F_FLOAT_0, UNIT_PERCENT, 1, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_DAY, TAG_DB_AUTARKY, 1, "day/%d/%d/%d/autarky", "", F_FLOAT_0, UNIT_PERCENT, 1, 0, false, false, false }, // YEAR { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_BAT_POWER_IN, 1, "history/%d/battery/energy/charge", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_BAT_POWER_OUT, 1, "history/%d/battery/energy/discharge", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, @@ -300,49 +329,32 @@ cache_t templates[] = { { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_GRID_POWER_IN, 1, "history/%d/grid/energy/in", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_GRID_POWER_OUT, 1, "history/%d/grid/energy/out", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_CONSUMPTION, 1, "history/%d/home/energy", "", F_FLOAT_0, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_PM_0_POWER, 1, "history/%d/pm_0/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_PM_1_POWER, 1, "history/%d/pm_1/energy", "", F_FLOAT_2, UNIT_KWH, 1000, 0, false, false, false }, + { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_BAT_CHARGE_LEVEL, 1, "history/%d/battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_CONSUMED_PRODUCTION, 1, "history/%d/consumed", "", F_FLOAT_0, UNIT_PERCENT, 1, 0, false, false, false }, { TAG_DB_HISTORY_DATA_YEAR, TAG_DB_AUTARKY, 1, "history/%d/autarky", "", F_FLOAT_0, UNIT_PERCENT, 1, 0, false, false, false }, - // TAG_BAT_DATA (1) - { TAG_BAT_DATA, TAG_BAT_RSOC, 0, "battery/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_MODULE_VOLTAGE, 0, "battery/voltage", "", F_FLOAT_2, UNIT_V, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_CURRENT, 0, "battery/current", "", F_FLOAT_2, UNIT_A, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_CHARGE_CYCLES, 0, "battery/cycles", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_STATUS_CODE, 0, "battery/status", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_ERROR_CODE, 0, "battery/error", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_DEVICE_NAME, 0, "battery/name", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_DCB_COUNT, 0, "battery/dcb/count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_TRAINING_MODE, 0, "battery/training", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_MAX_DCB_CELL_TEMPERATURE, 0, "battery/temperature/max", "", F_FLOAT_1, UNIT_GRAD_C, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_MIN_DCB_CELL_TEMPERATURE, 0, "battery/temperature/min", "", F_FLOAT_1, UNIT_GRAD_C, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_ASOC, 0, "battery/soh", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_ROLE, 0, "battery/role", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_CAPACITY, 0, "battery/specified_capacity", "", F_AUTO, UNIT_WH, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_DSCHARGE_POWER, 0, "battery/specified_discharge_power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_CHARGE_POWER, 0, "battery/specified_charge_power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_MAX_DCB_COUNT, 0, "battery/specified_max_dcb_count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_USABLE_CAPACITY, 0, "battery/usable_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_USABLE_REMAINING_CAPACITY, 0, "battery/usable_remaining_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_DESIGN_CAPACITY, 0, "battery/design_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, - // TAG_BAT_DATA (2) - { TAG_BAT_DATA, TAG_BAT_RSOC, 1, "battery/%d/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_MODULE_VOLTAGE, 1, "battery/%d/voltage", "", F_FLOAT_2, UNIT_V, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_CURRENT, 1, "battery/%d/current", "", F_FLOAT_2, UNIT_A, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_CHARGE_CYCLES, 1, "battery/%d/cycles", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_STATUS_CODE, 1, "battery/%d/status", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_ERROR_CODE, 1, "battery/%d/error", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_DEVICE_NAME, 1, "battery/%d/name", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_DCB_COUNT, 1, "battery/%d/dcb/count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_TRAINING_MODE, 1, "battery/%d/training", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_MAX_DCB_CELL_TEMPERATURE, 1, "battery/%d/temperature/max", "", F_FLOAT_1, UNIT_GRAD_C, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_MIN_DCB_CELL_TEMPERATURE, 1, "battery/%d/temperature/min", "", F_FLOAT_1, UNIT_GRAD_C, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_ROLE, 1, "battery/%d/role", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_CAPACITY, 1, "battery/%d/specified_capacity", "", F_AUTO, UNIT_WH, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_DSCHARGE_POWER, 1, "battery/%d/specified_discharge_power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_CHARGE_POWER, 1, "battery/%d/specified_charge_power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, - { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_MAX_DCB_COUNT, 1, "battery/%d/specified_max_dcb_count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_USABLE_CAPACITY, 0, "battery/%d/usable_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_USABLE_REMAINING_CAPACITY, 0, "battery/%d/usable_remaining_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, - { TAG_BAT_DATA, TAG_BAT_DESIGN_CAPACITY, 0, "battery/%d/design_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, + // TAG_BAT_DATA + { TAG_BAT_DATA, TAG_BAT_RSOC, 1, "%s/rsoc", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_MODULE_VOLTAGE, 1, "%s/voltage", "", F_FLOAT_2, UNIT_V, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_CURRENT, 1, "%s/current", "", F_FLOAT_2, UNIT_A, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_CHARGE_CYCLES, 1, "%s/cycles", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_STATUS_CODE, 1, "%s/status", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_ERROR_CODE, 1, "%s/error", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_DEVICE_NAME, 1, "%s/name", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_DCB_COUNT, 1, "%s/dcb/count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_TRAINING_MODE, 1, "%s/training", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_MAX_DCB_CELL_TEMPERATURE, 1, "%s/temperature/max", "", F_FLOAT_1, UNIT_GRAD_C, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_MIN_DCB_CELL_TEMPERATURE, 1, "%s/temperature/min", "", F_FLOAT_1, UNIT_GRAD_C, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_ASOC, 1, "%s/soh", "", F_FLOAT_1, UNIT_PERCENT, 1, 0, false, false, false }, + { TAG_BAT_SPECIFICATION, TAG_BAT_ROLE, 1, "%s/role", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_CAPACITY, 1, "%s/specified_capacity", "", F_AUTO, UNIT_WH, 1, 0, false, false, false }, + { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_DSCHARGE_POWER, 1, "%s/specified_discharge_power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, + { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_CHARGE_POWER, 1, "%s/specified_charge_power", "", F_AUTO, UNIT_W, 1, 0, false, false, false }, + { TAG_BAT_SPECIFICATION, TAG_BAT_SPECIFIED_MAX_DCB_COUNT, 1, "%s/specified_max_dcb_count", "", F_AUTO, UNIT_NONE, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_USABLE_CAPACITY, 1, "%s/usable_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_USABLE_REMAINING_CAPACITY, 1, "%s/usable_remaining_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, + { TAG_BAT_DATA, TAG_BAT_DESIGN_CAPACITY, 1, "%s/design_capacity", "", F_AUTO, UNIT_AH, 1, 0, false, false, false }, // DCB { TAG_BAT_DCB_INFO, TAG_BAT_DCB_MAX_CHARGE_VOLTAGE, 1, "battery/dcb/%d/max_charge_voltage", "", F_FLOAT_2, UNIT_V, 1, 0, false, false, false }, { TAG_BAT_DCB_INFO, TAG_BAT_DCB_MAX_CHARGE_CURRENT, 1, "battery/dcb/%d/max_charge_current", "", F_FLOAT_2, UNIT_A, 1, 0, false, false, false }, @@ -398,40 +410,42 @@ typedef struct _rec_cache_t { char unit[UNIT_SIZE]; int type; int refresh_count; + bool queue; bool done; } rec_cache_t; rec_cache_t rec_cache[] = { - { 0, TAG_EMS_REQ_START_MANUAL_CHARGE, "set/manual_charge", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, true }, - { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_WEATHER_REGULATED_CHARGE_ENABLED, "set/weather_regulation", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_POWER_LIMITS_USED, "set/power_limits", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_MAX_CHARGE_POWER, "set/max_charge_power", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, true }, - { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_MAX_DISCHARGE_POWER, "set/max_discharge_power", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, true }, - { TAG_EMS_REQ_SET_POWER, TAG_EMS_REQ_SET_POWER_MODE, "power_mode: mode", "", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, 0, true }, - { TAG_EMS_REQ_SET_POWER, TAG_EMS_REQ_SET_POWER_VALUE, "power_mode: value", "", "", "", "", "", UNIT_NONE, RSCP::eTypeInt32, 0, true }, - { TAG_SE_REQ_SET_EP_RESERVE, TAG_SE_PARAM_EP_RESERVE, "set/reserve/percent", PAYLOAD_REGEX_2_DIGIT, "", "", "", "", UNIT_PERCENT, RSCP::eTypeFloat32, -1, true }, - { TAG_SE_REQ_SET_EP_RESERVE, TAG_SE_PARAM_EP_RESERVE_W, "set/reserve/energy", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_WH, RSCP::eTypeFloat32, -1, true }, - { 0, 0, "set/power_mode", "^auto$|^idle:[0-9]{1,4}$|^charge:[0-9]{1,5}:[0-9]{1,4}$|^discharge:[0-9]{1,5}:[0-9]{1,4}$|^grid_charge:[0-9]{1,5}:[0-9]{1,4}$", "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/idle_period", SET_IDLE_PERIOD_REGEX, "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, TAG_EMS_REQ_SET_BATTERY_TO_CAR_MODE, "set/wallbox/battery_to_car", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, TAG_EMS_REQ_SET_BATTERY_BEFORE_CAR_MODE, "set/wallbox/battery_before_car", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, TAG_EMS_REQ_SET_WB_DISCHARGE_BAT_UNTIL, "set/wallbox/battery_discharge_until", PAYLOAD_REGEX_2_DIGIT, "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, TAG_EMS_REQ_SET_WALLBOX_ENFORCE_POWER_ASSIGNMENT, "set/wallbox/disable_battery_at_mix_mode", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { TAG_WB_REQ_DATA, TAG_WB_EXTERN_DATA, "set/wallbox/control", "^solar:[0-9]{1,2}$|^mix:[0-9]{1,2}$|^stop$", "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { TAG_WB_REQ_DATA, TAG_WB_REQ_SET_NUMBER_PHASES, "set/wallbox/number_phases", "^1|3$", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, 0, "set/requests/pm", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/requests/pvi", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/requests/dcb", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/soc_limiter", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/limit/charge/soc", PAYLOAD_REGEX_0_100, "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, 0, "set/limit/charge/durable", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, 0, "set/limit/discharge/soc", PAYLOAD_REGEX_0_100, "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, 0, "set/limit/discharge/durable", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true }, - { 0, 0, "set/limit/discharge/by_home_power", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, true }, - { 0, 0, "set/log", "^true|on|1$", "true", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/health", "^true|on|1$", "true", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/force", "[a-zA-z0-9/_.*]*", "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, true }, - { 0, 0, "set/interval", "(^[1-9]|10$)", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true } + { 0, TAG_EMS_REQ_START_MANUAL_CHARGE, "set/manual_charge", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, false, true }, + { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_WEATHER_REGULATED_CHARGE_ENABLED, "set/weather_regulation", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_POWER_LIMITS_USED, "set/power_limits", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_MAX_CHARGE_POWER, "set/max_charge_power", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, false, true }, + { TAG_EMS_REQ_SET_POWER_SETTINGS, TAG_EMS_MAX_DISCHARGE_POWER, "set/max_discharge_power", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, false, true }, + { TAG_EMS_REQ_SET_POWER, TAG_EMS_REQ_SET_POWER_MODE, "power_mode: mode", "", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, 0, false, true }, + { TAG_EMS_REQ_SET_POWER, TAG_EMS_REQ_SET_POWER_VALUE, "power_mode: value", "", "", "", "", "", UNIT_NONE, RSCP::eTypeInt32, 0, false, true }, + { TAG_SE_REQ_SET_EP_RESERVE, TAG_SE_PARAM_EP_RESERVE, "set/reserve/percent", PAYLOAD_REGEX_0_100, "", "", "", "", UNIT_PERCENT, RSCP::eTypeFloat32, -1, false, true }, + { TAG_SE_REQ_SET_EP_RESERVE, TAG_SE_PARAM_EP_RESERVE_W, "set/reserve/energy", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_WH, RSCP::eTypeFloat32, -1, false, true }, + { 0, 0, "set/power_mode", "^auto$|^idle:[0-9]{1,4}$|^charge:[0-9]{1,5}:[0-9]{1,4}$|^discharge:[0-9]{1,5}:[0-9]{1,4}$|^grid_charge:[0-9]{1,5}:[0-9]{1,4}$", "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/idle_period", SET_IDLE_PERIOD_REGEX, "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, TAG_EMS_REQ_SET_BATTERY_TO_CAR_MODE, "set/wallbox/battery_to_car", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, TAG_EMS_REQ_SET_BATTERY_BEFORE_CAR_MODE, "set/wallbox/battery_before_car", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, TAG_EMS_REQ_SET_WB_DISCHARGE_BAT_UNTIL, "set/wallbox/battery_discharge_until", PAYLOAD_REGEX_2_DIGIT, "", "", "", "", UNIT_PERCENT, RSCP::eTypeUChar8, -1, false, true }, + { 0, TAG_EMS_REQ_SET_WALLBOX_ENFORCE_POWER_ASSIGNMENT, "set/wallbox/disable_battery_at_mix_mode", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { TAG_WB_REQ_DATA, TAG_WB_EXTERN_DATA, "set/wallbox/control", "^solar:[0-9]{1,2}$|^mix:[0-9]{1,2}$|^stop$", "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { TAG_WB_REQ_DATA, TAG_WB_REQ_SET_NUMBER_PHASES, "set/wallbox/number_phases", "^1|3$", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, 0, "set/requests/pm", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/requests/pvi", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/requests/dcb", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/soc_limiter", "^true|on|1$", "true", "^false|off|0$", "false", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/limit/charge/soc", PAYLOAD_REGEX_0_100, "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, 0, "set/limit/charge/durable", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, 0, "set/limit/discharge/soc", PAYLOAD_REGEX_0_100, "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, 0, "set/limit/discharge/durable", "^true|on|1$", "1", "^false|off|0$", "0", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, 0, "set/limit/discharge/by_home_power", PAYLOAD_REGEX_5_DIGIT, "", "", "", "", UNIT_W, RSCP::eTypeUInt32, -1, false, true }, + { 0, 0, "set/log", "^true|on|1$", "true", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/health", "^true|on|1$", "true", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/force", "[a-zA-z0-9/_.*]*", "", "", "", "", UNIT_NONE, RSCP::eTypeBool, -1, false, true }, + { 0, 0, "set/interval", "(^[1-9]|10$)", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, false, true }, + { 0, 0, "set/request/day", "^[0-9]{4}-[0-1]?[0-9]-[0-3]?[0-9]$", "", "", "", "", UNIT_NONE, RSCP::eTypeUChar8, -1, true, true } }; std::vector RscpMqttReceiveCache(rec_cache, rec_cache + sizeof(rec_cache) / sizeof(rec_cache_t)); diff --git a/TOPICS.md b/TOPICS.md index de586d0..6e83c22 100644 --- a/TOPICS.md +++ b/TOPICS.md @@ -6,7 +6,6 @@ All topics are listed with the default prefix "e3dc". | Device / Tag | MQTT Topic | Values / [Unit] | | --- | --- | --- | -| Current Autarky | e3dc/autarky | [%] | | Battery Charge Cycles | e3dc/battery/cycles | | | Battery Current | e3dc/battery/current | [A] | | Battery Design Capacity | e3dc/battery/design_capacity | [Ah] | @@ -14,57 +13,59 @@ All topics are listed with the default prefix "e3dc". | Battery Energy Charge (today) | e3dc/battery/energy/charge | [kWh] | | Battery Energy Discharge (today) | e3dc/battery/energy/discharge | [kWh] | | Battery Error Code | e3dc/battery/error | | -| Battery Module Count | e3dc/battery/dcb/count | | -| Battery Module Max Charge Voltage | e3dc/battery/dcb/<#>/max_charge_voltage | [V] | -| Battery Module Max Charge Current | e3dc/battery/dcb/<#>/max_charge_current | [A] | -| Battery Module Max Discharge Current | e3dc/battery/dcb/<#>/max_discharge_current | [A] | -| Battery Module Full Charge Capacity | e3dc/battery/dcb/<#>/full_charge_capacity | [Ah] | -| Battery Module Remaining Capacity | e3dc/battery/dcb/<#>/remaining_capacity | [Ah] | -| Battery Module State of Charge (SOC) | e3dc/battery/dcb/<#>/soc | [%] | -| Battery Module State of Health (SOH) | e3dc/battery/dcb/<#>/soh | [%] | | Battery Module Charge Cycles | e3dc/battery/dcb/<#>/cycles | | -| Battery Module Current | e3dc/battery/dcb/<#>/current | [A] | -| Battery Module Voltage | e3dc/battery/dcb/<#>/voltage | [V] | +| Battery Module Count | e3dc/battery/dcb/count | | | Battery Module Current 30s Average | e3dc/battery/dcb/<#>/current_avg_30s | [A] | -| Battery Module Voltage 30s Average | e3dc/battery/dcb/<#>/voltage_avg_30s | [V] | -| Battery Module Nr Sensor | e3dc/battery/dcb/<#>/nr_sensor | | +| Battery Module Current | e3dc/battery/dcb/<#>/current | [A] | | Battery Module Design Capacity | e3dc/battery/dcb/<#>/design_capacity | [Ah] | | Battery Module Design Voltage | e3dc/battery/dcb/<#>/design_voltage | [V] | -| Battery Module Low Temperature | e3dc/battery/dcb/<#>/charge_low_temperature | [°C] | +| Battery Module Device Name | e3dc/battery/dcb/<#>/device_name | | +| Battery Module Firmware | e3dc/battery/dcb/<#>/firmware_version | | +| Battery Module Full Charge Capacity | e3dc/battery/dcb/<#>/full_charge_capacity | [Ah] | | Battery Module High Temperature | e3dc/battery/dcb/<#>/charge_high_temperature | [°C] | +| Battery Module Low Temperature | e3dc/battery/dcb/<#>/charge_low_temperature | [°C] | | Battery Module Manufacture Date | e3dc/battery/dcb/<#>/manufacture_date | | -| Battery Module Serial Number | e3dc/battery/dcb/<#>/serial_number | | -| Battery Module Protocol Version | e3dc/battery/dcb/<#>/protocol_version | | -| Battery Module Firmware | e3dc/battery/dcb/<#>/firmware_version | | -| Battery Module Table Version | e3dc/battery/dcb/<#>/table_version | | -| Battery Module PCB Version | e3dc/battery/dcb/<#>/pcb_version | | -| Battery Module Number of Series Cells | e3dc/battery/dcb/<#>/nr_series_cell | | -| Battery Module Number of Parallel Cells | e3dc/battery/dcb/<#>/nr_parallel_cell | | | Battery Module Manufacture Name | e3dc/battery/dcb/<#>/manufacture_name | | -| Battery Module Device Name | e3dc/battery/dcb/<#>/device_name | | +| Battery Module Max Charge Current | e3dc/battery/dcb/<#>/max_charge_current | [A] | +| Battery Module Max Charge Voltage | e3dc/battery/dcb/<#>/max_charge_voltage | [V] | +| Battery Module Max Discharge Current | e3dc/battery/dcb/<#>/max_discharge_current | [A] | +| Battery Module Number of Parallel Cells | e3dc/battery/dcb/<#>/nr_parallel_cell | | +| Battery Module Number of Series Cells | e3dc/battery/dcb/<#>/nr_series_cell | | +| Battery Module Number Sensor | e3dc/battery/dcb/<#>/nr_sensor | | +| Battery Module PCB Version | e3dc/battery/dcb/<#>/pcb_version | | +| Battery Module Protocol Version | e3dc/battery/dcb/<#>/protocol_version | | +| Battery Module Remaining Capacity | e3dc/battery/dcb/<#>/remaining_capacity | [Ah] | | Battery Module Serial Code | e3dc/battery/dcb/<#>/serial_code | | -| Battery Voltage | e3dc/battery/voltage | [V] | +| Battery Module Serial Number | e3dc/battery/dcb/<#>/serial_number | | +| Battery Module State of Charge (SOC) | e3dc/battery/dcb/<#>/soc | [%] | +| Battery Module State of Health (SOH) | e3dc/battery/dcb/<#>/soh | [%] | +| Battery Module Table Version | e3dc/battery/dcb/<#>/table_version | | +| Battery Module Voltage 30s Average | e3dc/battery/dcb/<#>/voltage_avg_30s | [V] | +| Battery Module Voltage | e3dc/battery/dcb/<#>/voltage | [V] | | Battery Remaining Capacity | e3dc/battery/usable_remaining_capacity | [Ah] | | Battery Role (?) | e3dc/battery/role | | | Battery RSOC | e3dc/battery/rsoc | [%] | | Battery SOC | e3dc/battery/soc | [%] | | Battery SOH | e3dc/battery/soh | [%] | | Battery Specified Capacity | e3dc/battery/specified_capacity | [Wh] | -| Battery Specified Discharge Power | e3dc/battery/specified_discharge_power | [W] | | Battery Specified Charge Power | e3dc/battery/specified_charge_power | [W] | +| Battery Specified Discharge Power | e3dc/battery/specified_discharge_power | [W] | | Battery Specified Max DCB Count | e3dc/battery/specified_max_dcb_count | | | Battery Status Code | e3dc/battery/status | | +| Battery Status | e3dc/battery/state | "EMPTY", "CHARGING", "DISCHARGING", "FULL", "PENDING" | | Battery Temperature Max | e3dc/battery/temperature/max | [°C] | | Battery Temperature Min | e3dc/battery/temperature/min | [°C] | | Battery Training Mode | e3dc/battery/training | (0-2) | | Battery Usable Capacity | e3dc/battery/usable_capacity | [Ah] | +| Battery Voltage | e3dc/battery/voltage | [V] | +| Current Autarky | e3dc/autarky | [%] | | Current Consumed Production | e3dc/consumed | [%] | | EMS Addon Power | e3dc/addon/power | [W] | | EMS Balanced Phase | e3dc/ems/balanced_phases/L1 | (true/false) | | EMS Balanced Phase | e3dc/ems/balanced_phases/L2 | (true/false) | | EMS Balanced Phase | e3dc/ems/balanced_phases/L3 | (true/false) | -| EMS Battery Count | e3dc/system/battery_count | | | EMS Battery Charge Limit | e3dc/ems/battery_charge_limit | [W] | +| EMS Battery Count | e3dc/system/battery_count | | | EMS Battery Discharge Limit | e3dc/ems/battery_discharge_limit | [W] | | EMS Battery Power | e3dc/battery/power | [W] | | EMS Charging Lock | e3dc/ems/charging_lock | (true/false) | @@ -108,10 +109,22 @@ All topics are listed with the default prefix "e3dc". | EMS Weather Regulation Enable | e3dc/ems/weather_regulation | (true/false) | | EP Reserve | e3dc/reserve/procent | [%] | | EP Reserve Energy | e3dc/reserve/energy | [Wh] | -| EP Reserve Max Energy | e3dc/reserve/max | [Wh] | | EP Reserve Last SOC | e3dc/reserve/last_soc | [%] | +| EP Reserve Max Energy | e3dc/reserve/max | [Wh] | | Grid In Energy "Einspeisung" (today) | e3dc/grid/energy/in | [kWh] | | Grid Out Energy "Netzbezug" (today) | e3dc/grid/energy/out | [kWh] | +| Grid Status | e3dc/grid/state | "IN", "OUT" | +| Historical Data Autarky * | e3dc/day////autarky | [%] | +| Historical Data Battery Energy Charge * | e3dc/day////battery/energy/charge | [kWh] | +| Historical Data Consumed Production * | e3dc/day////consumed | [%] | +| Historical Data Energy Discharge * | e3dc/day////battery/energy/discharge | [kWh] | +| Historical Data Grid In Energy "Einspeisung" * | e3dc/day////grid/energy/in | [kWh] | +| Historical Data Grid Out Energy "Netzbezug" * | e3dc/day////grid/energy/out | [kWh] | +| Historical Data Home Energy * | e3dc/day////home/energy | [kWh] | +| Historical Data PM 0 Energy * | e3dc/day////pm_0/energy | [kWh] | +| Historical Data PM 1 Energy * | e3dc/day////pm_1/energy | [kWh] | +| Historical Data SOC * | e3dc/day////battery/rsoc | [%] | +| Historical Data Solar Energy * | e3dc/day////solar/energy | [kWh] | | Home Energy | e3dc/home/energy (today) | [kWh] | | Month Autarky | e3dc/month/autarky | [%] | | Month Battery Energy Charge | e3dc/month/battery/energy/charge | [kWh] | @@ -137,25 +150,25 @@ All topics are listed with the default prefix "e3dc". | PVI Apparent Power L1 | e3dc/pvi/apparent_power/L1 | [VA] | | PVI Apparent Power L2 | e3dc/pvi/apparent_power/L2 | [VA] | | PVI Apparent Power L3 | e3dc/pvi/apparent_power/L3 | [VA] | -| PVI COS Phi | e3dc/pvi/cos_phi_value | | -| PVI COS Phi | e3dc/pvi/cos_phi_is_active | | | PVI COS Phi | e3dc/pvi/cos_phi_excited | | +| PVI COS Phi | e3dc/pvi/cos_phi_is_active | | +| PVI COS Phi | e3dc/pvi/cos_phi_value | | | PVI Current L1 | e3dc/pvi/current/L1 | [A] | | PVI Current L2 | e3dc/pvi/current/L2 | [A] | | PVI Current L3 | e3dc/pvi/current/L3 | [A] | -| PVI Energy L1 | e3dc/pvi/energy_all/L1 | [Wh] | -| PVI Energy L2 | e3dc/pvi/energy_all/L2 | [Wh] | -| PVI Energy L3 | e3dc/pvi/energy_all/L3 | [Wh] | | PVI Energy Day L1 | e3dc/pvi/energy_day/L1 | [Wh] | | PVI Energy Day L2 | e3dc/pvi/energy_day/L2 | [Wh] | | PVI Energy Day L3 | e3dc/pvi/energy_day/L3 | [Wh] | | PVI Energy Grid L1 | e3dc/pvi/energy_grid_consumption/L1 | [Wh] | | PVI Energy Grid L2 | e3dc/pvi/energy_grid_consumption/L2 | [Wh] | | PVI Energy Grid L3 | e3dc/pvi/energy_grid_consumption/L3 | [Wh] | +| PVI Energy L1 | e3dc/pvi/energy_all/L1 | [Wh] | +| PVI Energy L2 | e3dc/pvi/energy_all/L2 | [Wh] | +| PVI Energy L3 | e3dc/pvi/energy_all/L3 | [Wh] | | PVI Energy String1 | e3dc/pvi/energy_all/string_1 | Wh | | PVI Energy String2 | e3dc/pvi/energy_all/string_2 | Wh | -| PVI Frequency | e3dc/pvi/frequency_under | [Hz] | | PVI Frequency | e3dc/pvi/frequency_over | [Hz] | +| PVI Frequency | e3dc/pvi/frequency_under | [Hz] | | PVI Max Apparent Power L1 | e3dc/pvi/max_apparent_power/L1 | [VA] | | PVI Max Apparent Power L2 | e3dc/pvi/max_apparent_power/L2 | [VA] | | PVI Max Apparent Power L3 | e3dc/pvi/max_apparent_power/L3 | [VA] | @@ -166,49 +179,49 @@ All topics are listed with the default prefix "e3dc". | PVI Reactive Power L1 | e3dc/pvi/reactive_power/L1 | [var] | | PVI Reactive Power L2 | e3dc/pvi/reactive_power/L2 | [var] | | PVI Reactive Power L3 | e3dc/pvi/reactive_power/L3 | [var] | -| PVI Slope | e3dc/pvi/voltage_monitoring_slope_up | [V] | | PVI Slope | e3dc/pvi/voltage_monitoring_slope_down | [V] | -| PVI String Count | e3dc/pvi/used_string_count | | +| PVI Slope | e3dc/pvi/voltage_monitoring_slope_up | [V] | | PVI String1 Current | e3dc/pvi/current/string_1 | [A] | | PVI String1 Power | e3dc/pvi/power/string_1 | [W] | | PVI String1 Voltage | e3dc/pvi/voltage/string_1 | [V] | | PVI String2 Current | e3dc/pvi/current/string_2 | [A] | | PVI String2 Power | e3dc/pvi/power/string_2 | [W] | | PVI String2 Voltage | e3dc/pvi/voltage/string_2 | [V] | +| PVI String Count | e3dc/pvi/used_string_count | | | PVI Temperature 1 | e3dc/pvi/temperature/1 | [°C] | | PVI Temperature 2 | e3dc/pvi/temperature/2 | [°C] | | PVI Temperature 3 | e3dc/pvi/temperature/3 | [°C] | | PVI Temperature 4 | e3dc/pvi/temperature/4 | [°C] | -| PVI Threshold | e3dc/pvi/voltage_monitoring_threshold_top | [V] | | PVI Threshold | e3dc/pvi/voltage_monitoring_threshold_bottom | [V] | +| PVI Threshold | e3dc/pvi/voltage_monitoring_threshold_top | [V] | | PVI Voltage L1 | e3dc/pvi/voltage/L1 | [V] | | PVI Voltage L2 | e3dc/pvi/voltage/L2 | [V] | | PVI Voltage L3 | e3dc/pvi/voltage/L3 | [V] | | Serial Number | e3dc/system/serial_number | "S10-XXXXXXXXXXXX" | -| Software Release | e3dc/system/software | "S10_XXXX_XXX" | | SOC limiter | e3dc/limit/charge/durable | (0,1) | | SOC limiter | e3dc/limit/charge/soc | [%] | | SOC limiter | e3dc/limit/discharge/by_home_power | [W] | | SOC limiter | e3dc/limit/discharge/durable | (0,1) | | SOC limiter | e3dc/limit/discharge/soc | [%] | +| Software Release | e3dc/system/software | "S10_XXXX_XXX" | | Solar Energy | e3dc/solar/energy | [kWh] | | Time Zone | e3dc/time/zone | "Europe/City" | -| Wallbox battery | e3dc/wallbox/battery_to_car | (0,1) | -| Wallbox battery | e3dc/wallbox/battery_before_car | (0,1) | -| Wallbox battery | e3dc/wallbox/battery_discharge_until | [%] | -| Wallbox battery | e3dc/wallbox/disable_battery_at_mix_mode | (true/false) | -| Wallbox canceled | e3dc/wallbox/canceled | (true/false) | -| Wallbox charging | e3dc/wallbox/charging | (true/false) | -| Wallbox current | e3dc/wallbox/max_current | (true/false) | -| Wallbox locked | e3dc/wallbox/locked | (true/false) | -| Wallbox mode | e3dc/wallbox/sun_mode | (true/false) | -| Wallbox phases | e3dc/wallbox/active_phases | | -| Wallbox phases | e3dc/wallbox/number_phases | | -| Wallbox phases | e3dc/wallbox/number_used_phases | | -| Wallbox plugged | e3dc/wallbox/plugged | (true/false) | -| Wallbox power | e3dc/wallbox/total/power | [W] | -| Wallbox power | e3dc/wallbox/solar/power | [W] | -| Wallbox status | e3dc/wallbox/status | | +| Wallbox Battery | e3dc/wallbox/battery_before_car | (0,1) | +| Wallbox Battery | e3dc/wallbox/battery_discharge_until | [%] | +| Wallbox Battery | e3dc/wallbox/battery_to_car | (0,1) | +| Wallbox Battery | e3dc/wallbox/disable_battery_at_mix_mode | (true/false) | +| Wallbox Canceled | e3dc/wallbox/canceled | (true/false) | +| Wallbox Charging | e3dc/wallbox/charging | (true/false) | +| Wallbox Current | e3dc/wallbox/max_current | (true/false) | +| Wallbox Locked | e3dc/wallbox/locked | (true/false) | +| Wallbox Mode | e3dc/wallbox/sun_mode | (true/false) | +| Wallbox Phases | e3dc/wallbox/active_phases | | +| Wallbox Phases | e3dc/wallbox/number_phases | | +| Wallbox Phases | e3dc/wallbox/number_used_phases | | +| Wallbox Plugged | e3dc/wallbox/plugged | (true/false) | +| Wallbox Power | e3dc/wallbox/solar/power | [W] | +| Wallbox Power | e3dc/wallbox/total/power | [W] | +| Wallbox Status | e3dc/wallbox/status | | | Week Autarky | e3dc/week/autarky | [%] | | Week Battery Energy Charge | e3dc/week/battery/energy/charge | [kWh] | | Week Consumed Production | e3dc/week/consumed | [%] | @@ -223,8 +236,6 @@ All topics are listed with the default prefix "e3dc". | Year Energy Discharge | e3dc/year/battery/energy/discharge | [kWh] | | Year Grid In Energy "Einspeisung" | e3dc/year/grid/energy/in | [kWh] | | Year Grid Out Energy "Netzbezug" | e3dc/year/grid/energy/out | [kWh] | -| Year Home Energy | e3dc/year/home/energy | [kWh] | -| Year Solar Energy | e3dc/year/solar/energy | [kWh] | | Year History Autarky | e3dc/history//autarky | [%] | | Year History Battery Energy Charge | e3dc/history//battery/energy/charge | [kWh] | | Year History Consumed Production | e3dc/history//consumed | [%] | @@ -233,6 +244,8 @@ All topics are listed with the default prefix "e3dc". | Year History Grid Out Energy "Netzbezug" | e3dc/history//grid/energy/out | [kWh] | | Year History Home Energy | e3dc/history//home/energy | [kWh] | | Year History Solar Energy | e3dc/history//solar/energy | [kWh] | +| Year Home Energy | e3dc/year/home/energy | [kWh] | +| Year Solar Energy | e3dc/year/solar/energy | [kWh] | | Yesterday Autarky | e3dc/yesterday/autarky | [%] | | Yesterday Battery Energy Charge | e3dc/yesterday/battery/energy/charge | [kWh] | | Yesterday Battery SOC | e3dc/yesterday/battery/rsoc | [%] | @@ -244,6 +257,7 @@ All topics are listed with the default prefix "e3dc". | Yesterday Solar Energy | e3dc/yesterday/solar/energy | [kWh] | Energy topics are collected for today, yesterday and the current week, month, year and historical years if configured. +*) Historical data for a specific day can be queried by publishing "e3dc/set/request/day". If your system has more than one battery string (e.g. S10 Pro), you have to configure the parameter BATTERY_STRINGS accordingly. Battery topics that belong to a battery string are extended by the number of the battery string. @@ -280,11 +294,13 @@ Please find detailled information and examples in the [README](README.md). | Set battery before car mode | e3dc/set/wallbox/battery_before_car | (true/false) | | Set battery discharge until [%] | e3dc/set/wallbox/battery_discharge_until | [%] | | Set disable charging battery at mix mode | e3dc/set/wallbox/disable_battery_at_mix_mode | (true/false) | -| Set number of phases (1,3) | e3dc/set/wallbox/number_phases | 1 | +| Set number of phases (1,3) | e3dc/set/wallbox/number_phases | (1,3) | | Refresh all topics | e3dc/set/force | 1 | | Refresh specific topics | e3dc/set/force | "e3dc/history/2021.*" | +| Query data for a specific day | e3dc/set/request/day | "2023-12-31" | | Log all topics and payloads to the log file | e3dc/set/log | 1 | -| Set refresh interval [sec] | e3dc/set/interval | (1-10) | +| Log internal stuff to the log file | e3dc/set/health | 1 | +| Set refresh interval [sec] | e3dc/set/interval | (1-300) | | Enable PM requests | e3dc/set/requests/pm | (true/false) | | Enable PVI requests | e3dc/set/requests/pvi | (true/false) | | Enable DCB requests | e3dc/set/requests/dcb | (true/false) | diff --git a/config.template b/config.template index f04c5ba..c0111a3 100644 --- a/config.template +++ b/config.template @@ -34,7 +34,7 @@ DISABLE_MQTT_PUBLISH=false AUTO_REFRESH=false #--external Power Meter (i.e. S10 Mini) PM_EXTERN=false -#--Year of installation +#--Start of Operation HISTORY_START_YEAR=2022 #-MQTT Topics @@ -75,6 +75,7 @@ INFLUXDB_PORT=8086 INFLUXDB_VERSION=2 INFLUXDB_MEASUREMENT=e3dc INFLUXDB_TOPIC=e3dc/[a-z]+/power +INFLUXDB_TOPIC=e3dc/day/.* #-InfluxDB v1 #--if compiled with InfluxDB option diff --git a/request_days.sh b/request_days.sh new file mode 100755 index 0000000..0591552 --- /dev/null +++ b/request_days.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +if [ $# -ne 5 ]; then + echo "Usage: $0 " + exit 1 +fi + +broker=$1 +port=$2 +prefix=$3 +start_date=$4 +end_date=$5 + +if ! [[ $port =~ ^[0-9]+$ ]]; then + echo "Invalid port number. Please provide a positive integer." + exit 1 +fi +if (($port < 1)) || (($port > 65535)); then + echo "Invalid port number. Port must be between 1 and 65535." + exit 1 +fi +if ! [[ $start_date =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || ! [[ $end_date =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then + echo "Invalid date format. Please use YYYY-MM-DD." + exit 1 +fi +if ! date -d "$start_date" &> /dev/null; then + echo "Invalid start date: $start_date" + exit 1 +fi +if ! date -d "$end_date" &> /dev/null; then + echo "Invalid end date: $end_date" + exit 1 +fi + +end_date=$(date -d "$end_date + 1 day" +"%Y-%m-%d") + +while [[ $start_date < $end_date ]]; do + echo "Requesting data for $start_date" + mosquitto_pub -h $broker -p $port -t "$prefix/set/request/day" -m "$start_date" + start_date=$(date -d "$start_date + 1 day" +"%Y-%m-%d") +done