config: fix crashes, implement fallback profiles

This commit is contained in:
Torrie Fischer 2023-02-19 18:41:55 +01:00
parent de5d3e836a
commit bfbbeffcfd
2 changed files with 44 additions and 22 deletions

View File

@ -9,7 +9,7 @@
#include <LittleFS.h> #include <LittleFS.h>
#include <vector> #include <vector>
StaticJsonDocument<256> jsonConfig; StaticJsonDocument<1024> jsonConfig;
constexpr uint16_t HardwareConfig::MAX_LED_NUM; constexpr uint16_t HardwareConfig::MAX_LED_NUM;
@ -77,14 +77,20 @@ ConfigService::onStart()
m_config = HardwareConfig{}; m_config = HardwareConfig{};
m_config.save(); m_config.save();
} }
if (strlen(m_config.data.loadedProfile) == 0) {
strcpy(m_config.data.loadedProfile, "default"); bool loaded = false;
}
if (m_overrideProfile != nullptr) { if (m_overrideProfile != nullptr) {
loadProfile(m_overrideProfile); loaded = loadProfile(m_overrideProfile);
} else { }
loadProfile(m_config.data.loadedProfile);
if (!loaded && strlen(m_config.data.loadedProfile) > 0) {
loaded = loadProfile(m_config.data.loadedProfile);
}
if (!loaded && !loadProfile("default")) {
Log.fatal("Could not load default fallback profile! No tasks will be started.");
m_jsonMap.loadDefault();
} }
} }
@ -94,24 +100,24 @@ ConfigService::overrideProfile(const char* profileName)
m_overrideProfile = profileName; m_overrideProfile = profileName;
} }
void bool
ConfigService::loadMap(const String& mapName) ConfigService::loadMap(const String& mapName)
{ {
String fname = String("/maps/") + mapName + ".json"; String fname = String("/maps/") + mapName + ".json";
if (LittleFS.exists(fname)) { if (LittleFS.exists(fname)) {
File configFile = LittleFS.open(fname, "r"); File configFile = LittleFS.open(fname, "r");
Log.notice("config: Loading coordinate map %s", mapName.c_str()); Log.notice("config: Loading coordinate map from %s", fname.c_str());
deserializeJson(jsonConfig, configFile); deserializeJson(jsonConfig, configFile);
configFile.close(); configFile.close();
JsonArray strideList = jsonConfig["strides"]; JsonArray strideList = jsonConfig["strides"];
m_jsonMap.load(strideList); m_jsonMap.load(strideList);
return true;
} else { } else {
Log.warning("config: Couldn't load coordinate map %s!!! Defaulting to linear mapping.", mapName.c_str()); return false;
m_jsonMap.loadDefault();
} }
} }
void bool
ConfigService::loadProfile(const char* profileName) ConfigService::loadProfile(const char* profileName)
{ {
Log.notice("config: Loading profile %s...", profileName); Log.notice("config: Loading profile %s...", profileName);
@ -119,11 +125,16 @@ ConfigService::loadProfile(const char* profileName)
LittleFS.begin(); LittleFS.begin();
if (LittleFS.exists(fname)) { if (LittleFS.exists(fname)) {
strncpy(m_config.data.loadedProfile, fname.c_str(), sizeof(m_config.data.loadedProfile));
File configFile = LittleFS.open(fname, "r"); File configFile = LittleFS.open(fname, "r");
jsonConfig.clear(); jsonConfig.clear();
deserializeJson(jsonConfig, configFile); deserializeJson(jsonConfig, configFile);
configFile.close(); configFile.close();
//int profileLogLevel = max(0, min(6, jsonConfig["logLevel"]));
//Log.setLevel(profileLogLevel);
//Log.trace("config: \t %d logging level");
JsonObject sceneList = jsonConfig["scenes"]; JsonObject sceneList = jsonConfig["scenes"];
std::vector<Sequencer::Scene> scenes; std::vector<Sequencer::Scene> scenes;
for(JsonPair pair : sceneList) { for(JsonPair pair : sceneList) {
@ -139,25 +150,37 @@ ConfigService::loadProfile(const char* profileName)
JsonArray taskList = jsonConfig["tasks"]; JsonArray taskList = jsonConfig["tasks"];
Log.notice("config: Starting %d tasks", taskList.size()); Log.notice("config: Starting %d tasks", taskList.size());
for(int i = 0; i < taskList.size();i++) { for(int i = 0; i < taskList.size();i++) {
MainLoop::instance()->dispatch(InputEvent{InputEvent::StartThing, taskList[i].as<const char*>()}); MainLoop::instance()->dispatchSync(InputEvent{InputEvent::StartThing, taskList[i].as<const char*>()});
}
JsonObject defaults = jsonConfig["defaults"];
Log.notice("config: Loading %d app configurations", defaults.size());
MainLoop::instance()->dispatchSync(InputEvent{InputEvent::ConfigurationChanged, &defaults});
String mapName = jsonConfig["surfaceMap"];
jsonConfig.clear();
if (mapName.isEmpty()) {
Log.warning("config: No coordinate map defined! Defaulting to linear mapping.", mapName.c_str());
m_jsonMap.loadDefault();
} else if (!loadMap(mapName)) {
Log.warning("config: Couldn't load coordinate map %s!!! Defaulting to linear mapping.", mapName.c_str());
m_jsonMap.loadDefault();
} }
Log.notice("config: Loaded!"); Log.notice("config: Loaded!");
} else { } else {
Log.warning("config: Could not load profile %s!", profileName); Log.warning("config: Could not load profile %s!", profileName);
return false;
} }
JsonObject defaults = jsonConfig["defaults"];
MainLoop::instance()->dispatch(InputEvent{InputEvent::ConfigurationChanged, &defaults});
String configName = jsonConfig["surfaceMap"];
jsonConfig.clear();
loadMap(configName);
LittleFS.end(); LittleFS.end();
Log.notice("config: Configured to use %d pixels", m_jsonMap.physicalPixelCount()); Log.notice("config: Configured to use %d pixels", m_jsonMap.physicalPixelCount());
PhysicalCoordinates topLeft = m_jsonMap.virtualToPhysicalCoords({0, 0}); PhysicalCoordinates topLeft = m_jsonMap.virtualToPhysicalCoords({0, 0});
PhysicalCoordinates bottomRight = m_jsonMap.virtualToPhysicalCoords({255, 255}); PhysicalCoordinates bottomRight = m_jsonMap.virtualToPhysicalCoords({255, 255});
Log.verbose(" (0,0) -> (%d, %d) -> %d", topLeft.x, topLeft.y, m_jsonMap.physicalCoordsToIndex(topLeft)); Log.verbose(" (0,0) -> (%d, %d) -> %d", topLeft.x, topLeft.y, m_jsonMap.physicalCoordsToIndex(topLeft));
Log.verbose(" (255,255) -> (%d, %d) -> %d", bottomRight.x, bottomRight.y, m_jsonMap.physicalCoordsToIndex(bottomRight)); Log.verbose(" (255,255) -> (%d, %d) -> %d", bottomRight.x, bottomRight.y, m_jsonMap.physicalCoordsToIndex(bottomRight));
return true;
} }
void void
@ -177,7 +200,6 @@ ConfigService::handleEvent(const InputEvent &evt)
switch(evt.intent) { switch(evt.intent) {
case InputEvent::LoadConfigurationByName: case InputEvent::LoadConfigurationByName:
Log.notice("Reloading configuration %s", evt.asString()); Log.notice("Reloading configuration %s", evt.asString());
strcpy(m_config.data.loadedProfile, evt.asString());
loadProfile(evt.asString()); loadProfile(evt.asString());
case InputEvent::SaveConfigurationRequest: case InputEvent::SaveConfigurationRequest:
Log.notice("Saving configuration"); Log.notice("Saving configuration");

View File

@ -44,6 +44,6 @@ private:
JsonCoordinateMapping m_jsonMap; JsonCoordinateMapping m_jsonMap;
const char* m_overrideProfile = nullptr; const char* m_overrideProfile = nullptr;
void loadProfile(const char* name); bool loadProfile(const char* name);
void loadMap(const String& mapName); bool loadMap(const String& mapName);
}; };