config: implement commands to change profiles and save settings
This commit is contained in:
		| @@ -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<ConfigService>::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<ConfigService>::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<Command>& | ||||
| ConfigService::commands() const | ||||
| { | ||||
|   static const std::vector<Command> _commands = { | ||||
|     {"save", doSave}, | ||||
|     {"profile", doSetProfile}, | ||||
|     {"maps", doMapList}, | ||||
|     {"coordmap", doCoordMap} | ||||
|   }; | ||||
|   return _commands; | ||||
| } | ||||
|  | ||||
| STATIC_ALLOC(ConfigService); | ||||
| STATIC_TASK(ConfigService); | ||||
|   | ||||
							
								
								
									
										54
									
								
								src/Config.h
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								src/Config.h
									
									
									
									
									
								
							| @@ -2,6 +2,7 @@ | ||||
| #include <Figments.h> | ||||
| #include "JsonCoordinateMapping.h" | ||||
| #include <ArduinoJson.h> | ||||
| #include <LittleFS.h> | ||||
|  | ||||
| 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<Command>& commands() const override; | ||||
|  | ||||
|     struct filename_iterator: public std::iterator<std::input_iterator_tag, const char*> { | ||||
|       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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user