Skip to content

Commit

Permalink
v3.27
Browse files Browse the repository at this point in the history
  • Loading branch information
pvtom committed Jul 24, 2024
1 parent a71132e commit c06e8e9
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 30 deletions.
15 changes: 15 additions & 0 deletions NEWTAGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ e3dc/raw/TAG_BAT_DATA/TAG_BAT_RSOC
The tag names are used to build the topic names.
Raw data is only published via MQTT.

To limit the amount of raw data, a configuration entry can be created with a regular expression that describes the topics to be published:
```
RAW_TOPIC_REGEX=raw/(TAG_DCDC_DATA|TAG_BAT_DATA)/.*
```

### Configuration of Tags

All tags that are listed in RscpTags.h and have "REQ" in their name can be used.
Expand Down Expand Up @@ -154,4 +159,14 @@ ADD_NEW_REQUEST=TAG_DCDC_REQ_DATA:TAG_DCDC_REQ_P_DCL-1
ADD_NEW_REQUEST=TAG_DCDC_REQ_DATA:TAG_DCDC_REQ_ON_GRID-1
ADD_NEW_REQUEST=TAG_DCDC_REQ_DATA:TAG_DCDC_REQ_DERATING-1
ADD_NEW_REQUEST=TAG_DCDC_REQ_DATA:TAG_DCDC_REQ_DERATING_VALUE-1
# Wallbox & Emergency Power
ADD_NEW_REQUEST=0:TAG_EMS_REQ_GET_EP_WALLBOX_ALLOW-0
ADD_NEW_REQUEST=0:TAG_EMS_REQ_GET_MAX_EP_WALLBOX_POWER_W-0
ADD_NEW_REQUEST=0:TAG_EMS_REQ_GET_MIN_EP_WALLBOX_POWER_W-0
ADD_NEW_REQUEST=0:TAG_EMS_REQ_GET_EP_WALLBOX_ENERGY-0
ADD_NEW_REQUEST=0:TAG_EMS_REQ_EP_DELAY-0
# System Specifications
ADD_NEW_REQUEST_AT_START=0:TAG_EMS_REQ_GET_SYS_SPECS-0
```
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ or to show the help page
If everything works properly, you will see something like this:

```
rscp2mqtt [3.26]
rscp2mqtt [3.27]
E3DC system >192.168.178.111:5033< user: >your E3DC user<
MQTT broker >localhost:1883< qos = >0< retain = >✗< tls >✗< client id >✗< prefix >e3dc<
Requesting PVI ✓ | PM (0) | DCB ✓ (1 battery string) | Wallbox ✗ | Interval 2 | Autorefresh ✓ | Raw data ✗ | Logging OFF
Expand Down
5 changes: 5 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
## Release Notes

### Release v3.27 (24.07.2024)

Bug fixes:
- Issue #81: Raw data mode: Possible segmentation fault due to a memory leak

### Release v3.26 (14.07.2024)

Features:
Expand Down
1 change: 1 addition & 0 deletions RscpMqttConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ typedef struct _config_t {
char true_value[5];
char false_value[6];
bool raw_mode;
char *raw_topic_regex;
} config_t;

#endif
61 changes: 40 additions & 21 deletions RscpMqttMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <regex>
#include <mutex>

#define RSCP2MQTT_VERSION "3.26"
#define RSCP2MQTT_VERSION "3.27"

