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

Clean up api for serialization, fix bug with config fetching from webserver. #235

Merged
merged 3 commits into from
Dec 15, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 45 additions & 32 deletions src/thing/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,57 @@

namespace thing {

void Config::SerializeToJson(Stream* output, std::function<void(int size)> handle_size) const {
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["host"] = host.c_str();
root["auth"] = auth.c_str();
root["path"] = path.c_str();
root["wifi_ssid"] = wifi_ssid.c_str();
root["wifi_key"] = wifi_key.c_str();
root["analog_activation"] = analog_activation_threshold;
root["wifi_connect_attempts"] = wifi_connect_attempts;
ConfigJsonSerializer::ConfigJsonSerializer(const Config& config) {
JsonObject& root = json_.createObject();
root_ = &root;
root["host"] = config.host.c_str();
root["auth"] = config.auth.c_str();
root["path"] = config.path.c_str();
root["wifi_ssid"] = config.wifi_ssid.c_str();
root["wifi_key"] = config.wifi_key.c_str();
root["analog_activation"] = config.analog_activation_threshold;
root["wifi_connect_attempts"] = config.wifi_connect_attempts;

JsonObject& pins_root = root.createNestedObject("pins");
pins_root["digital_in"] = pins.digital_in;
pins_root["digital_out"] = pins.digital_out;
pins_root["analog_in"] = pins.analog_in;
pins_root["analog_out"] = pins.analog_out;
pins_root["config_mode_button"] = pins.config_mode_button;

handle_size(root.measureLength());
root.printTo(*output);
pins_root["digital_in"] = config.pins.digital_in;
pins_root["digital_out"] = config.pins.digital_out;
pins_root["analog_in"] = config.pins.analog_in;
pins_root["analog_out"] = config.pins.analog_out;
pins_root["config_mode_button"] = config.pins.config_mode_button;
}

int ConfigJsonSerializer::content_length() const {
return root_->measureLength();
}

void Config::ReadFromJson(char* string) {
void ConfigJsonSerializer::SerializeTo(Stream* output) {
// TODO: We "should" be able to have the root_ print directly to the stream
// however it currently closes the connection half way through.
String buffer;
root_->printTo(buffer);
output->print(buffer);
}

Config ConfigJsonSerializer::Deserialize(char* string) {
Config config;

DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(string);
host = root["host"].asString();
auth = root["auth"].asString();
path = root["path"].asString();
wifi_ssid = root["wifi_ssid"].asString();
wifi_key = root["wifi_key"].asString();
analog_activation_threshold = root["activation_threshold"];
wifi_connect_attempts = root["wifi_connect_attempts"];

pins.digital_in = root["pins"]["digital_in"];
pins.digital_out = root["pins"]["digital_out"];
pins.analog_in = root["pins"]["analog_in"];
pins.analog_out = root["pins"]["analog_out"];
pins.config_mode_button = root["pins"]["config_mode_button"];
config.host = root["host"].asString();
config.auth = root["auth"].asString();
config.path = root["path"].asString();
config.wifi_ssid = root["wifi_ssid"].asString();
config.wifi_key = root["wifi_key"].asString();
config.analog_activation_threshold = root["activation_threshold"];
config.wifi_connect_attempts = root["wifi_connect_attempts"];

config.pins.digital_in = root["pins"]["digital_in"];
config.pins.digital_out = root["pins"]["digital_out"];
config.pins.analog_in = root["pins"]["analog_in"];
config.pins.analog_out = root["pins"]["analog_out"];
config.pins.config_mode_button = root["pins"]["config_mode_button"];

return config;
}

};
Expand Down
13 changes: 11 additions & 2 deletions src/thing/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Arduino.h"
#include <string>
#include <functional>
#include "third-party/arduino-json-5.6.7/include/ArduinoJson.h"

namespace thing {

Expand All @@ -29,11 +30,19 @@ struct Config {
int wifi_connect_attempts;

Pins pins;
};

void SerializeToJson(Stream* output, std::function<void(int size)> handle_size) const;
class ConfigJsonSerializer {
public:
ConfigJsonSerializer(const Config& config);
int content_length() const;
void SerializeTo(Stream* output);

// We need a mutable char array here, otherwise a copy will be made.
void ReadFromJson(char* string);
static Config Deserialize(char* string);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I wonder if you could just have a DeserializeTo(Config& config) w/ a ConfigJsonSerializer ctor that takes a string.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion, updated the signature.

private:
DynamicJsonBuffer json_;
JsonObject* root_;
};

} // namespace thing
Expand Down
5 changes: 3 additions & 2 deletions src/thing/FireThing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ bool FireThing::ReadConfigFromStorage(Config* config) {
}
char buffer[cfg.size()];
cfg.readBytes(buffer, cfg.size());
config->ReadFromJson(buffer);
*config = ConfigJsonSerializer::Deserialize(buffer);
debug_("Config read from disk.");
}

Expand All @@ -113,7 +113,8 @@ bool FireThing::WriteConfigToStorage(const Config& config) {
SPIFFS.end();
return false;
}
config.SerializeToJson(&cfg, [](int){});
ConfigJsonSerializer serializer(config);
serializer.SerializeTo(&cfg);

SPIFFS.end();
return true;
Expand Down
12 changes: 6 additions & 6 deletions src/thing/Portal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ void Portal::Start(const Config& config) {
server_.on("/config", [&] () {
if (server_.method() == HTTP_GET) {
auto client = server_.client();
config_.SerializeToJson(&client,
[this](int size) {
server_.setContentLength(size);
server_.send(200, "application/json");
});

ConfigJsonSerializer serializer(config_);
server_.setContentLength(serializer.content_length());
server_.send(200, "application/json");
serializer.SerializeTo(&client);

debug_("config retrieved");
} else if (server_.method() == HTTP_POST) {
Expand All @@ -132,7 +132,7 @@ void Portal::Start(const Config& config) {
buffer = (char*)malloc(config.length()+1);
memcpy(buffer, config.c_str(), config.length()+1);
}
config_.ReadFromJson(buffer);
config_ = ConfigJsonSerializer::Deserialize(buffer);
free(buffer);

callback_(config_);
Expand Down