Skip to content

Commit

Permalink
Implement settable configuration and fix #36
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinroger committed Aug 19, 2016
1 parent 586ad7a commit 65bbe76
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/Homie/Boot/BootNormal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,16 @@ void BootNormal::_onMqttMessage(char* topic, char* payload, uint8_t qos, size_t
return;
}

/*if (strcmp_P(topic, PSTR("$implementation/config/set")) == 0) {
}*/
if (strcmp_P(topic, PSTR("$implementation/config/set")) == 0) {
if (_interface->config->patch(_mqttPayloadBuffer.get())) {
_interface->logger->logln(F("✔ Configuration updated"));
_flaggedForReboot = true;
_interface->logger->logln(F("Flagged for reboot"));
} else {
_interface->logger->logln(F("✖ Configuration not updated"));
}
return;
}

// Implicit node properties
topic[strlen(topic) - 4] = '\0'; // Remove /set
Expand Down
61 changes: 61 additions & 0 deletions src/Homie/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,67 @@ void Config::write(const char* config) {
configFile.close();
}

bool Config::patch(const char* patch) {
if (!_spiffsBegin()) { return false; }

StaticJsonBuffer<MAX_JSON_CONFIG_ARDUINOJSON_BUFFER_SIZE> patchJsonBuffer;
JsonObject& patchObject = patchJsonBuffer.parseObject(patch);

if (!patchObject.success()) {
_interface->logger->logln(F("✖ Invalid or too big JSON"));
return false;
}

File configFile = SPIFFS.open(CONFIG_FILE_PATH, "r");
if (!configFile) {
_interface->logger->logln(F("✖ Cannot open config file"));
return false;
}

size_t configSize = configFile.size();

char configJson[MAX_JSON_CONFIG_FILE_SIZE];
configFile.readBytes(configJson, configSize);
configFile.close();

StaticJsonBuffer<MAX_JSON_CONFIG_ARDUINOJSON_BUFFER_SIZE> configJsonBuffer;
JsonObject& configObject = configJsonBuffer.parseObject(configJson);

for (JsonObject::iterator it = patchObject.begin(); it != patchObject.end(); ++it) {
if (patchObject[it->key].is<JsonObject&>()) {
JsonObject& subObject = patchObject[it->key].as<JsonObject&>();
for (JsonObject::iterator it2 = subObject.begin(); it2 != subObject.end(); ++it2) {
if (!configObject.containsKey(it->key) || !configObject[it->key].is<JsonObject&>()) {
String error = "✖ Config does not contain a ";
error.concat(it->key);
error.concat(" object");
_interface->logger->logln(error);
return false;
}
JsonObject& subConfigObject = configObject[it->key].as<JsonObject&>();
subConfigObject[it2->key] = it2->value;
}
} else {
configObject[it->key] = it->value;
}
}

ConfigValidationResult configValidationResult = Helpers::validateConfig(configObject);
if (!configValidationResult.valid) {
_interface->logger->log(F("✖ Config file is not valid, reason: "));
_interface->logger->logln(configValidationResult.reason);
return false;
}

size_t finalBufferLength = configObject.measureLength() + 1;
std::unique_ptr<char[]> finalConfigString(new char[finalBufferLength]);
configObject.printTo(finalConfigString.get(), finalBufferLength);

write(finalConfigString.get());

return true;
}

BootMode Config::getBootMode() const {
return _bootMode;
}
Expand Down
1 change: 1 addition & 0 deletions src/Homie/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Config {
char* getSafeConfigFile() const;
void erase();
void write(const char* config);
bool patch(const char* patch);
BootMode getBootMode() const;
void log() const; // print the current config to log output

Expand Down

0 comments on commit 65bbe76

Please sign in to comment.