2222#include < regex>
2323#include < mutex>
2424
25- #define RSCP2MQTT_VERSION " 3.35 "
25+ #define RSCP2MQTT_VERSION " 3.36 "
2626
2727#define AES_KEY_SIZE 32
2828#define AES_BLOCK_SIZE 32
@@ -376,7 +376,7 @@ void addTemplTopicsIdx(int index, char *seg, int start, int n, int inc, bool fin
376376 return ;
377377}
378378
379- void addTemplTopics (uint32_t container, int index, char *seg, int start, int n, int inc, bool finalize) {
379+ void addTemplTopics (uint32_t container, int index, char *seg, int start, int n, int inc, int counter, bool finalize) {
380380 for (int c = start; c < n; c++) {
381381 for (std::vector<RSCP_MQTT::cache_t >::iterator it = RSCP_MQTT::RscpMqttCacheTempl.begin (); it != RSCP_MQTT::RscpMqttCacheTempl.end (); ++it) {
382382 if (it->container == container) {
@@ -395,7 +395,17 @@ void addTemplTopics(uint32_t container, int index, char *seg, int start, int n,
395395 snprintf (cache.topic , TOPIC_SIZE, it->topic , buffer);
396396 }
397397 strcpy (cache.unit , it->unit );
398- RSCP_MQTT::RscpMqttCache.push_back (cache);
398+ if (!counter) {
399+ RSCP_MQTT::RscpMqttCache.push_back (cache);
400+ } else {
401+ char buffer[TOPIC_SIZE];
402+ strcpy (buffer, cache.topic );
403+ for (int i = 1 ; i <= counter; i++) {
404+ if (counter >= 10 ) snprintf (cache.topic , TOPIC_SIZE, " %s/%.2d" , buffer, i);
405+ else snprintf (cache.topic , TOPIC_SIZE, " %s/%d" , buffer, i);
406+ RSCP_MQTT::RscpMqttCache.push_back (cache);
407+ }
408+ }
399409 }
400410 }
401411 }
@@ -406,8 +416,8 @@ void addTemplTopics(uint32_t container, int index, char *seg, int start, int n,
406416 return ;
407417}
408418
409- void addTopic (uint32_t container, uint32_t tag, char *topic, char *unit, int format, int divisor, int bit_to_bool, bool finalize) {
410- RSCP_MQTT::cache_t cache = { container, tag, 0 , " " , " " , format, " " , divisor, bit_to_bool, false , false , false , false , false };
419+ void addTopic (uint32_t container, uint32_t tag, int index, char *topic, char *unit, int format, int divisor, int bit_to_bool, bool finalize) {
420+ RSCP_MQTT::cache_t cache = { container, tag, index , " " , " " , format, " " , divisor, bit_to_bool, false , false , false , false , false };
411421 strcpy (cache.topic , topic);
412422 strcpy (cache.unit , unit);
413423 RSCP_MQTT::RscpMqttCache.push_back (cache);
@@ -1578,7 +1588,7 @@ void createRequest(SRscpFrameBuffer * frameBuffer) {
15781588 }
15791589
15801590 if (curr_year < l->tm_year + 1900 ) {
1581- addTemplTopics (TAG_DB_HISTORY_DATA_YEAR, 1 , NULL , curr_year, l->tm_year + 1900 , 0 , true );
1591+ addTemplTopics (TAG_DB_HISTORY_DATA_YEAR, 1 , NULL , curr_year, l->tm_year + 1900 , 0 , 0 , true );
15821592 curr_year = l->tm_year + 1900 ;
15831593 }
15841594
@@ -1694,6 +1704,8 @@ void createRequest(SRscpFrameBuffer * frameBuffer) {
16941704 if (cfg.dcb_requests ) {
16951705 for (uint8_t j = 0 ; j < cfg.bat_dcb_count [i]; j++) {
16961706 protocol.appendValue (&batteryContainer, TAG_BAT_REQ_DCB_INFO, j);
1707+ protocol.appendValue (&batteryContainer, TAG_BAT_REQ_DCB_ALL_CELL_TEMPERATURES, j); // Issue #103
1708+ protocol.appendValue (&batteryContainer, TAG_BAT_REQ_DCB_ALL_CELL_VOLTAGES, j); // Issue #103
16971709 }
16981710 }
16991711 if (!e3dc_ts) {
@@ -2276,7 +2288,12 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) {
22762288 cfg.bat_dcb_count [battery_nr] = protocol->getValueAsUChar8 (&containerData[i]);
22772289 cfg.bat_dcb_start [battery_nr] = battery_nr?cfg.bat_dcb_count [battery_nr - 1 ]:0 ;
22782290 storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag , 0 );
2279- 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 , true );
2291+ 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 , 0 , true );
2292+ if (cfg.bat_dcb_cell_voltages ) addTemplTopics (TAG_BAT_DCB_ALL_CELL_VOLTAGES, 1 , NULL , cfg.bat_dcb_start [battery_nr], cfg.bat_dcb_start [battery_nr] + cfg.bat_dcb_count [battery_nr], 1 , cfg.bat_dcb_cell_voltages , true );
2293+ if (cfg.bat_dcb_cell_temperatures ) addTemplTopics (TAG_BAT_DCB_ALL_CELL_TEMPERATURES, 1 , NULL , cfg.bat_dcb_start [battery_nr], cfg.bat_dcb_start [battery_nr] + cfg.bat_dcb_count [battery_nr], 1 , cfg.bat_dcb_cell_temperatures , true );
2294+ addTemplTopicsIdx (IDX_BATTERY_DCB_TEMPERATURE_MIN, NULL , cfg.bat_dcb_start [battery_nr], cfg.bat_dcb_start [battery_nr] + cfg.bat_dcb_count [battery_nr], 1 , false );
2295+ addTemplTopicsIdx (IDX_BATTERY_DCB_TEMPERATURE_MAX, NULL , cfg.bat_dcb_start [battery_nr], cfg.bat_dcb_start [battery_nr] + cfg.bat_dcb_count [battery_nr], 1 , false );
2296+ addTemplTopicsIdx (IDX_BATTERY_DCB_CELL_VOLTAGE, NULL , cfg.bat_dcb_start [battery_nr], cfg.bat_dcb_start [battery_nr] + cfg.bat_dcb_count [battery_nr], 1 , true );
22802297 break ;
22812298 }
22822299 case TAG_BAT_SPECIFICATION: {
@@ -2287,6 +2304,33 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) {
22872304 protocol->destroyValueData (container);
22882305 break ;
22892306 }
2307+ case TAG_BAT_DCB_ALL_CELL_VOLTAGES:
2308+ case TAG_BAT_DCB_ALL_CELL_TEMPERATURES: {
2309+ int dcb_nr = 0 ;
2310+ std::vector<SRscpValue> container = protocol->getValueAsContainer (&containerData[i]);
2311+ for (size_t j = 0 ; j < container.size (); j++) {
2312+ if (container[j].tag == TAG_BAT_DCB_INDEX) {
2313+ dcb_nr = protocol->getValueAsUInt16 (&container[j]) + cfg.bat_dcb_start [battery_nr];
2314+ } else {
2315+ if (container[j].dataType == RSCP::eTypeContainer) {
2316+ std::vector<SRscpValue> subcontainer = protocol->getValueAsContainer (&container[j]);
2317+ if (containerData[i].tag == TAG_BAT_DCB_ALL_CELL_TEMPERATURES) {
2318+ storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(subcontainer[0 ]), 0 , IDX_BATTERY_DCB_TEMPERATURE_MIN + dcb_nr);
2319+ storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(subcontainer[1 ]), 0 , IDX_BATTERY_DCB_TEMPERATURE_MAX + dcb_nr);
2320+ } else if (containerData[i].tag == TAG_BAT_DCB_ALL_CELL_VOLTAGES) {
2321+ storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(subcontainer[0 ]), 0 , IDX_BATTERY_DCB_CELL_VOLTAGE + dcb_nr);
2322+ }
2323+ if (cfg.bat_dcb_cell_voltages || cfg.bat_dcb_cell_temperatures ) {
2324+ for (size_t k = 0 ; k < subcontainer.size (); k++) {
2325+ if (storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(subcontainer[k]), containerData[i].tag , dcb_nr) < 0 ) break ;
2326+ }
2327+ }
2328+ }
2329+ }
2330+ }
2331+ protocol->destroyValueData (container);
2332+ break ;
2333+ }
22902334 default : {
22912335 if (response->tag == TAG_BAT_DATA) storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag , battery_nr);
22922336 else storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag , (response->tag == TAG_PM_DATA)?pm_nr:0 );
@@ -2379,15 +2423,15 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) {
23792423 case TAG_PVI_TEMPERATURE_COUNT: {
23802424 cfg.pvi_temp_count = protocol->getValueAsUChar8 (&containerData[i]);
23812425 storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag , 0 );
2382- addTemplTopics (TAG_PVI_TEMPERATURE, 1 , NULL , 0 , cfg.pvi_temp_count , 1 , true );
2426+ addTemplTopics (TAG_PVI_TEMPERATURE, 1 , NULL , 0 , cfg.pvi_temp_count , 1 , 0 , true );
23832427 break ;
23842428 }
23852429 case TAG_PVI_USED_STRING_COUNT: {
23862430 cfg.pvi_tracker = protocol->getValueAsUChar8 (&containerData[i]);
2387- addTemplTopics (TAG_PVI_DC_POWER, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
2388- addTemplTopics (TAG_PVI_DC_VOLTAGE, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
2389- addTemplTopics (TAG_PVI_DC_CURRENT, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
2390- addTemplTopics (TAG_PVI_DC_STRING_ENERGY_ALL, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
2431+ addTemplTopics (TAG_PVI_DC_POWER, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
2432+ addTemplTopics (TAG_PVI_DC_VOLTAGE, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
2433+ addTemplTopics (TAG_PVI_DC_CURRENT, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
2434+ addTemplTopics (TAG_PVI_DC_STRING_ENERGY_ALL, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
23912435 addTemplTopicsIdx (IDX_PVI_ENERGY, NULL , 0 , cfg.pvi_tracker , 1 , false );
23922436 addTemplTopicsIdx (IDX_PVI_ENERGY_START, NULL , 0 , cfg.pvi_tracker , 1 , true );
23932437 storeResponseValue (RSCP_MQTT::RscpMqttCache, protocol, &(containerData[i]), response->tag , 0 );
@@ -2947,6 +2991,8 @@ int main(int argc, char *argv[]) {
29472991 for (uint8_t i = 0 ; i < MAX_WB_COUNT; i++) {
29482992 cfg.wb_indexes [i] = 0 ;
29492993 }
2994+ cfg.bat_dcb_cell_voltages = 0 ;
2995+ cfg.bat_dcb_cell_temperatures = 0 ;
29502996 cfg.pm_number = 0 ;
29512997 cfg.wb_number = 0 ;
29522998 cfg.pm_extern = false ;
@@ -2995,7 +3041,12 @@ int main(int argc, char *argv[]) {
29953041
29963042 RSCP_MQTT::topic_store_t store = { 0 , " " };
29973043
3044+ bool skip = false ;
29983045 while (fgets (line, sizeof (line), fp)) {
3046+ if (!strncmp (line, " EXIT" , 4 )) break ;
3047+ if (!strncmp (line, " /*" , 2 )) skip = true ;
3048+ if (!strncmp (line, " */" , 2 )) skip = false ;
3049+ if (skip) continue ;
29993050 memset (key, 0 , sizeof (key));
30003051 memset (value, 0 , sizeof (value));
30013052 if (sscanf (line, " %127[^ \t =]=%127[^\n ]" , key, value) == 2 ) {
@@ -3107,6 +3158,10 @@ int main(int argc, char *argv[]) {
31073158 if ((cfg.pm_number < MAX_PM_COUNT) && (atoi (value) >= 0 ) && (atoi (value) <= 127 )) cfg.pm_indexes [cfg.pm_number ++] = atoi (value);
31083159 } else if (strcasecmp (key, " WB_INDEX" ) == 0 ) {
31093160 if ((cfg.wb_number < MAX_WB_COUNT) && (atoi (value) >= 0 ) && (atoi (value) < MAX_WB_COUNT)) cfg.wb_indexes [cfg.wb_number ++] = atoi (value);
3161+ } else if (strcasecmp (key, " DCB_CELL_VOLTAGES" ) == 0 ) {
3162+ if ((atoi (value) >= 0 ) && (atoi (value) <= 99 )) cfg.bat_dcb_cell_voltages = atoi (value);
3163+ } else if (strcasecmp (key, " DCB_CELL_TEMPERATURES" ) == 0 ) {
3164+ if ((atoi (value) >= 0 ) && (atoi (value) <= 99 )) cfg.bat_dcb_cell_temperatures = atoi (value);
31103165 } else if ((strcasecmp (key, " PM_REQUESTS" ) == 0 ) && (strcasecmp (value, " false" ) == 0 ))
31113166 cfg.pm_requests = false ;
31123167 else if ((strcasecmp (key, " EMS_REQUESTS" ) == 0 ) && (strcasecmp (value, " false" ) == 0 ))
@@ -3193,6 +3248,7 @@ int main(int argc, char *argv[]) {
31933248 else if (strcasecmp (key, " ADD_NEW_TOPIC" ) == 0 ) {
31943249 int divisor = 1 ;
31953250 int bit = 1 ;
3251+ int index = 0 ;
31963252 char container[128 ];
31973253 char tag[128 ];
31983254 char topic[TOPIC_SIZE];
@@ -3201,8 +3257,9 @@ int main(int argc, char *argv[]) {
32013257 memset (tag, 0 , sizeof (tag));
32023258 memset (topic, 0 , sizeof (topic));
32033259 memset (unit, 0 , sizeof (unit));
3204- if ((sscanf (value, " %127[^:]:%127[^:]:%127[^:]:%d:%d:%127[^:]" , container, tag, unit, &divisor, &bit, topic) == 6 )) {
3205- if (isTag (RSCP_TAGS::RscpTagsOverview, container, false ) && isTag (RSCP_TAGS::RscpTagsOverview, tag, false )) addTopic (tagID (RSCP_TAGS::RscpTagsOverview, container), tagID (RSCP_TAGS::RscpTagsOverview, tag), topic, unit, F_AUTO, divisor, bit, true );
3260+ if ((sscanf (value, " %127[^:]:%127[^:]:%d:%127[^:]:%d:%d:%127[^:]" , container, tag, &index, unit, &divisor, &bit, topic) == 7 ) ||
3261+ (sscanf (value, " %127[^:]:%127[^:]:%127[^:]:%d:%d:%127[^:]" , container, tag, unit, &divisor, &bit, topic) == 6 )) {
3262+ if (isTag (RSCP_TAGS::RscpTagsOverview, container, false ) && isTag (RSCP_TAGS::RscpTagsOverview, tag, false )) addTopic (tagID (RSCP_TAGS::RscpTagsOverview, container), tagID (RSCP_TAGS::RscpTagsOverview, tag), index, topic, unit, F_AUTO, divisor, bit, true );
32063263 } else logMessage (cfg.logfile , (char *)__FILE__, __LINE__, (char *)" key >%s< value >%s< not enough attributes.\n " , key, value);
32073264 }
32083265 else if (strcasecmp (key, " ADD_NEW_SET_TOPIC" ) == 0 ) {
@@ -3341,27 +3398,27 @@ int main(int argc, char *argv[]) {
33413398
33423399 // History year
33433400 if (cfg.verbose ) printf (" History year range from %d to %d\n " , cfg.history_start_year , curr_year);
3344- if (cfg.history_start_year < curr_year) addTemplTopics (TAG_DB_HISTORY_DATA_YEAR, 1 , NULL , cfg.history_start_year , curr_year, 0 , false );
3401+ if (cfg.history_start_year < curr_year) addTemplTopics (TAG_DB_HISTORY_DATA_YEAR, 1 , NULL , cfg.history_start_year , curr_year, 0 , 0 , false );
33453402
33463403 // Battery Strings
3347- addTemplTopics (TAG_BAT_DATA, (cfg.battery_strings == 1 )?0 :1 , (char *)" battery" , 0 , cfg.battery_strings , 1 , false );
3348- addTemplTopics (TAG_BAT_SPECIFICATION, (cfg.battery_strings == 1 )?0 :1 , (char *)" battery" , 0 , cfg.battery_strings , 1 , false );
3404+ addTemplTopics (TAG_BAT_DATA, (cfg.battery_strings == 1 )?0 :1 , (char *)" battery" , 0 , cfg.battery_strings , 1 , 0 , false );
3405+ addTemplTopics (TAG_BAT_SPECIFICATION, (cfg.battery_strings == 1 )?0 :1 , (char *)" battery" , 0 , cfg.battery_strings , 1 , 0 , false );
33493406
33503407 // PVI strings (no auto detection)
33513408 if (cfg.pvi_tracker ) {
3352- addTemplTopics (TAG_PVI_DC_POWER, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
3353- addTemplTopics (TAG_PVI_DC_VOLTAGE, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
3354- addTemplTopics (TAG_PVI_DC_CURRENT, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
3355- addTemplTopics (TAG_PVI_DC_STRING_ENERGY_ALL, 1 , NULL , 0 , cfg.pvi_tracker , 1 , false );
3409+ addTemplTopics (TAG_PVI_DC_POWER, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
3410+ addTemplTopics (TAG_PVI_DC_VOLTAGE, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
3411+ addTemplTopics (TAG_PVI_DC_CURRENT, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
3412+ addTemplTopics (TAG_PVI_DC_STRING_ENERGY_ALL, 1 , NULL , 0 , cfg.pvi_tracker , 1 , 0 , false );
33563413 addTemplTopicsIdx (IDX_PVI_ENERGY, NULL , 0 , cfg.pvi_tracker , 1 , false );
33573414 addTemplTopicsIdx (IDX_PVI_ENERGY_START, NULL , 0 , cfg.pvi_tracker , 1 , false );
33583415 }
33593416
33603417 // Wallbox
33613418 if (cfg.wallbox ) {
33623419 if (cfg.wb_number == 0 ) cfg.wb_number = 1 ;
3363- addTemplTopics (TAG_WB_DATA, (cfg.wb_number == 1 )?0 :1 , (char *)" wallbox" , 0 , cfg.wb_number , 1 , false );
3364- addTemplTopics (TAG_WB_EXTERN_DATA_ALG, (cfg.wb_number == 1 )?0 :1 , (char *)" wallbox" , 0 , cfg.wb_number , 1 , false );
3420+ addTemplTopics (TAG_WB_DATA, (cfg.wb_number == 1 )?0 :1 , (char *)" wallbox" , 0 , cfg.wb_number , 1 , 0 , false );
3421+ addTemplTopics (TAG_WB_EXTERN_DATA_ALG, (cfg.wb_number == 1 )?0 :1 , (char *)" wallbox" , 0 , cfg.wb_number , 1 , 0 , false );
33653422 addTemplTopicsIdx (IDX_WALLBOX_DAY_ENERGY_ALL, (char *)" wallbox" , 0 , cfg.wb_number , 1 , false );
33663423 addTemplTopicsIdx (IDX_WALLBOX_DAY_ENERGY_SOLAR, (char *)" wallbox" , 0 , cfg.wb_number , 1 , false );
33673424 addTemplTopicsIdx (IDX_WALLBOX_ENERGY_ALL_START, (char *)" wallbox" , 0 , cfg.wb_number , 1 , false );
@@ -3375,7 +3432,7 @@ int main(int argc, char *argv[]) {
33753432 }
33763433
33773434 // Power Meters
3378- addTemplTopics (TAG_PM_DATA, (cfg.pm_number == 1 )?0 :1 , (char *)" pm" , 0 , cfg.pm_number , 1 , false );
3435+ addTemplTopics (TAG_PM_DATA, (cfg.pm_number == 1 )?0 :1 , (char *)" pm" , 0 , cfg.pm_number , 1 , 0 , false );
33793436 addTemplTopicsIdx (IDX_PM_POWER, (char *)" pm" , 0 , cfg.pm_number , 1 , false );
33803437 addTemplTopicsIdx (IDX_PM_ENERGY, (char *)" pm" , 0 , cfg.pm_number , 1 , true );
33813438
0 commit comments