diff --git a/TODO.md b/TODO.md index 59d2554..7fedaa4 100644 --- a/TODO.md +++ b/TODO.md @@ -6,7 +6,6 @@ - Add Thingspeak support - Return (402): {"status":"402","error":"Payment required."} - Change so that posting configuration changes is not a complete page reload -- Merge update pages - Add mouseover on debug items - free = Total free bytes in the heap. Equivalent to multi_free_heap_size(). - max = Size of largest free block in the heap. This is the largest malloc-able size. @@ -162,3 +161,4 @@ - ~~Review mDNS restart schedule to see if it's still needed~~ - ~~See if we can do something about entering a bad password on portal~~ - ~~Fix 'nan' error in Bubbles after SPIFFS upload~~ +- ~~Merge update pages~~ diff --git a/data/settings.htm b/data/settings.htm index 1ce27cb..8518a36 100644 --- a/data/settings.htm +++ b/data/settings.htm @@ -586,7 +586,7 @@

Update Firmware: Confirmation

If you are sure you want to update firmware, click the button below.

-
+
diff --git a/json_models/Config JSON.md b/json_models/Config JSON.md new file mode 100644 index 0000000..d0a6d9c --- /dev/null +++ b/json_models/Config JSON.md @@ -0,0 +1,149 @@ +# Configuration JSON: + +``` +{ + "apconfig": { + "ssid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "passphrase": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + }, + "hostname": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "bubble": { + "name": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "tempinf": false + }, + "calibrate": { + "room": -999.9999, + "vessel": -999.9999 + }, + "urltarget": { + "url": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "freq": 999, + "update": false + }, + "brewersfriend": { + "key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "channel": 0, + "freq": 9999, + "update": false + }, + "brewfather": { + "key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "channel": 0, + "freq": 9999, + "update": false + }, + "thingspeak": { + "key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "channel": 999999999, + "freq": 9999, + "update": false + }, + "dospiffs1": false, + "dospiffs2": false, + "didupdate": false +} +``` + +## Size: + +``` +const size_t capacity = 3*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(11) + 810; +512+728 = 1240 +``` + +## Parsing: + +``` +const size_t capacity = 3*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(11) + 810; +DynamicJsonDocument doc(capacity); + +const char* json = "{\"apconfig\":{\"ssid\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"passphrase\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"},\"hostname\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"bubble\":{\"name\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"tempinf\":false},\"calibrate\":{\"room\":-999.9999,\"vessel\":-999.9999},\"urltarget\":{\"url\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"freq\":999,\"update\":false},\"brewersfriend\":{\"key\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"channel\":0,\"freq\":9999,\"update\":false},\"brewfather\":{\"key\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"channel\":0,\"freq\":9999,\"update\":false},\"thingspeak\":{\"key\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\"channel\":999999999,\"freq\":9999,\"update\":false},\"dospiffs1\":false,\"dospiffs2\":false,\"didupdate\":false}"; + +deserializeJson(doc, json); + +const char* apconfig_ssid = doc["apconfig"]["ssid"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +const char* apconfig_passphrase = doc["apconfig"]["passphrase"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +const char* hostname = doc["hostname"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +const char* bubble_name = doc["bubble"]["name"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +bool bubble_tempinf = doc["bubble"]["tempinf"]; // false + +float calibrate_room = doc["calibrate"]["room"]; // -999.9999 +float calibrate_vessel = doc["calibrate"]["vessel"]; // -999.9999 + +JsonObject urltarget = doc["urltarget"]; +const char* urltarget_url = urltarget["url"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +int urltarget_freq = urltarget["freq"]; // 999 +bool urltarget_update = urltarget["update"]; // false + +JsonObject brewersfriend = doc["brewersfriend"]; +const char* brewersfriend_key = brewersfriend["key"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +int brewersfriend_channel = brewersfriend["channel"]; // 0 +int brewersfriend_freq = brewersfriend["freq"]; // 9999 +bool brewersfriend_update = brewersfriend["update"]; // false + +JsonObject brewfather = doc["brewfather"]; +const char* brewfather_key = brewfather["key"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +int brewfather_channel = brewfather["channel"]; // 0 +int brewfather_freq = brewfather["freq"]; // 9999 +bool brewfather_update = brewfather["update"]; // false + +JsonObject thingspeak = doc["thingspeak"]; +const char* thingspeak_key = thingspeak["key"]; // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +long thingspeak_channel = thingspeak["channel"]; // 999999999 +int thingspeak_freq = thingspeak["freq"]; // 9999 +bool thingspeak_update = thingspeak["update"]; // false + +bool dospiffs1 = doc["dospiffs1"]; // false +bool dospiffs2 = doc["dospiffs2"]; // false +bool didupdate = doc["didupdate"]; // false +``` + +## Serializing: + +``` +const size_t capacity = 3*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(11); +DynamicJsonDocument doc(capacity); + +JsonObject apconfig = doc.createNestedObject("apconfig"); +apconfig["ssid"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +apconfig["passphrase"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +doc["hostname"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + +JsonObject bubble = doc.createNestedObject("bubble"); +bubble["name"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +bubble["tempinf"] = false; + +JsonObject calibrate = doc.createNestedObject("calibrate"); +calibrate["room"] = -999.9999; +calibrate["vessel"] = -999.9999; + +JsonObject urltarget = doc.createNestedObject("urltarget"); +urltarget["url"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +urltarget["freq"] = 999; +urltarget["update"] = false; + +JsonObject brewersfriend = doc.createNestedObject("brewersfriend"); +brewersfriend["key"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +brewersfriend["channel"] = 0; +brewersfriend["freq"] = 9999; +brewersfriend["update"] = false; + +JsonObject brewfather = doc.createNestedObject("brewfather"); +brewfather["key"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +brewfather["channel"] = 0; +brewfather["freq"] = 9999; +brewfather["update"] = false; + +JsonObject thingspeak = doc.createNestedObject("thingspeak"); +thingspeak["key"] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +thingspeak["channel"] = 999999999; +thingspeak["freq"] = 9999; +thingspeak["update"] = false; +doc["dospiffs1"] = false; +doc["dospiffs2"] = false; +doc["didupdate"] = false; + +serializeJson(doc, Serial); +``` diff --git a/src/jsonconfig.cpp b/src/jsonconfig.cpp index 321a4ff..e525dc5 100644 --- a/src/jsonconfig.cpp +++ b/src/jsonconfig.cpp @@ -24,8 +24,9 @@ SOFTWARE. */ const char *filename = "/config.json"; Config config; -extern const size_t capacityDeserial = 3 * JSON_OBJECT_SIZE(2) + 3 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(10) + 680; -extern const size_t capacitySerial = 3 * JSON_OBJECT_SIZE(2) + 3 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(10); + +extern const size_t capacitySerial = 3 * JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 3 * JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(11); +extern const size_t capacityDeserial = capacitySerial + 810; bool deleteConfigFile() { @@ -360,6 +361,7 @@ void URLTarget::load(JsonObjectConst obj) void KeyTarget::save(JsonObject obj) const { + obj["channel"] = channel; obj["key"] = key; obj["freq"] = freq; obj["update"] = update; @@ -369,6 +371,16 @@ void KeyTarget::load(JsonObjectConst obj) { // Load Key-type configuration // + if (obj["channel"].isNull()) + { + channel = 0; + } + else + { + int c = obj["channel"]; + channel = c; + } + if (obj["key"].isNull()) { strlcpy(key, "", sizeof(key)); @@ -422,6 +434,7 @@ void Config::load(JsonObjectConst obj) urltarget.load(obj["urltarget"]); brewersfriend.load(obj["brewersfriend"]); brewfather.load(obj["brewfather"]); + thingspeak.load(obj["thingspeak"]); if (obj["dospiffs1"].isNull()) { @@ -468,6 +481,8 @@ void Config::save(JsonObject obj) const brewersfriend.save(obj.createNestedObject("brewersfriend")); // Add Brewfather object brewfather.save(obj.createNestedObject("brewfather")); + // Add Thingspeak object + thingspeak.save(obj.createNestedObject("thingspeak")); // Add dospiffs1 object obj["dospiffs1"] = dospiffs1; // Add dospiffs2 object diff --git a/src/jsonconfig.h b/src/jsonconfig.h index b5ef28b..d2bb6c7 100644 --- a/src/jsonconfig.h +++ b/src/jsonconfig.h @@ -72,6 +72,7 @@ struct KeyTarget { // Stored Brewer's Friend configuration char key[64]; + int channel; int freq; bool update; @@ -89,6 +90,7 @@ struct Config URLTarget urltarget; KeyTarget brewersfriend; KeyTarget brewfather; + KeyTarget thingspeak; bool dospiffs1; bool dospiffs2; bool didupdate;