Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit e1c03c5

Browse files
authored
Merge pull request #235 from ed7coyne/firethings
Clean up api for serialization, fix bug with config fetching from webserver.
2 parents 922cf3f + f987e3b commit e1c03c5

File tree

5 files changed

+94
-47
lines changed

5 files changed

+94
-47
lines changed

src/thing/Config.cpp

+46-34
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,56 @@
44

55
namespace thing {
66

7-
void Config::SerializeToJson(Stream* output, std::function<void(int size)> handle_size) const {
8-
DynamicJsonBuffer jsonBuffer;
9-
JsonObject& root = jsonBuffer.createObject();
10-
root["host"] = host.c_str();
11-
root["auth"] = auth.c_str();
12-
root["path"] = path.c_str();
13-
root["wifi_ssid"] = wifi_ssid.c_str();
14-
root["wifi_key"] = wifi_key.c_str();
15-
root["analog_activation"] = analog_activation_threshold;
16-
root["wifi_connect_attempts"] = wifi_connect_attempts;
7+
ConfigJsonSerializer::ConfigJsonSerializer(const Config& config) {
8+
JsonObject& root = buffer_.createObject();
9+
root_ = &root;
10+
root["host"] = config.host.c_str();
11+
root["auth"] = config.auth.c_str();
12+
root["path"] = config.path.c_str();
13+
root["wifi_ssid"] = config.wifi_ssid.c_str();
14+
root["wifi_key"] = config.wifi_key.c_str();
15+
root["analog_activation"] = config.analog_activation_threshold;
16+
root["wifi_connect_attempts"] = config.wifi_connect_attempts;
1717

1818
JsonObject& pins_root = root.createNestedObject("pins");
19-
pins_root["digital_in"] = pins.digital_in;
20-
pins_root["digital_out"] = pins.digital_out;
21-
pins_root["analog_in"] = pins.analog_in;
22-
pins_root["analog_out"] = pins.analog_out;
23-
pins_root["config_mode_button"] = pins.config_mode_button;
24-
25-
handle_size(root.measureLength());
26-
root.printTo(*output);
19+
pins_root["digital_in"] = config.pins.digital_in;
20+
pins_root["digital_out"] = config.pins.digital_out;
21+
pins_root["analog_in"] = config.pins.analog_in;
22+
pins_root["analog_out"] = config.pins.analog_out;
23+
pins_root["config_mode_button"] = config.pins.config_mode_button;
2724
}
2825

29-
void Config::ReadFromJson(char* string) {
30-
DynamicJsonBuffer jsonBuffer;
31-
JsonObject& root = jsonBuffer.parseObject(string);
32-
host = root["host"].asString();
33-
auth = root["auth"].asString();
34-
path = root["path"].asString();
35-
wifi_ssid = root["wifi_ssid"].asString();
36-
wifi_key = root["wifi_key"].asString();
37-
analog_activation_threshold = root["activation_threshold"];
38-
wifi_connect_attempts = root["wifi_connect_attempts"];
39-
40-
pins.digital_in = root["pins"]["digital_in"];
41-
pins.digital_out = root["pins"]["digital_out"];
42-
pins.analog_in = root["pins"]["analog_in"];
43-
pins.analog_out = root["pins"]["analog_out"];
44-
pins.config_mode_button = root["pins"]["config_mode_button"];
26+
ConfigJsonSerializer::ConfigJsonSerializer(char* serialized_config) {
27+
root_ = &(buffer_.parseObject(serialized_config));
28+
}
29+
30+
int ConfigJsonSerializer::content_length() const {
31+
return root_->measureLength();
32+
}
33+
34+
void ConfigJsonSerializer::SerializeTo(Stream* output) {
35+
// TODO: We "should" be able to have the root_ print directly to the stream
36+
// however it currently closes the connection half way through. Fixing this
37+
// would save ~250B of memory during serialization.
38+
String buffer;
39+
root_->printTo(buffer);
40+
output->print(buffer);
41+
}
42+
43+
void ConfigJsonSerializer::DeserializeTo(Config* config) {
44+
config->host = root()["host"].asString();
45+
config->auth = root()["auth"].asString();
46+
config->path = root()["path"].asString();
47+
config->wifi_ssid = root()["wifi_ssid"].asString();
48+
config->wifi_key = root()["wifi_key"].asString();
49+
config->analog_activation_threshold = root()["activation_threshold"];
50+
config->wifi_connect_attempts = root()["wifi_connect_attempts"];
51+
52+
config->pins.digital_in = root()["pins"]["digital_in"];
53+
config->pins.digital_out = root()["pins"]["digital_out"];
54+
config->pins.analog_in = root()["pins"]["analog_in"];
55+
config->pins.analog_out = root()["pins"]["analog_out"];
56+
config->pins.config_mode_button = root()["pins"]["config_mode_button"];
4557
}
4658

4759
};

src/thing/Config.h

+16-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Arduino.h"
55
#include <string>
66
#include <functional>
7+
#include "third-party/arduino-json-5.6.7/include/ArduinoJson.h"
78

89
namespace thing {
910

@@ -29,11 +30,24 @@ struct Config {
2930
int wifi_connect_attempts;
3031

3132
Pins pins;
33+
};
3234

33-
void SerializeToJson(Stream* output, std::function<void(int size)> handle_size) const;
35+
class ConfigJsonSerializer {
36+
public:
37+
ConfigJsonSerializer(const Config& config);
3438

3539
// We need a mutable char array here, otherwise a copy will be made.
36-
void ReadFromJson(char* string);
40+
ConfigJsonSerializer(char* config);
41+
42+
int content_length() const;
43+
void SerializeTo(Stream* output);
44+
void DeserializeTo(Config* config);
45+
46+
private:
47+
JsonObject& root() {return *root_;}
48+
49+
DynamicJsonBuffer buffer_;
50+
JsonObject* root_;
3751
};
3852

3953
} // namespace thing

src/thing/FireThing.cpp

+19-4
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@ Config kDefaultConfig = {
1212
"", // wifi ssid
1313
"", // wifi key
1414
0.1, // analog activation threshold
15+
2, // wifi connect attempts
16+
{
1517
D1, // digital in
1618
BUILTIN_LED, // digital out
1719
A0, // analog in
1820
D1, // analog out
1921
D0, // config mode button
22+
}
2023
};
2124

2225
const char kStorageFilename[] = "fthing.cfg";
@@ -32,8 +35,7 @@ bool FireThing::Setup() {
3235
return false;
3336
}
3437
SetPinModes(config);
35-
36-
if (digitalRead(config.pins.config_mode_button) || !ConnectToWiFi(config)) {
38+
if (digitalRead(config.pins.config_mode_button) == HIGH || !ConnectToWiFi(config)) {
3739
wifi_.StartAP();
3840
}
3941

@@ -54,9 +56,20 @@ void FireThing::Loop() {
5456
transcriber_.Loop();
5557
}
5658

59+
bool FireThing::DeleteStoredConfig() {
60+
if (!SPIFFS.begin()) {
61+
debug_("Failed to mount FS.");
62+
return false;
63+
}
64+
bool success = SPIFFS.remove(kStorageFilename);
65+
SPIFFS.end();
66+
return success;
67+
}
68+
5769
bool FireThing::ConnectToWiFi(const Config& config) {
5870
debug_("Connecting to wifi:");
5971
debug_(config.wifi_ssid.c_str());
72+
// TODO we should probably not print the key to serial.
6073
debug_(config.wifi_key.c_str());
6174
if (wifi_.Connect(config.wifi_ssid, config.wifi_key)) {
6275
debug_("Connected");
@@ -93,7 +106,8 @@ bool FireThing::ReadConfigFromStorage(Config* config) {
93106
}
94107
char buffer[cfg.size()];
95108
cfg.readBytes(buffer, cfg.size());
96-
config->ReadFromJson(buffer);
109+
ConfigJsonSerializer serializer(buffer);
110+
serializer.DeserializeTo(config);
97111
debug_("Config read from disk.");
98112
}
99113

@@ -113,7 +127,8 @@ bool FireThing::WriteConfigToStorage(const Config& config) {
113127
SPIFFS.end();
114128
return false;
115129
}
116-
config.SerializeToJson(&cfg, [](int){});
130+
ConfigJsonSerializer serializer(config);
131+
serializer.SerializeTo(&cfg);
117132

118133
SPIFFS.end();
119134
return true;

src/thing/FireThing.h

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ class FireThing {
1919

2020
void SetDebugHandler(std::function<void(const char* message)> debug);
2121

22+
// Called to delete the currently stored config from the filesystem.
23+
bool DeleteStoredConfig();
24+
2225
private:
2326
bool ReadConfigFromStorage(Config* config);
2427
bool WriteConfigToStorage(const Config& config);

src/thing/Portal.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ void Portal::Start(const Config& config) {
111111
server_.on("/config", [&] () {
112112
if (server_.method() == HTTP_GET) {
113113
auto client = server_.client();
114-
config_.SerializeToJson(&client,
115-
[this](int size) {
116-
server_.setContentLength(size);
117-
server_.send(200, "application/json");
118-
});
114+
115+
ConfigJsonSerializer serializer(config_);
116+
server_.setContentLength(serializer.content_length());
117+
server_.send(200, "application/json");
118+
serializer.SerializeTo(&client);
119119

120120
debug_("config retrieved");
121121
} else if (server_.method() == HTTP_POST) {
@@ -132,8 +132,11 @@ void Portal::Start(const Config& config) {
132132
buffer = (char*)malloc(config.length()+1);
133133
memcpy(buffer, config.c_str(), config.length()+1);
134134
}
135-
config_.ReadFromJson(buffer);
136-
free(buffer);
135+
{ // Scoped because serializer is invalid after free().
136+
ConfigJsonSerializer serializer(buffer);
137+
serializer.DeserializeTo(&config_);
138+
free(buffer);
139+
}
137140

138141
callback_(config_);
139142
server_.send(200, "text/plain", "");

0 commit comments

Comments
 (0)