#define AES_KEY_SIZE 32
#define AES_BLOCK_SIZE 32
Expand Down Expand Up @@ -505,7 +505,7 @@ void publishImmediately(char *t, char *p, bool influx) {
char topic[TOPIC_SIZE];

snprintf(topic, TOPIC_SIZE, "%s/%s", cfg.prefix, t);
if (mosq) mosquitto_publish(mosq, NULL, topic, strlen(p), p, cfg.mqtt_qos, cfg.mqtt_retain);
if (mosq && (mosquitto_pub_topic_check(topic) == MOSQ_ERR_SUCCESS) && p && strlen(p)) mosquitto_publish(mosq, NULL, topic, strlen(p), p, cfg.mqtt_qos, cfg.mqtt_retain);
#ifdef INFLUXDB
if (cfg.influxdb_on && curl && influx) {
char buffer[CURL_BUFFER_SIZE];
Expand Down Expand Up @@ -867,17 +867,22 @@ void pushAdditionalTag(uint32_t req_container, uint32_t req_tag, int req_index,
}

bool updateRawData(char *topic, char *payload) {
for (std::vector<RSCP_MQTT::mqtt_data_t>::iterator it = RSCP_MQTT::rawData.begin(); it != RSCP_MQTT::rawData.end(); ++it) {
if (!strcmp(it->topic, topic)) {
if (strcmp(it->payload, payload)) strcpy(it->payload, payload);
return(true);
if (topic && payload) {
for (std::vector<RSCP_MQTT::mqtt_data_t>::iterator it = RSCP_MQTT::rawData.begin(); it != RSCP_MQTT::rawData.end(); ++it) {
if (!strcmp(it->topic, topic)) {
if (strcmp(it->payload, payload)) {
if (strlen(it->payload) != strlen(payload)) it->payload = (char *)realloc(it->payload, strlen(payload) + 1);
strcpy(it->payload, payload);
}
return(true);
}
}
}
return(false);
}

void mergeRawData(char *topic, char *payload) {
if (!updateRawData(topic, payload)) {
if (topic && payload && !updateRawData(topic, payload)) {
RSCP_MQTT::mqtt_data_t v;
v.topic = strdup(topic);
v.payload = strdup(payload);
Expand Down Expand Up @@ -2094,29 +2099,31 @@ void createRequest(SRscpFrameBuffer * frameBuffer) {
}

void publishRaw(RscpProtocol *protocol, SRscpValue *response, char *topic) {
char *payload_new = (char *)malloc(PAYLOAD_SIZE * sizeof(char));
char *payload_new = (char *)malloc(PAYLOAD_SIZE * sizeof(char) + 1);
char *payload_old = readRawData(topic);
memset(payload_new, 0, sizeof(payload_new));
preparePayload(protocol, response, &payload_new);
if (payload_old && strcmp(payload_old, payload_new)) {
if (payload_old && payload_new && strcmp(payload_new, "") && strcmp(payload_old, payload_new)) {
publishImmediately(topic, payload_new, false);
updateRawData(topic, payload_new);
} else if (!payload_old) {
} else if (!payload_old && payload_new && strcmp(payload_new, "")) {
publishImmediately(topic, payload_new, false);
mergeRawData(topic, payload_new);
}
if (payload_new) free(payload_new);
return;
}
return;
}

void handleRaw(RscpProtocol *protocol, SRscpValue *response, uint32_t *cache, int level) {
int l = level + 1;
char topic[TOPIC_SIZE];
memset(topic, 0, sizeof(topic));

if (response->dataType == RSCP::eTypeError) return;

if (!l && (response->dataType != RSCP::eTypeContainer)) {
sprintf(topic, "raw/%s", tagName(RSCP_TAGS::RscpTagsOverview, response->tag));
publishRaw(protocol, response, topic);
if (!cfg.raw_topic_regex || std::regex_match(topic, std::regex(cfg.raw_topic_regex))) publishRaw(protocol, response, topic);
return;
}
std::vector<SRscpValue> data = protocol->getValueAsContainer(response);
Expand All @@ -2131,11 +2138,13 @@ void handleRaw(RscpProtocol *protocol, SRscpValue *response, uint32_t *cache, in
strcpy(topic, "raw");
for (int i = 0; i < RECURSION_MAX_LEVEL; i++) {
if (cache[i]) {
strcat(topic, "/");
strcat(topic, tagName(RSCP_TAGS::RscpTagsOverview, cache[i]));
if (strlen(topic) + strlen(tagName(RSCP_TAGS::RscpTagsOverview, cache[i])) + 2 < TOPIC_SIZE) {
strcat(topic, "/");
strcat(topic, tagName(RSCP_TAGS::RscpTagsOverview, cache[i]));
} else logMessageByTag(response->tag, data[i].tag, 0, __LINE__, (char *)"Error: Topic name too long. Container >%s< Tag >%s< [%d]\n");
}
}
publishRaw(protocol, &data[i], topic);
if (!cfg.raw_topic_regex || std::regex_match(topic, std::regex(cfg.raw_topic_regex))) publishRaw(protocol, &data[i], topic);
}
}
}
Expand Down Expand Up @@ -2185,8 +2194,8 @@ int handleResponseValue(RscpProtocol *protocol, SRscpValue *response) {

if (cfg.raw_mode) {
for (int i = 0; i < RECURSION_MAX_LEVEL; i++) cache[i] = 0;
handleRaw(protocol, response, cache, -1);
}
if (mosq) handleRaw(protocol, response, cache, -1);
}

// check the SRscpValue TAG to detect which response it is
switch (response->tag) {
Expand Down Expand Up @@ -2740,7 +2749,7 @@ static void mainLoop(void) {
if (mosq) {
char topic[TOPIC_SIZE];
snprintf(topic, TOPIC_SIZE, "%s/rscp2mqtt/status", cfg.prefix);
mosquitto_threaded_set(mosq, true);
// mosquitto_threaded_set(mosq, true); // necessary?
if (cfg.mqtt_tls && cfg.mqtt_tls_password) {
if (mosquitto_tls_set(mosq, cfg.mqtt_tls_cafile, cfg.mqtt_tls_capath, cfg.mqtt_tls_certfile, cfg.mqtt_tls_keyfile, mqttCallbackTlsPassword) != MOSQ_ERR_SUCCESS) {
logMessage(cfg.logfile, (char *)__FILE__, __LINE__, (char *)"Error: Unable to set TLS options.\n");
Expand All @@ -2755,8 +2764,10 @@ static void mainLoop(void) {
if (cfg.mqtt_auth && strcmp(cfg.mqtt_user, "") && strcmp(cfg.mqtt_password, "")) mosquitto_username_pw_set(mosq, cfg.mqtt_user, cfg.mqtt_password);
mosquitto_will_set(mosq, topic, strlen("disconnected"), "disconnected", cfg.mqtt_qos, cfg.mqtt_retain);
if (!mosquitto_connect(mosq, cfg.mqtt_host, cfg.mqtt_port, 10)) {
std::thread th(mqttListener, mosq);
th.detach();
if (!cfg.once) {
std::thread th(mqttListener, mosq);
th.detach();
}
if (cfg.verbose) logMessage(cfg.logfile, (char *)__FILE__, __LINE__, (char *)"Success: MQTT broker connected.\n");
} else {
logMessage(cfg.logfile, (char *)__FILE__, __LINE__, (char *)"Error: MQTT broker connection failed.\n");
Expand Down Expand Up @@ -2935,6 +2946,7 @@ int main(int argc, char *argv[]) {
strcpy(cfg.true_value, "true");
strcpy(cfg.false_value, "false");
cfg.raw_mode = false;
cfg.raw_topic_regex = NULL;

// signal handler
signal(SIGINT, signal_handler);
Expand Down Expand Up @@ -3109,6 +3121,8 @@ int main(int argc, char *argv[]) {
#endif
else if ((strcasecmp(key, "RAW_MODE") == 0) && (strcasecmp(value, "true") == 0))
cfg.raw_mode = true;
else if (strcasecmp(key, "RAW_TOPIC_REGEX") == 0)
cfg.raw_topic_regex = strdup(value);
else if (strncasecmp(key, "ADD_NEW_REQUEST", strlen("ADD_NEW_REQUEST")) == 0) {
int order = 0;
int index = -1;
Expand Down Expand Up @@ -3467,6 +3481,10 @@ int main(int argc, char *argv[]) {
RSCP_MQTT::IdlePeriodCache.clear();
RSCP_MQTT::ErrorCache.clear();

// MQTT disconnect
mosquitto_disconnect(mosq);
mosq = NULL;

// MQTT cleanup
mosquitto_lib_cleanup();

Expand All @@ -3486,6 +3504,7 @@ int main(int argc, char *argv[]) {
if (cfg.mqtt_tls_certfile) free(cfg.mqtt_tls_certfile);
if (cfg.mqtt_tls_keyfile) free(cfg.mqtt_tls_keyfile);
if (cfg.mqtt_tls_password) free(cfg.mqtt_tls_password);
if (cfg.raw_topic_regex) free(cfg.raw_topic_regex);

exit(EXIT_SUCCESS);
}
39 changes: 31 additions & 8 deletions WALLBOX.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,45 +58,68 @@ The following topics are sent to the MQTT broker:
| Wallbox Power L3 * | e3dc/wallbox/power/L3 | [W] |
| Wallbox SOC * | e3dc/wallbox/soc | [%] |

*) If more than one wallbox exists, topics are extended by the number of the wallbox (1..8), e.g. e3dc/wallbox/1/charging, e3dc/wallbox/2/charging, ...
*) If more than one wallbox exists (maximum 8), topics are extended by the number of the wallbox (1..8), e.g. e3dc/wallbox/1/charging, e3dc/wallbox/2/charging, ... e3dc/wallbox/8/charging

**) The value is required to be able to calculate the daily value.

### Wallbox Control

In addition, these topics can be published to control the wallboxes:
In addition, the following topics can be published to control the wallboxes:

Sun Mode (true/1/false/0)
```
# if one wallbox is available
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/sun_mode" -m true
# or
#
# or if more than one wallbox is available
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/1/sun_mode" -m true # for the first wallbox
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/2/sun_mode" -m true # for the second wallbox
# ...
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/8/sun_mode" -m true # for the eighth wallbox
```

Suspend charging (true/1/false/0)
```
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/suspended" -m true
# or
#
# or if more than one wallbox is available
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/1/suspended" -m true # for the first wallbox
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/2/suspended" -m true # for the second wallbox
# ...
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/8/suspended" -m true # for the eighth wallbox
```

Toggle suspend charging
```
mosquitto_pub -h localhost -p 1883 -t"e3dc/set/wallbox/toggle" -m 1
# or
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/toggle" -m 1
#
# or if more than one wallbox is available
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/1/toggle" -m 1 # for the first wallbox
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/2/toggle" -m 1 # for the second wallbox
# ...
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/8/toggle" -m 1 # for the eighth wallbox
```

Set max current (1..32 A)
```
mosquitto_pub -h localhost -p 1883 -t"e3dc/set/wallbox/max_current" -m 16
# or
#
# or if more than one wallbox is available
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/1/max_current" -m 16 # for the first wallbox
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/2/max_current" -m 16 # for the second wallbox
# ...
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/8/max_current" -m 16 # for the eighth wallbox
```

Set number of phases (1/3)
```
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/number_phases" -m 1
# or
#
# or if more than one wallbox is available
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/1/number_phases" -m 1 # for the first wallbox
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/2/number_phases" -m 1 # for the second wallbox
# ...
mosquitto_pub -h localhost -p 1883 -t "e3dc/set/wallbox/8/number_phases" -m 1 # for the eighth wallbox
```

The following settings apply to all available wallboxes:
Expand Down
2 changes: 2 additions & 0 deletions config.template
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ DCB_REQUESTS=true

#-Raw Data Mode
RAW_MODE=false
#-- filter topics to be published (optional, only one entry possible!)
RAW_TOPIC_REGEX=raw/TAG_DCDC_DATA/.*

#-Additional Tags and Topics
#--please look at NEWTAGS.md
Expand Down

0 comments on commit c06e8e9

Please sign in to comment.