From d592810b3bb4e3245cd76c4a5f0b565f69f2aa47 Mon Sep 17 00:00:00 2001 From: Torrie Fischer Date: Mon, 11 Dec 2023 07:59:47 +0100 Subject: [PATCH] config: implement commands to change profiles and save settings --- src/Config.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/Config.h | 54 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index 09148bd..828bf21 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -53,7 +53,7 @@ Configuration::get(const char* key, bool defaultVal) const } } -StaticJsonDocument<1024> jsonConfig; +StaticJsonDocument<2048> jsonConfig; constexpr uint16_t HardwareConfig::MAX_LED_NUM; @@ -154,6 +154,11 @@ ConfigService::loadMap(const String& mapName) deserializeJson(jsonConfig, configFile); configFile.close(); JsonArray strideList = jsonConfig["strides"]; + if (jsonConfig.containsKey("rotation")) { + m_jsonMap.rotation = jsonConfig["rotation"]; + } else { + m_jsonMap.rotation = 0; + } m_jsonMap.load(strideList); return true; } else { @@ -213,8 +218,9 @@ ConfigService::loadProfile(const char* profileName) m_jsonMap.loadDefault(); } Log.notice("config: Loaded!"); + strcpy(m_config.data.loadedProfile, profileName); } else { - Log.warning("config: Could not load profile %s!", profileName); + Log.warning("config: Could not find profile json %s!", fname.c_str()); return false; } @@ -254,5 +260,56 @@ ConfigService::handleEvent(const InputEvent &evt) } } +void +doMapList(Args& args, Print& out) +{ + static const auto conf = Static::instance(); + out.println("Available maps:"); + LittleFS.begin(); + for(auto it = conf->mapsBegin();it != conf->mapsEnd(); it++) { + out.println(*it); + } + LittleFS.end(); +} + +void +doSave(Args& args, Print& print) +{ + MainLoop::instance()->dispatch(InputEvent::SaveConfigurationRequest); +} + +static String s; + +void +doSetProfile(Args& args, Print& out) +{ + s = args[1]; + MainLoop::instance()->dispatch(InputEvent{InputEvent::LoadConfigurationByName, s.c_str()}); +} + +void +doCoordMap(Args& args, Print& out) +{ + VirtualCoordinates coords{atoi(args[1].c_str()), atoi(args[2].c_str())}; + auto map = Static::instance()->coordMap(); + auto pPos = map->virtualToPhysicalCoords(coords); + auto idx = map->physicalCoordsToIndex(pPos); + char buf[32]; + sprintf(buf, "(%d, %d) -> (%d, %d) -> %d", coords.x, coords.y, pPos.x, pPos.y, idx); + out.println(buf); +} + +const std::vector& +ConfigService::commands() const +{ + static const std::vector _commands = { + {"save", doSave}, + {"profile", doSetProfile}, + {"maps", doMapList}, + {"coordmap", doCoordMap} + }; + return _commands; +} + STATIC_ALLOC(ConfigService); STATIC_TASK(ConfigService); diff --git a/src/Config.h b/src/Config.h index 898622b..0ee6102 100644 --- a/src/Config.h +++ b/src/Config.h @@ -2,6 +2,7 @@ #include #include "JsonCoordinateMapping.h" #include +#include class Configuration { public: @@ -59,6 +60,59 @@ struct ConfigService: public Task { const char* loadedProfile() const; void overrideProfile(const char* profileName); const char* getConfigValue(const char* key) const; + const std::vector& commands() const override; + + struct filename_iterator: public std::iterator { + Dir dir; + String ret; + bool valid; + const char* suffix; + explicit filename_iterator() : suffix(NULL), valid(false) {} + explicit filename_iterator(const char* path, const char* suffix) : dir(LittleFS.openDir(path)), valid(true), suffix(suffix) { + next(); + } + + void next() { + if (!valid) { + return; + } + int extPos = -1; + do { + valid = dir.next(); + Log.info("valid %F", valid); + if (valid) { + String fname = dir.fileName(); + extPos = fname.lastIndexOf(suffix); + Log.info("compare %s %d", fname.c_str(), extPos); + if (extPos != -1) { + ret = fname.substring(0, extPos); + Log.info("found %s", ret.c_str()); + } + } + } while (valid && extPos == -1); + } + + filename_iterator& operator++() { + next(); + return *this; + } + + filename_iterator& operator++(int) {filename_iterator ret = *this; ++(*this); return ret;} + bool operator==(const filename_iterator &other) const { return valid == other.valid;} + bool operator!=(const filename_iterator &other) const { return !(*this == other); } + const char* operator*() const { + if (!valid) { + return NULL; + } + return ret.c_str(); + } + }; + + filename_iterator mapsBegin() const { return filename_iterator("/maps/", ".json"); } + filename_iterator mapsEnd() const { return filename_iterator(); } + + filename_iterator profilesBegin() const { return filename_iterator("/profiles/", ".json"); } + filename_iterator profilesEnd() const { return filename_iterator(); } private: HardwareConfig m_config;