remove FirebaseJson lib from firmware (save 17.5k of flash)

we used this library solely to interpret the answer of an HTTP web
server as JSON and find a particular value using a path expression in
the HTTP power meter implementation.

since we ran out of flash memory on non-S3 ESP32, we need to cut some
corners. removing FirebaseJson is the last low-hanging fruit that we
currently know of. we can get rid of it by using ArduinoJson (which is
already integral part of the firmware) and implementing a custom logic
to extract a value based on a path expression.

other than the FirebaseJson path "finder", the new implementation
only knows how to access sub-keys delimited by a forward slash. in
particular, accessing array members is not supported any more. I am
hoping that this is simply not an issue. if so, we will have users
complaining and we can add this functionality in a later release.
This commit is contained in:
Bernhard Kirchen 2024-05-05 22:05:08 +02:00 committed by Bernhard Kirchen
parent 6620ab487a
commit 1dd64a57fd
6 changed files with 38 additions and 16 deletions

View File

@ -26,7 +26,7 @@ private:
String extractParam(String& authReq, const String& param, const char delimit);
String getcNonce(const int len);
String getDigestAuth(String& authReq, const String& username, const String& password, const String& method, const String& uri, unsigned int counter);
bool tryGetFloatValueForPhase(int phase, const char* jsonPath, Unit_t unit, bool signInverted);
bool tryGetFloatValueForPhase(int phase, String jsonPath, Unit_t unit, bool signInverted);
void prepareRequest(uint32_t timeout, const char* httpHeader, const char* httpValue);
String sha256(const String& data);
};

View File

@ -47,7 +47,6 @@ lib_deps =
https://github.com/coryjfowler/MCP_CAN_lib
plerup/EspSoftwareSerial @ ^8.0.1
https://github.com/dok-net/ghostl @ ^1.0.1
mobizt/FirebaseJson @ ^3.0.6
rweather/Crypto@^0.4.0
extra_scripts =

View File

@ -3,7 +3,7 @@
#include "HttpPowerMeter.h"
#include "MessageOutput.h"
#include <WiFiClientSecure.h>
#include <FirebaseJson.h>
#include <ArduinoJson.h>
#include <Crypto.h>
#include <SHA256.h>
#include <base64.h>
@ -219,18 +219,43 @@ String HttpPowerMeterClass::getDigestAuth(String& authReq, const String& usernam
return authorization;
}
bool HttpPowerMeterClass::tryGetFloatValueForPhase(int phase, const char* jsonPath, Unit_t unit, bool signInverted)
bool HttpPowerMeterClass::tryGetFloatValueForPhase(int phase, String jsonPath, Unit_t unit, bool signInverted)
{
FirebaseJson json;
json.setJsonData(httpResponse);
FirebaseJsonData value;
if (!json.get(value, jsonPath)) {
snprintf_P(httpPowerMeterError, sizeof(httpPowerMeterError), PSTR("[HttpPowerMeter] Couldn't find a value for phase %i with Json query \"%s\""), phase, jsonPath);
JsonDocument root;
const DeserializationError error = deserializeJson(root, httpResponse);
if (error) {
snprintf_P(httpPowerMeterError, sizeof(httpPowerMeterError),
PSTR("[HttpPowerMeter] Unable to parse server response as JSON"));
return false;
}
constexpr char delimiter = '/';
int start = 0;
int end = jsonPath.indexOf(delimiter);
auto value = root.as<JsonVariantConst>();
// NOTE: "Because ArduinoJson implements the Null Object Pattern, it is
// always safe to read the object: if the key doesn't exist, it returns an
// empty value."
while (end != -1) {
String key = jsonPath.substring(start, end);
value = value[key];
start = end + 1;
end = jsonPath.indexOf(delimiter, start);
}
String lastKey = jsonPath.substring(start);
value = value[lastKey];
if (value.isNull()) {
snprintf_P(httpPowerMeterError, sizeof(httpPowerMeterError),
PSTR("[HttpPowerMeter] Unable to find a value for phase %i with JSON path \"%s\""),
phase+1, jsonPath.c_str());
return false;
}
// this value is supposed to be in Watts and positive if energy is consumed.
power[phase] = value.to<float>();
power[phase] = value.as<float>();
switch (unit) {
case Unit_t::MilliWatts:

View File

@ -577,7 +577,7 @@
"httpHeaderKeyDescription": "Ein individueller HTTP request header kann hier definiert werden. Das kann z.B. verwendet werden um einen eigenen Authorization header mitzugeben.",
"httpHeaderValue": "Optional: HTTP request header - Wert",
"httpJsonPath": "JSON Pfad",
"httpJsonPathDescription": "JSON Pfad um den Leistungswert zu finden. Es verwendet die Selektions-Syntax von mobizt/FirebaseJson. Beispiele gibt es oben.",
"httpJsonPathDescription": "Anwendungsspezifischer JSON-Pfad um den Leistungswert in the HTTP(S) Antwort zu finden, z.B. 'power/total/watts' oder nur 'total'.",
"httpUnit": "Einheit",
"httpSignInverted": "Vorzeichen umkehren",
"httpSignInvertedHint": "Positive Werte werden als Leistungsabnahme aus dem Netz interpretiert. Diese Option muss aktiviert werden, wenn das Vorzeichen des Wertes die gegenteilige Bedeutung hat.",

View File

@ -582,7 +582,7 @@
"httpHeaderKeyDescription": "A custom HTTP request header can be defined. Might be useful if you have to send something like a custom Authorization header.",
"httpHeaderValue": "Optional: HTTP request header - Value",
"httpJsonPath": "JSON path",
"httpJsonPathDescription": "JSON path to find the power value in the response. This uses the JSON path query syntax from mobizt/FirebaseJson. See above for examples.",
"httpJsonPathDescription": "Application specific JSON path to find the power value in the HTTP(S) response, e.g., 'power/total/watts' or simply 'total'.",
"httpUnit": "Unit",
"httpSignInverted": "Change Sign",
"httpSignInvertedHint": "Is is expected that positive values denote power usage from the grid. Check this option if the sign of this value has the opposite meaning.",

View File

@ -116,11 +116,9 @@
<h2>JSON path examples:</h2>
<ul>
<li>total_power - { "othervalue": "blah", "total_power": 123.4 }</li>
<li>testarray/[2]/myvalue - { "testarray": [ {}, { "power": 123.4 } ] }</li>
<li><code>power/total/watts</code> - Finds 123.4 in <code>{ "power": { "phase1": { "factor": 0.98, "watts": 42 }, "total": { "watts": 123.4 } } }</code></li>
<li><code>total</code> - Finds 123.4 in <code>{ "othervalue": 66, "total": 123.4 }</code></li>
</ul>
More info: <a href="https://github.com/mobizt/FirebaseJson">https://github.com/mobizt/FirebaseJson</a>
</div>
<CardElement