Skip to content

Commit

Permalink
Expose config and config updates through MQTT
Browse files Browse the repository at this point in the history
  • Loading branch information
Carbou, Mathieu authored and Carbou, Mathieu committed May 10, 2023
1 parent 40c7ee1 commit 91643dc
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 167 deletions.
180 changes: 175 additions & 5 deletions src/app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#define FACTORY_OFFSET CONFIG_SIZE
#define FACTORY_SIZE 1024

uint32_t config_version = 0;

// Wifi Network Strings
String esid;
String epass;
Expand Down Expand Up @@ -267,6 +269,46 @@ config_load_settings()
}
}

void append_common_config(DynamicJsonDocument &doc) {
doc["config_version"] = config_version;

#if ENABLE_CONFIG_CHANGE_NOTIFICATION
// Read only information
doc["firmware"] = evse.getFirmwareVersion();
doc["protocol"] = "-";
doc["espflash"] = ESPAL.getFlashChipSize();
doc["espinfo"] = ESPAL.getChipInfo();
doc["buildenv"] = buildenv;
doc["version"] = currentfirmware;
doc["evse_serial"] = evse.getSerial();
doc["wifi_serial"] = serial;

// Static supported protocols
JsonArray mqtt_supported_protocols = doc.createNestedArray("mqtt_supported_protocols");
mqtt_supported_protocols.add("mqtt");
mqtt_supported_protocols.add("mqtts");

JsonArray http_supported_protocols = doc.createNestedArray("http_supported_protocols");
http_supported_protocols.add("http");

// OpenEVSE module config
if(!doc.containsKey("diode_check")) doc["diode_check"] = evse.isDiodeCheckEnabled();
if(!doc.containsKey("gfci_check")) doc["gfci_check"] = evse.isGfiTestEnabled();
if(!doc.containsKey("ground_check")) doc["ground_check"] = evse.isGroundCheckEnabled();
if(!doc.containsKey("relay_check")) doc["relay_check"] = evse.isStuckRelayCheckEnabled();
if(!doc.containsKey("vent_check")) doc["vent_check"] = evse.isVentRequiredEnabled();
if(!doc.containsKey("temp_check")) doc["temp_check"] = evse.isTemperatureCheckEnabled();
if(!doc.containsKey("service")) doc["service"] = static_cast<uint8_t>(evse.getServiceLevel());
if(!doc.containsKey("scale")) doc["scale"] = evse.getCurrentSensorScale();
if(!doc.containsKey("offset")) doc["offset"] = evse.getCurrentSensorOffset();
if(!doc.containsKey("max_current_soft")) doc["max_current_soft"] = evse.getMaxConfiguredCurrent();

// OpenEVSE Read only information
doc["min_current_hard"] = evse.getMinCurrent();
doc["max_current_hard"] = evse.getMaxHardwareCurrent();
#endif
}

void config_changed(String name)
{
DBUGF("%s changed", name.c_str());
Expand Down Expand Up @@ -349,16 +391,17 @@ bool config_deserialize(const char *json)

bool config_deserialize(DynamicJsonDocument &doc)
{
return user_config.deserialize(doc);
}
append_common_config(doc);

bool config_serialize(String& json, bool longNames, bool compactOutput, bool hideSecrets)
{
return user_config.serialize(json, longNames, compactOutput, hideSecrets);
// WiFi module config
return user_config.deserialize(doc);
}

bool config_serialize(DynamicJsonDocument &doc, bool longNames, bool compactOutput, bool hideSecrets)
{
append_common_config(doc);

// WiFi module config
return user_config.serialize(doc, longNames, compactOutput, hideSecrets);
}

Expand All @@ -382,5 +425,132 @@ void config_reset()
config_load_settings();
}

