Skip to content

Commit

Permalink
Add MQTT and REST API to control the connected LED in EVSE 'Off' mode…
Browse files Browse the repository at this point in the history
… (#131)

* Cheap Tariff Indicator
- Adds MQTT configurable parameter '/Set/CheapTariffIndicator'
- Adds MQTT publication of '/CheapTariffIndicator'
- When 'CheapTariffIndicator' is set to a future unix time (in seconds), the EVSE LED will turn blue, when no EV is connected and access is locked.

* More general mode off LED color implementation:
- Removes MQTT configurable parameter '/Set/CheapTariffIndicator'
- Removes MQTT publication of '/CheapTariffIndicator'
- Adds MQTT configurable parameter '/Set/ColorOff' which takes an RGB value 'R:G:B'
- Adds MQTT publication of '/ColorOff'

* Expanded LED color off-mode implementation:
- Added REST api: curl -X POST 'http://ipaddress/color_off?R=0&G=0&B=255' -d ''
- Added LED color off-mode setting to http://ipaddress/settings
- Add /Set/ColorOff to list of valid MQTT topics to publish to
- Add REST api mods to REST_API manual
  • Loading branch information
jonesPD authored Oct 3, 2024
1 parent 8e0ac76 commit 08528f8
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
51 changes: 46 additions & 5 deletions SmartEVSE-3/src/evse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ int homeBatteryLastUpdate = 0; // Time in milliseconds
char *downloadUrl = NULL;
int downloadProgress = 0;
int downloadSize = 0;
// set by EXTERNAL logic through MQTT/REST to indicate cheap tariffs ahead until unix time indicated
uint8_t ColorOff[3]={0, 0, 0};

//#define FW_UPDATE_DELAY 30 //DINGO TODO // time between detection of new version and actual update in seconds
#define FW_UPDATE_DELAY 3600 // time between detection of new version and actual update in seconds
uint16_t firmwareUpdateTimer = 0; // timer for firmware updates in seconds, max 0xffff = approx 18 hours
Expand Down Expand Up @@ -454,11 +457,10 @@ void BlinkLed(void * parameter) {
GreenPwm = 0;
BluePwm = 0;
#endif //ENABLE_OCPP
} else if (Access_bit == 0 || State == STATE_MODEM_DENIED) { // No Access, LEDs off
RedPwm = 0;
GreenPwm = 0;
BluePwm = 0;
LedPwm = 0;
} else if (Access_bit == 0 || State == STATE_MODEM_DENIED) {
RedPwm = ColorOff[0];
GreenPwm = ColorOff[1];
BluePwm = ColorOff[2];
} else { // State A, B or C

if (State == STATE_A) {
Expand Down Expand Up @@ -2832,6 +2834,16 @@ void mqtt_receive_callback(const String topic, const String payload) {
preferences.putString("RequiredEVCCID", String(RequiredEVCCID));
preferences.end();
}
} else if (topic == MQTTprefix + "/Set/ColorOff") {
int32_t R, G, B;
int n = sscanf(payload.c_str(), "%d:%d:%d", &R, &G, &B);

// R,G,B is between 0..255
if (n == 3 && (R >= 0 && R < 256) && (G >= 0 && G < 256) && (B >= 0 && B < 256)) {
ColorOff[0] = R;
ColorOff[1] = G;
ColorOff[2] = B;
}
}

// Make sure MQTT updates directly to prevent debounces
Expand Down Expand Up @@ -3068,6 +3080,7 @@ void mqttPublishData() {
MQTTclient.publish(MQTTprefix + "/OCPP", OcppMode ? "Enabled" : "Disabled", true, 0);
MQTTclient.publish(MQTTprefix + "/OCPPConnection", (OcppWsClient && OcppWsClient->isConnected()) ? "Connected" : "Disconnected", false, 0);
#endif //ENABLE_OCPP
MQTTclient.publish(MQTTprefix + "/LEDColorOff", String(ColorOff[0])+","+String(ColorOff[1])+","+String(ColorOff[2]), true, 0);
}
#endif

Expand Down Expand Up @@ -4818,6 +4831,10 @@ static void fn_http_server(struct mg_connection *c, int ev, void *ev_data) {
doc["backlight"]["timer"] = BacklightTimer;
doc["backlight"]["status"] = backlight;

doc["color_off"]["R"] = ColorOff[0];
doc["color_off"]["G"] = ColorOff[1];
doc["color_off"]["B"] = ColorOff[2];

String json;
serializeJson(doc, json);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", json.c_str()); // Yes. Respond JSON
Expand Down Expand Up @@ -5145,6 +5162,30 @@ static void fn_http_server(struct mg_connection *c, int ev, void *ev_data) {
} else {
mg_http_reply(c, 404, "", "Not Found\n");
}
} else if (mg_http_match_uri(hm, "/color_off") && !memcmp("POST", hm->method.buf, hm->method.len)) {
DynamicJsonDocument doc(200);

if (request->hasParam("R") && request->hasParam("G") && request->hasParam("B")) {
int32_t R = request->getParam("R")->value().toInt();
int32_t G = request->getParam("G")->value().toInt();
int32_t B = request->getParam("B")->value().toInt();

// R,G,B is between 0..255
if ((R >= 0 && R < 256) && (G >= 0 && G < 256) && (B >= 0 && B < 256)) {
ColorOff[0] = R;
ColorOff[1] = G;
ColorOff[2] = B;
doc["color_off"]["R"] = ColorOff[0];
doc["color_off"]["G"] = ColorOff[1];
doc["color_off"]["B"] = ColorOff[2];
}
}


String json;
serializeJson(doc, json);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\r\n", json.c_str()); // Yes. Respond JSON

} else if (mg_http_match_uri(hm, "/currents") && !memcmp("POST", hm->method.buf, hm->method.len)) {
DynamicJsonDocument doc(200);

Expand Down
9 changes: 9 additions & 0 deletions docs/REST_API.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ to your curl POST command. -d ''
<br>&emsp;&emsp;Usually you should leave this setting at its default value (600A)
<br>&emsp;&emsp;since your electricity provider probably does not supports this.

# POST: /color_off

* R, G, B

<br>&emsp;&emsp;R, G and B must be send all together otherwise the data won't be registered.
```
curl -X POST 'http://ipaddress/color_off?R=0&G=0&B=255' -d ''
```

# POST: /currents

* battery_current
Expand Down
1 change: 1 addition & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ Valid topics you can publish to are:
/Set/EVMeter
/Set/HomeBatteryCurrent
/Set/RequiredEVCCID
/Set/ColorOff
```
Your MainsMeter can be fed with:
```
Expand Down

0 comments on commit 08528f8

Please sign in to comment.