From 00a718c11a4f451140f684bd21fbcc98964a4811 Mon Sep 17 00:00:00 2001 From: Stefan de Bruijn Date: Tue, 1 Jun 2021 20:19:07 +0200 Subject: [PATCH] Implemented JSON generator for WebUI [untested] --- Grbl_Esp32/src/Configuration/AfterParse.h | 2 +- Grbl_Esp32/src/Configuration/Generator.h | 2 +- Grbl_Esp32/src/Configuration/HandlerBase.h | 8 +- .../src/Configuration/JsonGenerator.cpp | 110 ++++++++++++++++++ Grbl_Esp32/src/Configuration/JsonGenerator.h | 60 ++++++++++ Grbl_Esp32/src/Configuration/ParserHandler.h | 2 +- .../src/Configuration/RuntimeSetting.cpp | 2 +- Grbl_Esp32/src/Configuration/RuntimeSetting.h | 2 +- Grbl_Esp32/src/Configuration/Validator.h | 2 +- 9 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 Grbl_Esp32/src/Configuration/JsonGenerator.cpp create mode 100644 Grbl_Esp32/src/Configuration/JsonGenerator.h diff --git a/Grbl_Esp32/src/Configuration/AfterParse.h b/Grbl_Esp32/src/Configuration/AfterParse.h index 1403e394..dbc9964a 100644 --- a/Grbl_Esp32/src/Configuration/AfterParse.h +++ b/Grbl_Esp32/src/Configuration/AfterParse.h @@ -41,7 +41,7 @@ namespace Configuration { void handle(const char* name, bool& value) override {} void handle(const char* name, int32_t& value, int32_t minValue, int32_t maxValue) override {} void handle(const char* name, double& value, double minValue, double maxValue) override {} - void handle(const char* name, StringRange& value) override {} + void handle(const char* name, StringRange& value, int minLength, int maxLength) override {} void handle(const char* name, Pin& value) override {} void handle(const char* name, int& value, EnumItem* e) override {} }; diff --git a/Grbl_Esp32/src/Configuration/Generator.h b/Grbl_Esp32/src/Configuration/Generator.h index df51cec8..d059ec0c 100644 --- a/Grbl_Esp32/src/Configuration/Generator.h +++ b/Grbl_Esp32/src/Configuration/Generator.h @@ -65,7 +65,7 @@ namespace Configuration { dst_ << name << ": " << value << '\n'; } - void handle(const char* name, StringRange& value) override { + void handle(const char* name, StringRange& value, int minLength, int maxLength) override { indent(); dst_ << name << ": " << value << '\n'; } diff --git a/Grbl_Esp32/src/Configuration/HandlerBase.h b/Grbl_Esp32/src/Configuration/HandlerBase.h index 3000bb04..8da0af92 100644 --- a/Grbl_Esp32/src/Configuration/HandlerBase.h +++ b/Grbl_Esp32/src/Configuration/HandlerBase.h @@ -55,15 +55,15 @@ namespace Configuration { } virtual void handle(const char* name, double& value, double minValue = -1e300, double maxValue = 1e300) = 0; - - void handle(const char* name, float& value, float minValue = -1e30f, float maxValue = 1e30f) { + + void handle(const char* name, float& value, float minValue = -1e30f, float maxValue = 1e30f) { double d = double(value); handle(name, d, double(minValue), double(maxValue)); value = float(d); } - virtual void handle(const char* name, StringRange& value) = 0; - virtual void handle(const char* name, Pin& value) = 0; + virtual void handle(const char* name, StringRange& value, int minLength = 0, int maxLength = 255) = 0; + virtual void handle(const char* name, Pin& value) = 0; virtual void handle(const char* name, int& value, EnumItem* e) = 0; virtual void handle(const char* name, String& value) { diff --git a/Grbl_Esp32/src/Configuration/JsonGenerator.cpp b/Grbl_Esp32/src/Configuration/JsonGenerator.cpp new file mode 100644 index 00000000..c3a5f185 --- /dev/null +++ b/Grbl_Esp32/src/Configuration/JsonGenerator.cpp @@ -0,0 +1,110 @@ +/* + Part of Grbl_ESP32 + 2021 - Stefan de Bruijn + + Grbl_ESP32 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl_ESP32 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl_ESP32. If not, see . +*/ + +#include "JsonGenerator.h" + +#include "Configurable.h" + +#include +#include +#include + +namespace Configuration { + JsonGenerator::JsonGenerator(WebUI::JSONencoder& encoder) : _encoder(encoder) { + std::atomic_thread_fence(std::memory_order::memory_order_seq_cst); + + _currentPath[0] = '\0'; + _depth = 0; + _paths[0] = _currentPath; + } + + void JsonGenerator::enter(const char* name) { + auto currentEnd = _paths[_depth]; + *currentEnd++ = '/'; + for (auto i = name; *i;) { + Assert(currentEnd != _currentPath + 256, "Path out of bounds while serializing json."); + *currentEnd++ = *i++; + } + ++_depth; + _paths[_depth] = currentEnd; + *currentEnd = '\0'; + } + + void JsonGenerator::add(Configuration::Configurable* configurable) { + if (configurable != nullptr) { + configurable->handle(*this); + } + } + + void JsonGenerator::leave() { + --_depth; + Assert(_depth >= 0, "Depth out of bounds while serializing to json"); + *_paths[_depth] = '\0'; + } + + void JsonGenerator::handleDetail(const char* name, Configurable* value) { + enter(name); + value->handle(*this); + leave(); + } + + void JsonGenerator::handle(const char* name, int& value, int32_t minValue, int32_t maxValue) { + char buf[32]; + itoa(value, buf, 10); + _encoder.begin_webui(name, _currentPath, "I", buf, minValue, maxValue); + _encoder.end_object(); + } + + void JsonGenerator::handle(const char* name, double& value, double minValue, double maxValue) { + int n = int(value * 1000); + handle(name, n, int(minValue * 1000), int(maxValue * 1000)); + } + + void JsonGenerator::handle(const char* name, StringRange& value, int minLength, int maxLength) { + auto sv = value.str(); + _encoder.begin_webui(name, _currentPath, "S", sv.c_str(), minLength, maxLength); + _encoder.end_object(); + } + + void JsonGenerator::handle(const char* name, Pin& value) { + // Let's for now say these are strings. + auto sv = value.name(); + _encoder.begin_webui(name, _currentPath, "S", sv.c_str(), 0, 255); + _encoder.end_object(); + } + + void JsonGenerator::handle(const char* name, int& value, EnumItem* e) { + const char* str = "unknown"; + for (; e->name; ++e) { + if (value == e->value) { + str = e->name; + break; + } + } + + _encoder.begin_webui(name, _currentPath, "B", str); + _encoder.begin_array("O"); + for (; e->name; ++e) { + _encoder.begin_object(); + _encoder.member(e->name, e->value); + _encoder.end_object(); + } + _encoder.end_array(); + _encoder.end_object(); + } +} diff --git a/Grbl_Esp32/src/Configuration/JsonGenerator.h b/Grbl_Esp32/src/Configuration/JsonGenerator.h new file mode 100644 index 00000000..f3377d59 --- /dev/null +++ b/Grbl_Esp32/src/Configuration/JsonGenerator.h @@ -0,0 +1,60 @@ +/* + Part of Grbl_ESP32 + 2021 - Stefan de Bruijn + + Grbl_ESP32 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl_ESP32 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl_ESP32. If not, see . +*/ + +#pragma once + +#include + +#include "../Pin.h" +#include "../StringRange.h" +#include "../StringStream.h" +#include "HandlerBase.h" + +#include "../WebUI/JSONEncoder.h" + +namespace Configuration { + class Configurable; + + class JsonGenerator : public HandlerBase { + JsonGenerator(const JsonGenerator&) = delete; + JsonGenerator& operator=(const JsonGenerator&) = delete; + + char _currentPath[256]; // 256 = max size of configuration string. + char* _paths[16]; // 16 = max depth. Points to the _end_ of a string in currentPath + int _depth; // current depth. Used along with _paths + WebUI::JSONencoder& _encoder; + + void enter(const char* name); + void add(Configuration::Configurable* configurable); + void leave(); + + protected: + void handleDetail(const char* name, Configurable* value) override; + bool matchesUninitialized(const char* name) override { return false; } + HandlerType handlerType() override { return HandlerType::Generator; } + + public: + JsonGenerator(WebUI::JSONencoder& encoder); + + void handle(const char* name, int& value, int32_t minValue, int32_t maxValue) override; + void handle(const char* name, double& value, double minValue, double maxValue) override; + void handle(const char* name, StringRange& value, int minLength, int maxLength) override; + void handle(const char* name, Pin& value) override; + void handle(const char* name, int& value, EnumItem* e) override; + }; +} diff --git a/Grbl_Esp32/src/Configuration/ParserHandler.h b/Grbl_Esp32/src/Configuration/ParserHandler.h index 3934cb41..8e49f29f 100644 --- a/Grbl_Esp32/src/Configuration/ParserHandler.h +++ b/Grbl_Esp32/src/Configuration/ParserHandler.h @@ -78,7 +78,7 @@ namespace Configuration { // } // } - void handle(const char* name, StringRange& value) override { + void handle(const char* name, StringRange& value, int minLength, int maxLength) override { if (parser_.is(name)) { value = parser_.stringValue(); } diff --git a/Grbl_Esp32/src/Configuration/RuntimeSetting.cpp b/Grbl_Esp32/src/Configuration/RuntimeSetting.cpp index f9dbbf1f..f4b2aae1 100644 --- a/Grbl_Esp32/src/Configuration/RuntimeSetting.cpp +++ b/Grbl_Esp32/src/Configuration/RuntimeSetting.cpp @@ -62,7 +62,7 @@ namespace Configuration { } } - void RuntimeSetting::handle(const char* name, StringRange& value) { + void RuntimeSetting::handle(const char* name, StringRange& value, int minLength, int maxLength) { if (is(name) && this->value() != nullptr) { value = this->value(); } diff --git a/Grbl_Esp32/src/Configuration/RuntimeSetting.h b/Grbl_Esp32/src/Configuration/RuntimeSetting.h index c7cc635d..8dc21771 100644 --- a/Grbl_Esp32/src/Configuration/RuntimeSetting.h +++ b/Grbl_Esp32/src/Configuration/RuntimeSetting.h @@ -57,7 +57,7 @@ namespace Configuration { void handle(const char* name, int32_t& value, int32_t minValue, int32_t maxValue) override; void handle(const char* name, double& value, double minValue, double maxValue) override; - void handle(const char* name, StringRange& value) override; + void handle(const char* name, StringRange& value, int minLength, int maxLength) override; void handle(const char* name, Pin& value) override; void handle(const char* name, int& value, EnumItem* e) override {} diff --git a/Grbl_Esp32/src/Configuration/Validator.h b/Grbl_Esp32/src/Configuration/Validator.h index 8a8902ea..7982f5bf 100644 --- a/Grbl_Esp32/src/Configuration/Validator.h +++ b/Grbl_Esp32/src/Configuration/Validator.h @@ -41,7 +41,7 @@ namespace Configuration { void handle(const char* name, bool& value) override {} void handle(const char* name, int32_t& value, int32_t minValue, int32_t maxValue) override {} void handle(const char* name, double& value, double minValue, double maxValue) override {} - void handle(const char* name, StringRange& value) override {} + void handle(const char* name, StringRange& value, int minLength, int maxLength) override {} void handle(const char* name, Pin& value) override {} void handle(const char* name, int& value, EnumItem* e) override {} };