bool web_server_config_deserialise(DynamicJsonDocument &doc, bool factory)
{
bool config_modified = false;

if(config_deserialize(doc))
{
config_commit(factory);
config_modified = true;
DBUGLN("Config updated");
}

#if ENABLE_CONFIG_CHANGE_NOTIFICATION
// Update EVSE config
// Update the EVSE setting flags, a little low level, may move later
if(doc.containsKey("diode_check"))
{
bool enable = doc["diode_check"];
if(enable != evse.isDiodeCheckEnabled()) {
evse.enableDiodeCheck(enable);
config_modified = true;
DBUGLN("diode_check changed");
}
}

if(doc.containsKey("gfci_check"))
{
bool enable = doc["gfci_check"];
if(enable != evse.isGfiTestEnabled()) {
evse.enableGfiTestCheck(enable);
config_modified = true;
DBUGLN("gfci_check changed");
}
}

if(doc.containsKey("ground_check"))
{
bool enable = doc["ground_check"];
if(enable != evse.isGroundCheckEnabled()) {
evse.enableGroundCheck(enable);
config_modified = true;
DBUGLN("ground_check changed");
}
}

if(doc.containsKey("relay_check"))
{
bool enable = doc["relay_check"];
if(enable != evse.isStuckRelayCheckEnabled()) {
evse.enableStuckRelayCheck(enable);
config_modified = true;
DBUGLN("relay_check changed");
}
}

if(doc.containsKey("vent_check"))
{
bool enable = doc["vent_check"];
if(enable != evse.isVentRequiredEnabled()) {
evse.enableVentRequired(enable);
config_modified = true;
DBUGLN("vent_check changed");
}
}

if(doc.containsKey("temp_check"))
{
bool enable = doc["temp_check"];
if(enable != evse.isTemperatureCheckEnabled()) {
evse.enableTemperatureCheck(enable);
config_modified = true;
DBUGLN("temp_check changed");
}
}

if(doc.containsKey("service"))
{
EvseMonitor::ServiceLevel service = static_cast<EvseMonitor::ServiceLevel>(doc["service"].as<uint8_t>());
if(service != evse.getServiceLevel()) {
evse.setServiceLevel(service);
config_modified = true;
DBUGLN("service changed");
}
}

if(doc.containsKey("max_current_soft"))
{
long current = doc["max_current_soft"];
if(current != evse.getMaxConfiguredCurrent()) {
evse.setMaxConfiguredCurrent(current);
config_modified = true;
DBUGLN("max_current_soft changed");
}
}

if(doc.containsKey("scale") && doc.containsKey("offset"))
{
long scale = doc["scale"];
long offset = doc["offset"];
if(scale != evse.getCurrentSensorScale() || offset != evse.getCurrentSensorOffset()) {
evse.configureCurrentSensorScale(doc["scale"], doc["offset"]);
config_modified = true;
DBUGLN("scale changed");
}
}
#endif

if(config_modified)
{
config_version++;
doc["config_version"] = config_version;
DBUGVAR(config_version);

#if ENABLE_CONFIG_CHANGE_NOTIFICATION
// HACK: force a flush of the RAPI command queue to make sure the config
// is updated before we send the response
DBUG("Flushing RAPI command queue ...");
rapiSender.flush();
DBUGLN(" Done");

StaticJsonDocument<128> event;
event["config_version"] = config_version;
event_send(event);
#endif
}

return config_modified;
}


1 change: 0 additions & 1 deletion src/app_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,6 @@ bool config_deserialize(DynamicJsonDocument &doc);
void config_commit(bool factory = false);

// Write config settings to JSON object
bool config_serialize(String& json, bool longNames = true, bool compactOutput = false, bool hideSecrets = false);
bool config_serialize(DynamicJsonDocument &doc, bool longNames = true, bool compactOutput = false, bool hideSecrets = false);

#endif // _EMONESP_CONFIG_H
22 changes: 21 additions & 1 deletion src/mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ mqtt_connect()
event_send(doc);

// Publish MQTT override/claim
mqtt_publish_config();
mqtt_publish_override();
mqtt_publish_claim();
mqtt_publish_schedule();
Expand Down Expand Up @@ -399,6 +400,9 @@ mqtt_publish(JsonDocument &data) {
topic = mqtt_topic + "/";
}

// re-publish config in any case
mqtt_publish_config();

Profile_End(mqtt_publish, 5);
}

Expand Down Expand Up @@ -489,6 +493,22 @@ mqtt_publish_schedule() {
}
}

void
mqtt_publish_config() {
if(!config_mqtt_enabled() || !mqttclient.connected()) {
return;
}
const size_t capacity = JSON_OBJECT_SIZE(128) + 1024;
DynamicJsonDocument doc(capacity);

config_serialize(doc, true, false, true);
mqtt_publish_json(doc, "/config");

String fulltopic = mqtt_topic + "/config_version";
String config_version = doc["config_version"];
mqttclient.publish(fulltopic, config_version, true);
}

void
mqtt_publish_json(JsonDocument &data, const char* topic) {
Profile_Start(mqtt_publish_json);
Expand All @@ -499,7 +519,7 @@ mqtt_publish_json(JsonDocument &data, const char* topic) {
String fulltopic = mqtt_topic + topic;
String doc;
serializeJson(data, doc);
mqttclient.publish(fulltopic,doc, true); // claims are always published as retained as they are not updated regularly
mqttclient.publish(fulltopic,doc, true); // json topics are always published as retained as they are not updated regularly
Profile_End(mqtt_publish_json, 5);

}
Expand Down
1 change: 1 addition & 0 deletions src/mqtt.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern void mqtt_loop();
// data: a comma seperated list of name:value pairs to send
// -------------------------------------------------------------------
extern void mqtt_publish(JsonDocument &data);
extern void mqtt_publish_config();
extern void mqtt_publish_claim();
extern void mqtt_set_claim(bool override, EvseProperties &props);
extern void mqtt_publish_override();
Expand Down
Loading

0 comments on commit 91643dc

Please sign in to comment.