diff --git a/platformio.ini b/platformio.ini index 615bbb9af..192a6cc8f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -165,8 +165,8 @@ lib_deps = #For use SSD1306 OLED display uncomment following U8g2@~2.28.8 #For Dallas sensor uncomment following 2 lines - OneWire@~2.3.5 - ; milesburton/DallasTemperature@^3.9.0 + #OneWire@~2.3.5 + #milesburton/DallasTemperature@^3.9.0 #For BME280 sensor uncomment following #BME280@~3.0.0 ; adafruit/Adafruit BMP280 Library @ 2.1.0 @@ -470,4 +470,4 @@ build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_D -D USER_SETUP_LOADED monitor_filters = esp32_exception_decoder lib_deps = ${esp32.lib_deps} TFT_eSPI - \ No newline at end of file + diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE_v2/usermod_v2_example.h index 3e1f8d3a6..48fb7cd8e 100644 --- a/usermods/EXAMPLE_v2/usermod_v2_example.h +++ b/usermods/EXAMPLE_v2/usermod_v2_example.h @@ -23,12 +23,20 @@ //class name. Use something descriptive and leave the ": public Usermod" part :) class MyExampleUsermod : public Usermod { private: - // sample usermod default value for variable (you can also use constructor) - int userVar0 = 42; - //Private class members. You can declare variables and functions only accessible to your usermod here unsigned long lastTime = 0; + // set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer) + bool testBool = false; + unsigned long testULong = 42424242; + float testFloat = 42.42; + String testString = "Forty-Two"; + + // These config variables have defaults set inside readFromConfig() + int testInt; + long testLong; + int8_t testPins[2]; + public: //Functions called by WLED @@ -118,40 +126,85 @@ class MyExampleUsermod : public Usermod { * It might cause the LEDs to stutter and will cause flash wear if called too often. * Use it sparingly and always in the loop, never in network callbacks! * - * addToConfig() will also not yet add your setting to one of the settings pages automatically. - * To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually. + * addToConfig() will make your settings editable through the Usermod Settings page automatically. + * + * Usermod Settings Overview: + * - Numeric values are treated as floats in the browser. + * - If the numeric value entered into the browser contains a decimal point, it will be parsed as a C float + * before being returned to the Usermod. The float data type has only 6-7 decimal digits of precision, and + * doubles are not supported, numbers will be rounded to the nearest float value when being parsed. + * The range accepted by the input field is +/- 1.175494351e-38 to +/- 3.402823466e+38. + * - If the numeric value entered into the browser doesn't contain a decimal point, it will be parsed as a + * C int32_t (range: -2147483648 to 2147483647) before being returned to the usermod. + * Overflows or underflows are truncated to the max/min value for an int32_t, and again truncated to the type + * used in the Usermod when reading the value from ArduinoJson. + * - Pin values can be treated differently from an integer value by using the key name "pin" + * - "pin" can contain a single or array of integer values + * - On the Usermod Settings page there is simple checking for pin conflicts and warnings for special pins + * - Red color indicates a conflict. Yellow color indicates a pin with a warning (e.g. an input-only pin) + * - Tip: use int8_t to store the pin value in the Usermod, so a -1 value (pin not set) can be used + * + * See usermod_v2_auto_save.h for an example that saves Flash space by reusing ArduinoJson key name strings + * + * If you need a dedicated settings page with custom layout for your Usermod, that takes a lot more work. + * You will have to add the setting to the HTML, xml.cpp and set.cpp manually. + * See the WLED Soundreactive fork (code and wiki) for reference. https://github.com/atuline/WLED * * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! */ void addToConfig(JsonObject& root) { JsonObject top = root.createNestedObject("exampleUsermod"); - top["great"] = userVar0; //save this var persistently whenever settings are saved + top["great"] = userVar0; //save these vars persistently whenever settings are saved + top["testBool"] = testBool; + top["testInt"] = testInt; + top["testLong"] = testLong; + top["testULong"] = testULong; + top["testFloat"] = testFloat; + top["testString"] = testString; + JsonArray pinArray = top.createNestedArray("pin"); + pinArray.add(testPins[0]); + pinArray.add(testPins[1]); } /* * readFromConfig() can be used to read back the custom settings you added with addToConfig(). - * This is called by WLED when settings are loaded (currently this only happens once immediately after boot) + * This is called by WLED when settings are loaded (currently this only happens immediately after boot, or after saving on the Usermod Settings page) * * readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes), * but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup. * If you don't know what that is, don't fret. It most likely doesn't affect your use case :) * - * Return true in case your config was complete, or false if you'd like WLED to save your defaults to disk + * Return true in case the config values returned from Usermod Settings were complete, or false if you'd like WLED to save your defaults to disk (so any missing values are editable in Usermod Settings) + * + * getJsonValue() returns false if the value is missing, or copies the value into the variable provided and returns true if the value is present + * The configComplete variable is true only if the "exampleUsermod" object and all values are present. If any values are missing, WLED will know to call addToConfig() to save them * * This function is guaranteed to be called on boot, but could also be called every time settings are updated */ bool readFromConfig(JsonObject& root) { - //set defaults for variables when declaring the variable (class definition or constructor) + // default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor + // setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed) + JsonObject top = root["exampleUsermod"]; - if (!top.isNull()) return false; - userVar0 = top["great"] | userVar0; + bool configComplete = !top.isNull(); - // use "return !top["newestParameter"].isNull();" when updating Usermod with new features - return true; + configComplete &= getJsonValue(top["great"], userVar0); + configComplete &= getJsonValue(top["testBool"], testBool); + configComplete &= getJsonValue(top["testULong"], testULong); + configComplete &= getJsonValue(top["testFloat"], testFloat); + configComplete &= getJsonValue(top["testString"], testString); + + // A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing + configComplete &= getJsonValue(top["testInt"], testInt, 42); + configComplete &= getJsonValue(top["testLong"], testLong, -42424242); + configComplete &= getJsonValue(top["pin"][0], testPins[0], -1); + configComplete &= getJsonValue(top["pin"][1], testPins[1], -1); + + return configComplete; } diff --git a/usermods/rotary_encoder_change_brightness/usermod.cpp b/usermods/rotary_encoder_change_brightness/usermod.cpp deleted file mode 100644 index 8fae61204..000000000 --- a/usermods/rotary_encoder_change_brightness/usermod.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "wled.h" -/* - * This file allows you to add own functionality to WLED more easily - * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality - * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h) - * bytes 2400+ are currently ununsed, but might be used for future wled features - */ - -//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) - -/* -** Rotary Encoder Example -** Use the Sparkfun Rotary Encoder to vary brightness of LED -** -** Sample the encoder at 500Hz using the millis() function -*/ - -int fadeAmount = 5; // how many points to fade the Neopixel with each step -unsigned long currentTime; -unsigned long loopTime; -const int pinA = D6; // DT from encoder -const int pinB = D7; // CLK from encoder - -unsigned char Enc_A; -unsigned char Enc_B; -unsigned char Enc_A_prev = 0; - -//gets called once at boot. Do all initialization that doesn't depend on network here -void userSetup() { - pinMode(pinA, INPUT_PULLUP); - pinMode(pinB, INPUT_PULLUP); - currentTime = millis(); - loopTime = currentTime; -} - -//gets called every time WiFi is (re-)connected. Initialize own network interfaces here -void userConnected() { -} - -//loop. You can use "if (WLED_CONNECTED)" to check for successful connection -void userLoop() { - currentTime = millis(); // get the current elapsed time - if(currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz - { - int Enc_A = digitalRead(pinA); // Read encoder pins - int Enc_B = digitalRead(pinB); - if((! Enc_A) && (Enc_A_prev)) { // A has gone from high to low - if(Enc_B == HIGH) { // B is high so clockwise - if(bri + fadeAmount <= 255) bri += fadeAmount; // increase the brightness, dont go over 255 - - } else if (Enc_B == LOW) { // B is low so counter-clockwise - if(bri - fadeAmount >= 0) bri -= fadeAmount; // decrease the brightness, dont go below 0 - } - } - Enc_A_prev = Enc_A; // Store value of A for next time - loopTime = currentTime; // Updates loopTime - - //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) - // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa - colorUpdated(6); - } -} diff --git a/usermods/rotary_encoder_change_brightness/usermode_rotary_set.h b/usermods/rotary_encoder_change_brightness/usermode_rotary_set.h deleted file mode 100644 index 5c95573d7..000000000 --- a/usermods/rotary_encoder_change_brightness/usermode_rotary_set.h +++ /dev/null @@ -1,211 +0,0 @@ -#pragma once - -#include "wled.h" - -//v2 usermod that allows to change brightness and color using a rotary encoder, -//change between modes by pressing a button (many encoder have one included) -class RotaryEncoderSet : public Usermod -{ -private: - //Private class members. You can declare variables and functions only accessible to your usermod here - unsigned long lastTime = 0; - /* -** Rotary Encoder Example -** Use the Sparkfun Rotary Encoder to vary brightness of LED -** -** Sample the encoder at 500Hz using the millis() function -*/ - - int fadeAmount = 5; // how many points to fade the Neopixel with each step - unsigned long currentTime; - unsigned long loopTime; - const int pinA = 5; // DT from encoder - const int pinB = 18; // CLK from encoder - const int pinC = 23; // SW from encoder - unsigned char select_state = 0; // 0 = brightness 1 = color - unsigned char button_state = HIGH; - unsigned char prev_button_state = HIGH; - CRGB fastled_col; - CHSV prim_hsv; - int16_t new_val; - - unsigned char Enc_A; - unsigned char Enc_B; - unsigned char Enc_A_prev = 0; - -public: - //Functions called by WLED - - /* - * setup() is called once at boot. WiFi is not yet connected at this point. - * You can use it to initialize variables, sensors or similar. - */ - void setup() - { - //Serial.println("Hello from my usermod!"); - pinMode(pinA, INPUT_PULLUP); - pinMode(pinB, INPUT_PULLUP); - pinMode(pinC, INPUT_PULLUP); - currentTime = millis(); - loopTime = currentTime; - } - - /* - * connected() is called every time the WiFi is (re)connected - * Use it to initialize network interfaces - */ - void connected() - { - //Serial.println("Connected to WiFi!"); - } - - /* - * loop() is called continuously. Here you can check for events, read sensors, etc. - * - * Tips: - * 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection. - * Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker. - * - * 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds. - * Instead, use a timer check as shown here. - */ - void loop() - { - currentTime = millis(); // get the current elapsed time - - if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz - { - button_state = digitalRead(pinC); - if (prev_button_state != button_state) - { - if (button_state == LOW) - { - if (select_state == 1) - { - select_state = 0; - } - else - { - select_state = 1; - } - prev_button_state = button_state; - } - else - { - prev_button_state = button_state; - } - } - int Enc_A = digitalRead(pinA); // Read encoder pins - int Enc_B = digitalRead(pinB); - if ((!Enc_A) && (Enc_A_prev)) - { // A has gone from high to low - if (Enc_B == HIGH) - { // B is high so clockwise - if (select_state == 0) - { - if (bri + fadeAmount <= 255) - bri += fadeAmount; // increase the brightness, dont go over 255 - } - else - { - fastled_col.red = col[0]; - fastled_col.green = col[1]; - fastled_col.blue = col[2]; - prim_hsv = rgb2hsv_approximate(fastled_col); - new_val = (int16_t)prim_hsv.h + fadeAmount; - if (new_val > 255) - new_val -= 255; // roll-over if bigger than 255 - if (new_val < 0) - new_val += 255; // roll-over if smaller than 0 - prim_hsv.h = (byte)new_val; - hsv2rgb_rainbow(prim_hsv, fastled_col); - col[0] = fastled_col.red; - col[1] = fastled_col.green; - col[2] = fastled_col.blue; - } - } - else if (Enc_B == LOW) - { // B is low so counter-clockwise - if (select_state == 0) - { - if (bri - fadeAmount >= 0) - bri -= fadeAmount; // decrease the brightness, dont go below 0 - } - else - { - fastled_col.red = col[0]; - fastled_col.green = col[1]; - fastled_col.blue = col[2]; - prim_hsv = rgb2hsv_approximate(fastled_col); - new_val = (int16_t)prim_hsv.h - fadeAmount; - if (new_val > 255) - new_val -= 255; // roll-over if bigger than 255 - if (new_val < 0) - new_val += 255; // roll-over if smaller than 0 - prim_hsv.h = (byte)new_val; - hsv2rgb_rainbow(prim_hsv, fastled_col); - col[0] = fastled_col.red; - col[1] = fastled_col.green; - col[2] = fastled_col.blue; - } - } - //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) - // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa - colorUpdated(NOTIFIER_CALL_MODE_BUTTON); - updateInterfaces() - } - Enc_A_prev = Enc_A; // Store value of A for next time - loopTime = currentTime; // Updates loopTime - } - } - - /* - * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. - * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. - * Below it is shown how this could be used for e.g. a light sensor - */ - /* - void addToJsonInfo(JsonObject& root) - { - int reading = 20; - //this code adds "u":{"Light":[20," lux"]} to the info object - JsonObject user = root["u"]; - if (user.isNull()) user = root.createNestedObject("u"); - - JsonArray lightArr = user.createNestedArray("Light"); //name - lightArr.add(reading); //value - lightArr.add(" lux"); //unit - } - */ - - /* - * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). - * Values in the state object may be modified by connected clients - */ - void addToJsonState(JsonObject &root) - { - //root["user0"] = userVar0; - } - - /* - * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). - * Values in the state object may be modified by connected clients - */ - void readFromJsonState(JsonObject &root) - { - userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value - //if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!")); - } - - /* - * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). - * This could be used in the future for the system to determine whether your usermod is installed. - */ - uint16_t getId() - { - return 0xABCD; - } - - //More methods can be added in the future, this example will then be extended. - //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! -}; diff --git a/usermods/usermod_rotary_brightness_color/README.md b/usermods/usermod_rotary_brightness_color/README.md new file mode 100644 index 000000000..9d59a0ba9 --- /dev/null +++ b/usermods/usermod_rotary_brightness_color/README.md @@ -0,0 +1,42 @@ +# Rotary Encoder (Brightness and Color) + +V2 usermod that allows changing brightness and color using a rotary encoder, +change between modes by pressing a button (many encoders have one included) + +but it will wait for AUTOSAVE_SETTLE_MS milliseconds, a "settle" +period in case there are other changes (any change will +extend the "settle" window). + +It will additionally load preset AUTOSAVE_PRESET_NUM at startup. +during the first `loop()`. Reasoning below. + +AutoSaveUsermod is standalone, but if FourLineDisplayUsermod is installed, it will notify the user of the saved changes. + +Note: I don't love that WLED doesn't respect the brightness of the preset being auto loaded, so the AutoSaveUsermod will set the AUTOSAVE_PRESET_NUM preset in the first loop, so brightness IS honored. This means WLED will effectively ignore Default brightness and Apply N preset at boot when the AutoSaveUsermod is installed. + +## Installation + +define `USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR` e.g. + +`#define USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR` in my_config.h + +or add `-D USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR` to `build_flags` in platformio_override.ini + +### Define Your Options + +Open Usermod Settings in WLED to change settings: + +`fadeAmount` - how many points to fade the Neopixel with each step of the rotary encoder (default 5) +`pin[3]` - pins to connect to the rotary encoder: +- `pin[0]` is pin A on your rotary encoder +- `pin[1]` is pin B on your rotary encoder +- `pin[2]` is the button on your rotary encoder (optional, set to -1 to disable the button and the rotary encoder will control brightness only) + +### PlatformIO requirements + +No special requirements. + +## Change Log + +2021-07 +* Upgraded to work with the latest WLED code, and make settings configurable in Usermod Settings diff --git a/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h b/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h new file mode 100644 index 000000000..24f1e7ae4 --- /dev/null +++ b/usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h @@ -0,0 +1,189 @@ +#pragma once + +#include "wled.h" + +//v2 usermod that allows to change brightness and color using a rotary encoder, +//change between modes by pressing a button (many encoders have one included) +class RotaryEncoderBrightnessColor : public Usermod +{ +private: + //Private class members. You can declare variables and functions only accessible to your usermod here + unsigned long lastTime = 0; + unsigned long currentTime; + unsigned long loopTime; + + unsigned char select_state = 0; // 0 = brightness 1 = color + unsigned char button_state = HIGH; + unsigned char prev_button_state = HIGH; + CRGB fastled_col; + CHSV prim_hsv; + int16_t new_val; + + unsigned char Enc_A; + unsigned char Enc_B; + unsigned char Enc_A_prev = 0; + + // private class memebers configurable by Usermod Settings (defaults set inside readFromConfig()) + int8_t pins[3]; // pins[0] = DT from encoder, pins[1] = CLK from encoder, pins[2] = CLK from encoder (optional) + int fadeAmount; // how many points to fade the Neopixel with each step + +public: + //Functions called by WLED + + /* + * setup() is called once at boot. WiFi is not yet connected at this point. + * You can use it to initialize variables, sensors or similar. + */ + void setup() + { + //Serial.println("Hello from my usermod!"); + pinMode(pins[0], INPUT_PULLUP); + pinMode(pins[1], INPUT_PULLUP); + if(pins[2] >= 0) pinMode(pins[2], INPUT_PULLUP); + currentTime = millis(); + loopTime = currentTime; + } + + /* + * loop() is called continuously. Here you can check for events, read sensors, etc. + * + * Tips: + * 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection. + * Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker. + * + * 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds. + * Instead, use a timer check as shown here. + */ + void loop() + { + currentTime = millis(); // get the current elapsed time + + if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz + { + if(pins[2] >= 0) { + button_state = digitalRead(pins[2]); + if (prev_button_state != button_state) + { + if (button_state == LOW) + { + if (select_state == 1) + { + select_state = 0; + } + else + { + select_state = 1; + } + prev_button_state = button_state; + } + else + { + prev_button_state = button_state; + } + } + } + int Enc_A = digitalRead(pins[0]); // Read encoder pins + int Enc_B = digitalRead(pins[1]); + if ((!Enc_A) && (Enc_A_prev)) + { // A has gone from high to low + if (Enc_B == HIGH) + { // B is high so clockwise + if (select_state == 0) + { + if (bri + fadeAmount <= 255) + bri += fadeAmount; // increase the brightness, dont go over 255 + } + else + { + fastled_col.red = col[0]; + fastled_col.green = col[1]; + fastled_col.blue = col[2]; + prim_hsv = rgb2hsv_approximate(fastled_col); + new_val = (int16_t)prim_hsv.h + fadeAmount; + if (new_val > 255) + new_val -= 255; // roll-over if bigger than 255 + if (new_val < 0) + new_val += 255; // roll-over if smaller than 0 + prim_hsv.h = (byte)new_val; + hsv2rgb_rainbow(prim_hsv, fastled_col); + col[0] = fastled_col.red; + col[1] = fastled_col.green; + col[2] = fastled_col.blue; + } + } + else if (Enc_B == LOW) + { // B is low so counter-clockwise + if (select_state == 0) + { + if (bri - fadeAmount >= 0) + bri -= fadeAmount; // decrease the brightness, dont go below 0 + } + else + { + fastled_col.red = col[0]; + fastled_col.green = col[1]; + fastled_col.blue = col[2]; + prim_hsv = rgb2hsv_approximate(fastled_col); + new_val = (int16_t)prim_hsv.h - fadeAmount; + if (new_val > 255) + new_val -= 255; // roll-over if bigger than 255 + if (new_val < 0) + new_val += 255; // roll-over if smaller than 0 + prim_hsv.h = (byte)new_val; + hsv2rgb_rainbow(prim_hsv, fastled_col); + col[0] = fastled_col.red; + col[1] = fastled_col.green; + col[2] = fastled_col.blue; + } + } + //call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification) + // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa + colorUpdated(NOTIFIER_CALL_MODE_BUTTON); + updateInterfaces(NOTIFIER_CALL_MODE_BUTTON); + } + Enc_A_prev = Enc_A; // Store value of A for next time + loopTime = currentTime; // Updates loopTime + } + } + + void addToConfig(JsonObject& root) + { + JsonObject top = root.createNestedObject("rotEncBrightness"); + top["fadeAmount"] = fadeAmount; + JsonArray pinArray = top.createNestedArray("pin"); + pinArray.add(pins[0]); + pinArray.add(pins[1]); + pinArray.add(pins[2]); + } + + /* + * This example uses a more robust method of checking for missing values in the config, and setting back to defaults: + * - The getJsonValue() function copies the value to the variable only if the key requested is present, returning false with no copy if the value isn't present + * - configComplete is used to return false if any value is missing, not just if the main object is missing + * - The defaults are loaded every time readFromConfig() is run, not just once after boot + * + * This ensures that missing values are added to the config, with their default values, in the rare but plauible cases of: + * - a single value being missing at boot, e.g. if the Usermod was upgraded and a new setting was added + * - a single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed) + * + * If configComplete is false, the default values are already set, and by returning false, WLED now knows it needs to save the defaults by calling addToConfig() + */ + bool readFromConfig(JsonObject& root) + { + // set defaults here, they will be set before setup() is called, and if any values parsed from ArduinoJson below are missing, the default will be used instead + fadeAmount = 5; + pins[0] = -1; + pins[1] = -1; + pins[2] = -1; + + JsonObject top = root["rotEncBrightness"]; + + bool configComplete = !top.isNull(); + configComplete &= getJsonValue(top["fadeAmount"], fadeAmount); + configComplete &= getJsonValue(top["pin"][0], pins[0]); + configComplete &= getJsonValue(top["pin"][1], pins[1]); + configComplete &= getJsonValue(top["pin"][2], pins[2]); + + return configComplete; + } +}; diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 246c4b2c5..e48068f7e 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -3488,7 +3488,7 @@ uint16_t WS2812FX::mode_twinkleup(void) { // A very short twinkl uint8_t ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work. uint8_t pixBri = sin8(ranstart + 16 * now/(256-SEGMENT.speed)); if (random8() > SEGMENT.intensity) pixBri = 0; - setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i*20, false, PALETTE_SOLID_WRAP, 0), pixBri)); + setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(random8()+now/100, false, PALETTE_SOLID_WRAP, 0), pixBri)); } return FRAMETIME; diff --git a/wled00/data/settings_um.htm b/wled00/data/settings_um.htm index b1cc039aa..fa294bd1c 100644 --- a/wled00/data/settings_um.htm +++ b/wled00/data/settings_um.htm @@ -84,7 +84,7 @@ c += ' max="39" min="-1" class="s"'; t = "int"; } else { - c += ' step="0.00001" class="xxl"'; + c += ' step="any" class="xxl"'; } break; default: diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 6269e25eb..6ad0ec866 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -34,6 +34,27 @@ bool deserializeConfigSec(); void serializeConfig(); void serializeConfigSec(); +template +bool getJsonValue(const JsonVariant& element, DestType& destination) { + if (element.isNull()) { + return false; + } + + destination = element.as(); + return true; +} + +template +bool getJsonValue(const JsonVariant& element, DestType& destination, const DefaultType defaultValue) { + if(!getJsonValue(element, destination)) { + destination = defaultValue; + return false; + } + + return true; +} + + //colors.cpp void colorFromUint32(uint32_t in, bool secondary = false); void colorFromUint24(uint32_t in, bool secondary = false); @@ -192,7 +213,7 @@ class Usermod { virtual void addToJsonInfo(JsonObject& obj) {} virtual void readFromJsonState(JsonObject& obj) {} virtual void addToConfig(JsonObject& obj) {} - virtual bool readFromConfig(JsonObject& obj) { return true; } //Heads up! readFromConfig() now needs to return a bool + virtual bool readFromConfig(JsonObject& obj) { return true; } // Note as of 2021-06 readFromConfig() now needs to return a bool, see usermod_v2_example.h virtual void onMqttConnect(bool sessionPresent) {} virtual bool onMqttMessage(char* topic, char* payload) { return false; } virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;} diff --git a/wled00/src/dependencies/json/ArduinoJson-v6.h b/wled00/src/dependencies/json/ArduinoJson-v6.h index 0dd590af4..6b79d7a2a 100644 --- a/wled00/src/dependencies/json/ArduinoJson-v6.h +++ b/wled00/src/dependencies/json/ArduinoJson-v6.h @@ -7,183 +7,199 @@ #ifdef __cplusplus #if __cplusplus >= 201103L -#define ARDUINOJSON_HAS_LONG_LONG 1 -#define ARDUINOJSON_HAS_NULLPTR 1 -#define ARDUINOJSON_HAS_RVALUE_REFERENCES 1 +# define ARDUINOJSON_HAS_LONG_LONG 1 +# define ARDUINOJSON_HAS_RVALUE_REFERENCES 1 #else -#define ARDUINOJSON_HAS_LONG_LONG 0 -#define ARDUINOJSON_HAS_NULLPTR 0 -#define ARDUINOJSON_HAS_RVALUE_REFERENCES 0 +# define ARDUINOJSON_HAS_LONG_LONG 0 +# define ARDUINOJSON_HAS_RVALUE_REFERENCES 0 +#endif +#ifndef ARDUINOJSON_HAS_NULLPTR +# if __cplusplus >= 201103L +# define ARDUINOJSON_HAS_NULLPTR 1 +# else +# define ARDUINOJSON_HAS_NULLPTR 0 +# endif #endif #if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG -#define ARDUINOJSON_HAS_INT64 1 +# define ARDUINOJSON_HAS_INT64 1 #else -#define ARDUINOJSON_HAS_INT64 0 +# define ARDUINOJSON_HAS_INT64 0 #endif #ifndef ARDUINOJSON_EMBEDDED_MODE -#if defined(ARDUINO) /* Arduino*/ \ - || defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \ - || defined(__XC) /* MPLAB XC compiler */ \ - || defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \ - || defined(__AVR) /* Atmel AVR8/GNU C Compiler */ -#define ARDUINOJSON_EMBEDDED_MODE 1 -#else -#define ARDUINOJSON_EMBEDDED_MODE 0 -#endif +# if defined(ARDUINO) /* Arduino*/ \ + || defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \ + || defined(__XC) /* MPLAB XC compiler */ \ + || defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \ + || defined(__AVR) /* Atmel AVR8/GNU C Compiler */ +# define ARDUINOJSON_EMBEDDED_MODE 1 +# else +# define ARDUINOJSON_EMBEDDED_MODE 0 +# endif #endif #if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include) -#if __has_include() && \ +# if __has_include() && \ __has_include() && \ !defined(min) && \ !defined(max) -#define ARDUINOJSON_ENABLE_STD_STREAM 1 -#else -#define ARDUINOJSON_ENABLE_STD_STREAM 0 -#endif +# define ARDUINOJSON_ENABLE_STD_STREAM 1 +# else +# define ARDUINOJSON_ENABLE_STD_STREAM 0 +# endif #endif #if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include) -#if __has_include() && !defined(min) && !defined(max) -#define ARDUINOJSON_ENABLE_STD_STRING 1 -#else -#define ARDUINOJSON_ENABLE_STD_STRING 0 +# if __has_include() && !defined(min) && !defined(max) +# define ARDUINOJSON_ENABLE_STD_STRING 1 +# else +# define ARDUINOJSON_ENABLE_STD_STRING 0 +# endif #endif +#ifndef ARDUINOJSON_ENABLE_STRING_VIEW +# ifdef __has_include +# if __has_include() && __cplusplus >= 201703L +# define ARDUINOJSON_ENABLE_STRING_VIEW 1 +# endif +# endif +#endif +#ifndef ARDUINOJSON_ENABLE_STRING_VIEW +# define ARDUINOJSON_ENABLE_STRING_VIEW 0 #endif #if ARDUINOJSON_EMBEDDED_MODE -#ifndef ARDUINOJSON_USE_DOUBLE -#define ARDUINOJSON_USE_DOUBLE 0 -#endif -#ifndef ARDUINOJSON_USE_LONG_LONG -#define ARDUINOJSON_USE_LONG_LONG 0 -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STRING -#define ARDUINOJSON_ENABLE_STD_STRING 0 -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STREAM -#define ARDUINOJSON_ENABLE_STD_STREAM 0 -#endif -#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT -#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 -#endif -#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE -#if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 2 -#define ARDUINOJSON_SLOT_OFFSET_SIZE 1 -#else -#define ARDUINOJSON_SLOT_OFFSET_SIZE 2 -#endif -#endif +# ifndef ARDUINOJSON_USE_DOUBLE +# define ARDUINOJSON_USE_DOUBLE 0 +# endif +# ifndef ARDUINOJSON_USE_LONG_LONG +# define ARDUINOJSON_USE_LONG_LONG 0 +# endif +# ifndef ARDUINOJSON_ENABLE_STD_STRING +# define ARDUINOJSON_ENABLE_STD_STRING 0 +# endif +# ifndef ARDUINOJSON_ENABLE_STD_STREAM +# define ARDUINOJSON_ENABLE_STD_STREAM 0 +# endif +# ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +# define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 +# endif +# ifndef ARDUINOJSON_SLOT_OFFSET_SIZE +# if defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 2 +# define ARDUINOJSON_SLOT_OFFSET_SIZE 1 +# else +# define ARDUINOJSON_SLOT_OFFSET_SIZE 2 +# endif +# endif #else // ARDUINOJSON_EMBEDDED_MODE -#ifndef ARDUINOJSON_USE_DOUBLE -#define ARDUINOJSON_USE_DOUBLE 1 -#endif -#ifndef ARDUINOJSON_USE_LONG_LONG -#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64 -#define ARDUINOJSON_USE_LONG_LONG 1 -#else -#define ARDUINOJSON_USE_LONG_LONG 0 -#endif -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STRING -#define ARDUINOJSON_ENABLE_STD_STRING 1 -#endif -#ifndef ARDUINOJSON_ENABLE_STD_STREAM -#define ARDUINOJSON_ENABLE_STD_STREAM 1 -#endif -#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT -#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 -#endif -#ifndef ARDUINOJSON_SLOT_OFFSET_SIZE -#define ARDUINOJSON_SLOT_OFFSET_SIZE 4 -#endif +# ifndef ARDUINOJSON_USE_DOUBLE +# define ARDUINOJSON_USE_DOUBLE 1 +# endif +# ifndef ARDUINOJSON_USE_LONG_LONG +# if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64 +# define ARDUINOJSON_USE_LONG_LONG 1 +# else +# define ARDUINOJSON_USE_LONG_LONG 0 +# endif +# endif +# ifndef ARDUINOJSON_ENABLE_STD_STRING +# define ARDUINOJSON_ENABLE_STD_STRING 1 +# endif +# ifndef ARDUINOJSON_ENABLE_STD_STREAM +# define ARDUINOJSON_ENABLE_STD_STREAM 1 +# endif +# ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT +# define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 +# endif +# ifndef ARDUINOJSON_SLOT_OFFSET_SIZE +# define ARDUINOJSON_SLOT_OFFSET_SIZE 4 +# endif #endif // ARDUINOJSON_EMBEDDED_MODE #ifdef ARDUINO #include -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING -#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 -#endif -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM -#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 -#endif -#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT -#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1 -#endif +# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +# define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 +# endif +# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM +# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 +# endif +# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT +# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1 +# endif #else // ARDUINO -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING -#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 -#endif -#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM -#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 -#endif -#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT -#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0 -#endif +# ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING +# define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 +# endif +# ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM +# define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 +# endif +# ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT +# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0 +# endif #endif // ARDUINO #ifndef ARDUINOJSON_ENABLE_PROGMEM -#if defined(PROGMEM) && defined(pgm_read_byte) && defined(pgm_read_dword) && \ - defined(pgm_read_ptr) && defined(pgm_read_float) -#define ARDUINOJSON_ENABLE_PROGMEM 1 -#else -#define ARDUINOJSON_ENABLE_PROGMEM 0 -#endif +# if defined(PROGMEM) && defined(pgm_read_byte) && defined(pgm_read_dword) && \ + defined(pgm_read_ptr) && defined(pgm_read_float) +# define ARDUINOJSON_ENABLE_PROGMEM 1 +# else +# define ARDUINOJSON_ENABLE_PROGMEM 0 +# endif #endif #ifndef ARDUINOJSON_DECODE_UNICODE -#define ARDUINOJSON_DECODE_UNICODE 1 +# define ARDUINOJSON_DECODE_UNICODE 1 #endif #ifndef ARDUINOJSON_ENABLE_COMMENTS -#define ARDUINOJSON_ENABLE_COMMENTS 0 +# define ARDUINOJSON_ENABLE_COMMENTS 0 #endif #ifndef ARDUINOJSON_ENABLE_NAN -#define ARDUINOJSON_ENABLE_NAN 0 +# define ARDUINOJSON_ENABLE_NAN 0 #endif #ifndef ARDUINOJSON_ENABLE_INFINITY -#define ARDUINOJSON_ENABLE_INFINITY 0 +# define ARDUINOJSON_ENABLE_INFINITY 0 #endif #ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD -#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 +# define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 #endif #ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD -#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 +# define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 #endif #ifndef ARDUINOJSON_LITTLE_ENDIAN -#if defined(_MSC_VER) || \ - (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ - defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64) -#define ARDUINOJSON_LITTLE_ENDIAN 1 -#else -#define ARDUINOJSON_LITTLE_ENDIAN 0 -#endif +# if defined(_MSC_VER) || \ + (defined(__BYTE_ORDER__) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64) +# define ARDUINOJSON_LITTLE_ENDIAN 1 +# else +# define ARDUINOJSON_LITTLE_ENDIAN 0 +# endif #endif #ifndef ARDUINOJSON_ENABLE_ALIGNMENT -#if defined(__AVR) -#define ARDUINOJSON_ENABLE_ALIGNMENT 0 -#else -#define ARDUINOJSON_ENABLE_ALIGNMENT 1 -#endif +# if defined(__AVR) +# define ARDUINOJSON_ENABLE_ALIGNMENT 0 +# else +# define ARDUINOJSON_ENABLE_ALIGNMENT 1 +# endif #endif #ifndef ARDUINOJSON_TAB -#define ARDUINOJSON_TAB " " +# define ARDUINOJSON_TAB " " #endif #ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION -#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1 +# define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1 #endif #ifndef ARDUINOJSON_STRING_BUFFER_SIZE -#define ARDUINOJSON_STRING_BUFFER_SIZE 32 +# define ARDUINOJSON_STRING_BUFFER_SIZE 32 #endif #ifndef ARDUINOJSON_DEBUG -#ifdef __PLATFORMIO_BUILD_DEBUG__ -#define ARDUINOJSON_DEBUG 1 -#else -#define ARDUINOJSON_DEBUG 0 -#endif +# ifdef __PLATFORMIO_BUILD_DEBUG__ +# define ARDUINOJSON_DEBUG 1 +# else +# define ARDUINOJSON_DEBUG 0 +# endif #endif #if ARDUINOJSON_HAS_NULLPTR && defined(nullptr) -#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr +# error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr #endif #if !ARDUINOJSON_DEBUG -#ifdef __clang__ -#pragma clang system_header -#elif defined __GNUC__ -#pragma GCC system_header -#endif +# ifdef __clang__ +# pragma clang system_header +# elif defined __GNUC__ +# pragma GCC system_header +# endif #endif #define ARDUINOJSON_EXPAND6(a, b, c, d, e, f) a, b, c, d, e, f #define ARDUINOJSON_EXPAND9(a, b, c, d, e, f, g, h, i) a, b, c, d, e, f, g, h, i @@ -212,29 +228,29 @@ #define ARDUINOJSON_HEX_DIGIT_1111() F #define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D() #define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D) -#define ARDUINOJSON_VERSION "6.18.0" +#define ARDUINOJSON_VERSION "6.18.1" #define ARDUINOJSON_VERSION_MAJOR 6 #define ARDUINOJSON_VERSION_MINOR 18 -#define ARDUINOJSON_VERSION_REVISION 0 +#define ARDUINOJSON_VERSION_REVISION 1 #ifndef ARDUINOJSON_NAMESPACE -#define ARDUINOJSON_NAMESPACE \ - ARDUINOJSON_CONCAT4( \ - ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ - ARDUINOJSON_VERSION_MINOR, \ - ARDUINOJSON_VERSION_REVISION), \ - _, \ - ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \ - ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \ - ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ - ARDUINOJSON_HEX_DIGIT( \ - ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ - ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE)) +# define ARDUINOJSON_NAMESPACE \ + ARDUINOJSON_CONCAT4( \ + ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \ + ARDUINOJSON_VERSION_MINOR, \ + ARDUINOJSON_VERSION_REVISION), \ + _, \ + ARDUINOJSON_HEX_DIGIT( \ + ARDUINOJSON_ENABLE_PROGMEM, ARDUINOJSON_USE_LONG_LONG, \ + ARDUINOJSON_USE_DOUBLE, ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \ + ARDUINOJSON_HEX_DIGIT( \ + ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \ + ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE)) #endif #if ARDUINOJSON_DEBUG #include -#define ARDUINOJSON_ASSERT(X) assert(X) +# define ARDUINOJSON_ASSERT(X) assert(X) #else -#define ARDUINOJSON_ASSERT(X) ((void)0) +# define ARDUINOJSON_ASSERT(X) ((void)0) #endif #include namespace ARDUINOJSON_NAMESPACE { @@ -345,22 +361,27 @@ struct Max { static const size_t value = Y; }; } // namespace ARDUINOJSON_NAMESPACE +#include #include namespace ARDUINOJSON_NAMESPACE { -template -struct int_t; -template <> -struct int_t<8> { - typedef int8_t type; -}; -template <> -struct int_t<16> { - typedef int16_t type; -}; -template <> -struct int_t<32> { - typedef int32_t type; -}; +inline int safe_strcmp(const char* a, const char* b) { + if (a == b) + return 0; + if (!a) + return -1; + if (!b) + return 1; + return strcmp(a, b); +} +inline int safe_strncmp(const char* a, const char* b, size_t n) { + if (a == b) + return 0; + if (!a) + return -1; + if (!b) + return 1; + return strncmp(a, b, n); +} template struct conditional { typedef TrueType type; @@ -418,8 +439,8 @@ template struct is_const : true_type {}; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4244) +# pragma warning(push) +# pragma warning(disable : 4244) #endif #ifdef __ICCARM__ #pragma diag_suppress=Pa093 @@ -437,41 +458,58 @@ struct is_convertible { }; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif #ifdef __ICCARM__ #pragma diag_default=Pa093 #endif namespace ARDUINOJSON_NAMESPACE { -template -struct is_floating_point : false_type {}; -template <> -struct is_floating_point : true_type {}; -template <> -struct is_floating_point : true_type {}; template struct is_same : false_type {}; template struct is_same : true_type {}; template -struct is_integral { - static const bool value = - is_same::value || is_same::value || - is_same::value || is_same::value || - is_same::value || is_same::value || - is_same::value || is_same::value || -#if ARDUINOJSON_HAS_LONG_LONG - is_same::value || - is_same::value || -#endif -#if ARDUINOJSON_HAS_INT64 - is_same::value || - is_same::value || -#endif - is_same::value || is_same::value; +struct remove_cv { + typedef T type; }; template -struct is_integral : is_integral {}; +struct remove_cv { + typedef T type; +}; +template +struct remove_cv { + typedef T type; +}; +template +struct remove_cv { + typedef T type; +}; +template +struct is_floating_point + : integral_constant< + bool, // + is_same::type>::value || + is_same::type>::value> {}; +template +struct is_integral : integral_constant::type, signed char>::value || + is_same::type, unsigned char>::value || + is_same::type, signed short>::value || + is_same::type, unsigned short>::value || + is_same::type, signed int>::value || + is_same::type, unsigned int>::value || + is_same::type, signed long>::value || + is_same::type, unsigned long>::value || +#if ARDUINOJSON_HAS_LONG_LONG + is_same::type, signed long long>::value || + is_same::type, unsigned long long>::value || +#endif +#if ARDUINOJSON_HAS_INT64 + is_same::type, signed __int64>::value || + is_same::type, unsigned __int64>::value || +#endif + is_same::type, char>::value || + is_same::type, bool>::value> {}; template struct is_enum { static const bool value = is_convertible::value && @@ -482,50 +520,34 @@ template struct is_pointer : false_type {}; template struct is_pointer : true_type {}; -template -struct is_signed : false_type {}; -template <> -struct is_signed : true_type {}; -template <> -struct is_signed : true_type {}; -template <> -struct is_signed : true_type {}; -template <> -struct is_signed : true_type {}; -template <> -struct is_signed : true_type {}; -template <> -struct is_signed : true_type {}; -template <> -struct is_signed : true_type {}; +template +struct is_signed : integral_constant::type, char>::value || + is_same::type, signed char>::value || + is_same::type, signed short>::value || + is_same::type, signed int>::value || + is_same::type, signed long>::value || #if ARDUINOJSON_HAS_LONG_LONG -template <> -struct is_signed : true_type {}; + is_same::type, signed long long>::value || #endif #if ARDUINOJSON_HAS_INT64 -template <> -struct is_signed : true_type {}; + is_same::type, signed __int64>::value || #endif -template -struct is_unsigned : false_type {}; -template <> -struct is_unsigned : true_type {}; -template <> -struct is_unsigned : true_type {}; -template <> -struct is_unsigned : true_type {}; -template <> -struct is_unsigned : true_type {}; -template <> -struct is_unsigned : true_type {}; + is_same::type, float>::value || + is_same::type, double>::value> {}; +template +struct is_unsigned : integral_constant::type, unsigned char>::value || + is_same::type, unsigned short>::value || + is_same::type, unsigned int>::value || + is_same::type, unsigned long>::value || #if ARDUINOJSON_HAS_INT64 -template <> -struct is_unsigned : true_type {}; + is_same::type, unsigned __int64>::value || #endif #if ARDUINOJSON_HAS_LONG_LONG -template <> -struct is_unsigned : true_type {}; + is_same::type, unsigned long long>::value || #endif + is_same::type, bool>::value> {}; template struct type_identity { typedef T type; @@ -578,10 +600,365 @@ template struct remove_reference { typedef T type; }; +template +struct IsString : false_type {}; +template +struct IsString : IsString {}; +template +struct IsString : IsString {}; +namespace storage_policies { +struct store_by_address {}; +struct store_by_copy {}; +struct decide_at_runtime {}; +} // namespace storage_policies +class ConstRamStringAdapter { + public: + ConstRamStringAdapter(const char* str = 0) : _str(str) {} + int compare(const char* other) const { + return safe_strcmp(_str, other); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + size_t size() const { + if (!_str) + return 0; + return strlen(_str); + } + const char* data() const { + return _str; + } + typedef storage_policies::store_by_address storage_policy; + protected: + const char* _str; +}; +template <> +struct IsString : true_type {}; +template +struct IsString : true_type {}; +inline ConstRamStringAdapter adaptString(const char* str) { + return ConstRamStringAdapter(str); +} +class RamStringAdapter : public ConstRamStringAdapter { + public: + RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} + void copyTo(char* p, size_t n) const { + memcpy(p, _str, n); + } + typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy; +}; +template +inline RamStringAdapter adaptString(const TChar* str) { + return RamStringAdapter(reinterpret_cast(str)); +} +inline RamStringAdapter adaptString(char* str) { + return RamStringAdapter(str); +} +template +struct IsString { + static const bool value = sizeof(TChar) == 1; +}; +template <> +struct IsString { + static const bool value = false; +}; +class SizedRamStringAdapter { + public: + SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {} + int compare(const char* other) const { + return safe_strncmp(_str, other, _size); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + void copyTo(char* p, size_t n) const { + memcpy(p, _str, n); + } + size_t size() const { + return _size; + } + typedef storage_policies::store_by_copy storage_policy; + private: + const char* _str; + size_t _size; +}; +template +inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) { + return SizedRamStringAdapter(reinterpret_cast(str), size); +} +} // namespace ARDUINOJSON_NAMESPACE +#if ARDUINOJSON_ENABLE_STD_STRING +#include +namespace ARDUINOJSON_NAMESPACE { +template +class StdStringAdapter { + public: + StdStringAdapter(const TString& str) : _str(&str) {} + void copyTo(char* p, size_t n) const { + memcpy(p, _str->c_str(), n); + } + bool isNull() const { + return false; + } + int compare(const char* other) const { + if (!other) + return 1; + return _str->compare(other); + } + bool equals(const char* expected) const { + if (!expected) + return false; + return *_str == expected; + } + size_t size() const { + return _str->size(); + } + typedef storage_policies::store_by_copy storage_policy; + private: + const TString* _str; +}; +template +struct IsString > : true_type { +}; +template +inline StdStringAdapter > +adaptString(const std::basic_string& str) { + return StdStringAdapter >( + str); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +#if ARDUINOJSON_ENABLE_STRING_VIEW +#include +namespace ARDUINOJSON_NAMESPACE { +class StringViewAdapter { + public: + StringViewAdapter(std::string_view str) : _str(str) {} + void copyTo(char* p, size_t n) const { + memcpy(p, _str.data(), n); + } + bool isNull() const { + return false; + } + int compare(const char* other) const { + if (!other) + return 1; + return _str.compare(other); + } + bool equals(const char* expected) const { + if (!expected) + return false; + return _str == expected; + } + size_t size() const { + return _str.size(); + } + typedef storage_policies::store_by_copy storage_policy; + private: + std::string_view _str; +}; +template <> +struct IsString : true_type {}; +inline StringViewAdapter adaptString(const std::string_view& str) { + return StringViewAdapter(str); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +#if ARDUINOJSON_ENABLE_ARDUINO_STRING +namespace ARDUINOJSON_NAMESPACE { +class ArduinoStringAdapter { + public: + ArduinoStringAdapter(const ::String& str) : _str(&str) {} + void copyTo(char* p, size_t n) const { + memcpy(p, _str->c_str(), n); + } + bool isNull() const { + return !_str->c_str(); + } + int compare(const char* other) const { + const char* me = _str->c_str(); + return safe_strcmp(me, other); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + size_t size() const { + return _str->length(); + } + typedef storage_policies::store_by_copy storage_policy; + private: + const ::String* _str; +}; +template <> +struct IsString< ::String> : true_type {}; +template <> +struct IsString< ::StringSumHelper> : true_type {}; +inline ArduinoStringAdapter adaptString(const ::String& str) { + return ArduinoStringAdapter(str); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +#if ARDUINOJSON_ENABLE_PROGMEM +namespace ARDUINOJSON_NAMESPACE { +struct pgm_p { + pgm_p(const char* p) : address(p) {} + const char* address; +}; +} // namespace ARDUINOJSON_NAMESPACE +#ifndef strlen_P +inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) { + const char* p = s.address; + ARDUINOJSON_ASSERT(p != NULL); + while (pgm_read_byte(p)) p++; + return size_t(p - s.address); +} +#endif +#ifndef strncmp_P +inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) { + const char* s1 = a; + const char* s2 = b.address; + ARDUINOJSON_ASSERT(s1 != NULL); + ARDUINOJSON_ASSERT(s2 != NULL); + while (n-- > 0) { + char c1 = *s1++; + char c2 = static_cast(pgm_read_byte(s2++)); + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + if (c1 == 0 /* and c2 as well */) + return 0; + } + return 0; +} +#endif +#ifndef strcmp_P +inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) { + const char* s1 = a; + const char* s2 = b.address; + ARDUINOJSON_ASSERT(s1 != NULL); + ARDUINOJSON_ASSERT(s2 != NULL); + for (;;) { + char c1 = *s1++; + char c2 = static_cast(pgm_read_byte(s2++)); + if (c1 < c2) + return -1; + if (c1 > c2) + return 1; + if (c1 == 0 /* and c2 as well */) + return 0; + } +} +#endif +#ifndef memcpy_P +inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) { + uint8_t* d = reinterpret_cast(dst); + const char* s = src.address; + ARDUINOJSON_ASSERT(d != NULL); + ARDUINOJSON_ASSERT(s != NULL); + while (n-- > 0) { + *d++ = pgm_read_byte(s++); + } + return dst; +} +#endif +namespace ARDUINOJSON_NAMESPACE { +class FlashStringAdapter { + public: + FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} + int compare(const char* other) const { + if (!other && !_str) + return 0; + if (!_str) + return -1; + if (!other) + return 1; + return -strcmp_P(other, reinterpret_cast(_str)); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + void copyTo(char* p, size_t n) const { + memcpy_P(p, reinterpret_cast(_str), n); + } + size_t size() const { + if (!_str) + return 0; + return strlen_P(reinterpret_cast(_str)); + } + typedef storage_policies::store_by_copy storage_policy; + private: + const __FlashStringHelper* _str; +}; +inline FlashStringAdapter adaptString(const __FlashStringHelper* str) { + return FlashStringAdapter(str); +} +template <> +struct IsString : true_type {}; +class SizedFlashStringAdapter { + public: + SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz) + : _str(str), _size(sz) {} + int compare(const char* other) const { + if (!other && !_str) + return 0; + if (!_str) + return -1; + if (!other) + return 1; + return -strncmp_P(other, reinterpret_cast(_str), _size); + } + bool equals(const char* expected) const { + return compare(expected) == 0; + } + bool isNull() const { + return !_str; + } + void copyTo(char* p, size_t n) const { + memcpy_P(p, reinterpret_cast(_str), n); + } + size_t size() const { + return _size; + } + typedef storage_policies::store_by_copy storage_policy; + private: + const __FlashStringHelper* _str; + size_t _size; +}; +inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str, + size_t sz) { + return SizedFlashStringAdapter(str, sz); +} +} // namespace ARDUINOJSON_NAMESPACE +#endif +namespace ARDUINOJSON_NAMESPACE { +template +struct int_t; +template <> +struct int_t<8> { + typedef int8_t type; +}; +template <> +struct int_t<16> { + typedef int16_t type; +}; +template <> +struct int_t<32> { + typedef int32_t type; +}; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4310) +# pragma warning(push) +# pragma warning(disable : 4310) #endif namespace ARDUINOJSON_NAMESPACE { template @@ -607,14 +984,9 @@ struct numeric_limits< }; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif namespace ARDUINOJSON_NAMESPACE { -namespace storage_policies { -struct store_by_address {}; -struct store_by_copy {}; -struct decide_at_runtime {}; -} // namespace storage_policies #if ARDUINOJSON_USE_DOUBLE typedef double Float; #else @@ -629,13 +1001,13 @@ typedef unsigned long UInt; #endif } // namespace ARDUINOJSON_NAMESPACE #if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG -#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \ - static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \ - "To use 64-bit integers with ArduinoJson, you must set " \ - "ARDUINOJSON_USE_LONG_LONG to 1. See " \ - "https://arduinojson.org/v6/api/config/use_long_long/"); +# define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \ + static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \ + "To use 64-bit integers with ArduinoJson, you must set " \ + "ARDUINOJSON_USE_LONG_LONG to 1. See " \ + "https://arduinojson.org/v6/api/config/use_long_long/"); #else -#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) +# define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) #endif namespace ARDUINOJSON_NAMESPACE { enum { @@ -749,7 +1121,6 @@ class VariantSlot { } }; } // namespace ARDUINOJSON_NAMESPACE -#include #define JSON_STRING_SIZE(SIZE) (SIZE + 1) namespace ARDUINOJSON_NAMESPACE { class MemoryPool { @@ -765,7 +1136,7 @@ class MemoryPool { ARDUINOJSON_ASSERT(isAligned(_end)); } void* buffer() { - return _begin; + return _begin; // NOLINT(clang-analyzer-unix.Malloc) } size_t capacity() const { return size_t(_end - _begin); @@ -784,7 +1155,7 @@ class MemoryPool { if (str.isNull()) return 0; #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION - const char* existingCopy = findString(str.begin()); + const char* existingCopy = findString(str); if (existingCopy) return existingCopy; #endif @@ -802,7 +1173,7 @@ class MemoryPool { } const char* saveStringFromFreeZone(size_t len) { #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION - const char* dup = findString(_left); + const char* dup = findString(adaptString(_left)); if (dup) return dup; #endif @@ -853,14 +1224,11 @@ class MemoryPool { ARDUINOJSON_ASSERT(isAligned(_right)); } #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION - template - const char* findString(TIterator str) { + template + const char* findString(const TAdaptedString& str) { for (char* next = _begin; next < _left; ++next) { - char* begin = next; - for (TIterator it = str; *it == *next; ++it) { - if (*next++ == 0) - return begin; - } + if (str.equals(next)) + return next; while (*next) ++next; } return 0; @@ -891,368 +1259,6 @@ class MemoryPool { char *_begin, *_left, *_right, *_end; bool _overflowed; }; -inline int safe_strcmp(const char* a, const char* b) { - if (a == b) - return 0; - if (!a) - return -1; - if (!b) - return 1; - return strcmp(a, b); -} -inline int safe_strncmp(const char* a, const char* b, size_t n) { - if (a == b) - return 0; - if (!a) - return -1; - if (!b) - return 1; - return strncmp(a, b, n); -} -template -struct IsString : false_type {}; -template -struct IsString : IsString {}; -template -struct IsString : IsString {}; -class ConstRamStringAdapter { - public: - ConstRamStringAdapter(const char* str = 0) : _str(str) {} - int compare(const char* other) const { - return safe_strcmp(_str, other); - } - bool equals(const char* expected) const { - return compare(expected) == 0; - } - bool isNull() const { - return !_str; - } - size_t size() const { - if (!_str) - return 0; - return strlen(_str); - } - const char* data() const { - return _str; - } - const char* begin() const { - return _str; - } - typedef storage_policies::store_by_address storage_policy; - protected: - const char* _str; -}; -template <> -struct IsString : true_type {}; -template -struct IsString : true_type {}; -inline ConstRamStringAdapter adaptString(const char* str) { - return ConstRamStringAdapter(str); -} -class RamStringAdapter : public ConstRamStringAdapter { - public: - RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} - void copyTo(char* p, size_t n) const { - memcpy(p, _str, n); - } - typedef ARDUINOJSON_NAMESPACE::storage_policies::store_by_copy storage_policy; -}; -template -inline RamStringAdapter adaptString(const TChar* str) { - return RamStringAdapter(reinterpret_cast(str)); -} -inline RamStringAdapter adaptString(char* str) { - return RamStringAdapter(str); -} -template -struct IsString { - static const bool value = sizeof(TChar) == 1; -}; -template <> -struct IsString { - static const bool value = false; -}; -class SizedRamStringAdapter { - public: - SizedRamStringAdapter(const char* str, size_t n) : _str(str), _size(n) {} - int compare(const char* other) const { - return safe_strncmp(_str, other, _size); - } - bool equals(const char* expected) const { - return compare(expected) == 0; - } - bool isNull() const { - return !_str; - } - void copyTo(char* p, size_t n) const { - memcpy(p, _str, n); - } - size_t size() const { - return _size; - } - const char* begin() const { - return _str; - } - typedef storage_policies::store_by_copy storage_policy; - private: - const char* _str; - size_t _size; -}; -template -inline SizedRamStringAdapter adaptString(const TChar* str, size_t size) { - return SizedRamStringAdapter(reinterpret_cast(str), size); -} -} // namespace ARDUINOJSON_NAMESPACE -#if ARDUINOJSON_ENABLE_STD_STRING -#include -namespace ARDUINOJSON_NAMESPACE { -template -class StdStringAdapter { - public: - StdStringAdapter(const TString& str) : _str(&str) {} - void copyTo(char* p, size_t n) const { - memcpy(p, _str->c_str(), n); - } - bool isNull() const { - return false; - } - int compare(const char* other) const { - if (!other) - return 1; - return _str->compare(other); - } - bool equals(const char* expected) const { - if (!expected) - return false; - return *_str == expected; - } - size_t size() const { - return _str->size(); - } - const char* begin() const { - return _str->c_str(); - } - typedef storage_policies::store_by_copy storage_policy; - private: - const TString* _str; -}; -template -struct IsString > : true_type { -}; -template -inline StdStringAdapter > -adaptString(const std::basic_string& str) { - return StdStringAdapter >( - str); -} -} // namespace ARDUINOJSON_NAMESPACE -#endif -#if ARDUINOJSON_ENABLE_ARDUINO_STRING -namespace ARDUINOJSON_NAMESPACE { -class ArduinoStringAdapter { - public: - ArduinoStringAdapter(const ::String& str) : _str(&str) {} - void copyTo(char* p, size_t n) const { - memcpy(p, _str->c_str(), n); - } - bool isNull() const { - return !_str->c_str(); - } - int compare(const char* other) const { - const char* me = _str->c_str(); - return safe_strcmp(me, other); - } - bool equals(const char* expected) const { - return compare(expected) == 0; - } - size_t size() const { - return _str->length(); - } - const char* begin() const { - return _str->c_str(); - } - typedef storage_policies::store_by_copy storage_policy; - private: - const ::String* _str; -}; -template <> -struct IsString< ::String> : true_type {}; -template <> -struct IsString< ::StringSumHelper> : true_type {}; -inline ArduinoStringAdapter adaptString(const ::String& str) { - return ArduinoStringAdapter(str); -} -} // namespace ARDUINOJSON_NAMESPACE -#endif -#if ARDUINOJSON_ENABLE_PROGMEM -namespace ARDUINOJSON_NAMESPACE { -struct pgm_p { - pgm_p(const char* p) : address(p) {} - const char* address; -}; -} // namespace ARDUINOJSON_NAMESPACE -#ifndef strlen_P -inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) { - const char* p = s.address; - ARDUINOJSON_ASSERT(p != NULL); - while (pgm_read_byte(p)) p++; - return size_t(p - s.address); -} -#endif -#ifndef strncmp_P -inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) { - const char* s1 = a; - const char* s2 = b.address; - ARDUINOJSON_ASSERT(s1 != NULL); - ARDUINOJSON_ASSERT(s2 != NULL); - while (n-- > 0) { - char c1 = *s1++; - char c2 = static_cast(pgm_read_byte(s2++)); - if (c1 < c2) - return -1; - if (c1 > c2) - return 1; - if (c1 == 0 /* and c2 as well */) - return 0; - } - return 0; -} -#endif -#ifndef strcmp_P -inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) { - const char* s1 = a; - const char* s2 = b.address; - ARDUINOJSON_ASSERT(s1 != NULL); - ARDUINOJSON_ASSERT(s2 != NULL); - for (;;) { - char c1 = *s1++; - char c2 = static_cast(pgm_read_byte(s2++)); - if (c1 < c2) - return -1; - if (c1 > c2) - return 1; - if (c1 == 0 /* and c2 as well */) - return 0; - } -} -#endif -#ifndef memcpy_P -inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) { - uint8_t* d = reinterpret_cast(dst); - const char* s = src.address; - ARDUINOJSON_ASSERT(d != NULL); - ARDUINOJSON_ASSERT(s != NULL); - while (n-- > 0) { - *d++ = pgm_read_byte(s++); - } - return dst; -} -#endif -namespace ARDUINOJSON_NAMESPACE { -class FlashStringIterator { - public: - explicit FlashStringIterator(const __FlashStringHelper* ptr) - : _ptr(reinterpret_cast(ptr)) {} - explicit FlashStringIterator(const char* ptr) : _ptr(ptr) {} - FlashStringIterator operator+(ptrdiff_t d) const { - return FlashStringIterator(_ptr + d); - } - ptrdiff_t operator-(FlashStringIterator other) const { - return _ptr - other._ptr; - } - FlashStringIterator operator++(int) { - return FlashStringIterator(_ptr++); - } - FlashStringIterator operator++() { - return FlashStringIterator(++_ptr); - } - bool operator!=(FlashStringIterator other) const { - return _ptr != other._ptr; - } - char operator*() const { - return char(pgm_read_byte(_ptr)); - } - private: - const char* _ptr; -}; -class FlashStringAdapter { - public: - FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} - int compare(const char* other) const { - if (!other && !_str) - return 0; - if (!_str) - return -1; - if (!other) - return 1; - return -strcmp_P(other, reinterpret_cast(_str)); - } - bool equals(const char* expected) const { - return compare(expected) == 0; - } - bool isNull() const { - return !_str; - } - void copyTo(char* p, size_t n) const { - memcpy_P(p, reinterpret_cast(_str), n); - } - size_t size() const { - if (!_str) - return 0; - return strlen_P(reinterpret_cast(_str)); - } - FlashStringIterator begin() const { - return FlashStringIterator(_str); - } - typedef storage_policies::store_by_copy storage_policy; - private: - const __FlashStringHelper* _str; -}; -inline FlashStringAdapter adaptString(const __FlashStringHelper* str) { - return FlashStringAdapter(str); -} -template <> -struct IsString : true_type {}; -class SizedFlashStringAdapter { - public: - SizedFlashStringAdapter(const __FlashStringHelper* str, size_t sz) - : _str(str), _size(sz) {} - int compare(const char* other) const { - if (!other && !_str) - return 0; - if (!_str) - return -1; - if (!other) - return 1; - return -strncmp_P(other, reinterpret_cast(_str), _size); - } - bool equals(const char* expected) const { - return compare(expected) == 0; - } - bool isNull() const { - return !_str; - } - void copyTo(char* p, size_t n) const { - memcpy_P(p, reinterpret_cast(_str), n); - } - size_t size() const { - return _size; - } - FlashStringIterator begin() const { - return FlashStringIterator(_str); - } - typedef storage_policies::store_by_copy storage_policy; - private: - const __FlashStringHelper* _str; - size_t _size; -}; -inline SizedFlashStringAdapter adaptString(const __FlashStringHelper* str, - size_t sz) { - return SizedFlashStringAdapter(str, sz); -} -} // namespace ARDUINOJSON_NAMESPACE -#endif -namespace ARDUINOJSON_NAMESPACE { template class SerializedValue { public: @@ -1300,13 +1306,13 @@ inline SerializedValue serialized(TChar* p, size_t n) { } } // namespace ARDUINOJSON_NAMESPACE #if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wconversion" #elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#pragma GCC diagnostic push -#endif -#pragma GCC diagnostic ignored "-Wconversion" +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# pragma GCC diagnostic push +# endif +# pragma GCC diagnostic ignored "-Wconversion" #endif namespace ARDUINOJSON_NAMESPACE { template @@ -1348,7 +1354,18 @@ canConvertNumber(TIn) { } template typename enable_if::value && is_signed::value && - is_integral::value && is_unsigned::value, + is_integral::value && is_unsigned::value && + sizeof(TOut) >= sizeof(TIn), + bool>::type +canConvertNumber(TIn value) { + if (value < 0) + return false; + return TOut(value) <= numeric_limits::highest(); +} +template +typename enable_if::value && is_signed::value && + is_integral::value && is_unsigned::value && + sizeof(TOut) < sizeof(TIn), bool>::type canConvertNumber(TIn value) { if (value < 0) @@ -1369,18 +1386,18 @@ TOut convertNumber(TIn value) { } } // namespace ARDUINOJSON_NAMESPACE #if defined(__clang__) -#pragma clang diagnostic pop +# pragma clang diagnostic pop #elif defined(__GNUC__) -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#pragma GCC diagnostic pop -#endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# pragma GCC diagnostic pop +# endif #endif #if defined(__GNUC__) -#if __GNUC__ >= 7 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#pragma GCC diagnostic ignored "-Wuninitialized" -#endif +# if __GNUC__ >= 7 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# pragma GCC diagnostic ignored "-Wuninitialized" +# endif #endif namespace ARDUINOJSON_NAMESPACE { class VariantData { @@ -1388,7 +1405,7 @@ class VariantData { uint8_t _flags; public: void init() { - _flags = 0; + _flags = VALUE_IS_NULL; } template typename TVisitor::result_type accept(TVisitor &visitor) const { @@ -1658,9 +1675,9 @@ class VariantData { }; } // namespace ARDUINOJSON_NAMESPACE #if defined(__GNUC__) -#if __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif +# if __GNUC__ >= 8 +# pragma GCC diagnostic pop +# endif #endif namespace ARDUINOJSON_NAMESPACE { template @@ -1714,43 +1731,45 @@ template struct IsVisitable : IsVisitable {}; template struct Converter; +template +class InvalidConversion; // Error here? See https://arduinojson.org/v6/invalid-conversion/ } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER // Visual Studio -#define FORCE_INLINE // __forceinline causes C4714 when returning std::string -#define NO_INLINE __declspec(noinline) -#ifndef ARDUINOJSON_DEPRECATED -#define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg)) -#endif +# define FORCE_INLINE // __forceinline causes C4714 when returning std::string +# define NO_INLINE __declspec(noinline) +# ifndef ARDUINOJSON_DEPRECATED +# define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg)) +# endif #elif defined(__GNUC__) // GCC or Clang -#define FORCE_INLINE __attribute__((always_inline)) -#define NO_INLINE __attribute__((noinline)) -#ifndef ARDUINOJSON_DEPRECATED -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) -#define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg))) -#else -#define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated)) -#endif -#endif +# define FORCE_INLINE __attribute__((always_inline)) +# define NO_INLINE __attribute__((noinline)) +# ifndef ARDUINOJSON_DEPRECATED +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +# define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg))) +# else +# define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated)) +# endif +# endif #else // Other compilers -#define FORCE_INLINE -#define NO_INLINE -#ifndef ARDUINOJSON_DEPRECATED -#define ARDUINOJSON_DEPRECATED(msg) -#endif +# define FORCE_INLINE +# define NO_INLINE +# ifndef ARDUINOJSON_DEPRECATED +# define ARDUINOJSON_DEPRECATED(msg) +# endif #endif #if __cplusplus >= 201103L -#define NOEXCEPT noexcept +# define NOEXCEPT noexcept #else -#define NOEXCEPT throw() +# define NOEXCEPT throw() #endif #if defined(__has_attribute) -#if __has_attribute(no_sanitize) -#define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) +# if __has_attribute(no_sanitize) +# define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) +# else +# define ARDUINOJSON_NO_SANITIZE(check) +# endif #else -#define ARDUINOJSON_NO_SANITIZE(check) -#endif -#else -#define ARDUINOJSON_NO_SANITIZE(check) +# define ARDUINOJSON_NO_SANITIZE(check) #endif namespace ARDUINOJSON_NAMESPACE { template @@ -2168,11 +2187,9 @@ class VariantRef : public VariantRefBase, FORCE_INLINE bool set(const T &value) const { return Converter::toJson(value, *this); } - FORCE_INLINE bool ARDUINOJSON_DEPRECATED( + bool ARDUINOJSON_DEPRECATED( "Support for char is deprecated, use int8_t or uint8_t instead") - set(char value) const { - return set(value); - } + set(char value) const; template FORCE_INLINE bool set(T *value) const { return Converter::toJson(value, *this); @@ -2359,6 +2376,8 @@ struct Converter { static VariantRef fromJson(VariantRef src) { return src; } + static InvalidConversion fromJson( + VariantConstRef); static bool checkJson(VariantRef src) { VariantData *data = getData(src); return !!data; @@ -2580,6 +2599,11 @@ class ArrayRef : public ArrayRefBase, return; _data->removeElement(index); } + void clear() const { + if (!_data) + return; + _data->clear(); + } private: MemoryPool* _pool; }; @@ -2606,6 +2630,7 @@ struct Converter { MemoryPool* pool = getPool(src); return ArrayRef(pool, data != 0 ? data->asArray() : 0); } + static InvalidConversion fromJson(VariantConstRef); static bool checkJson(VariantConstRef) { return false; } @@ -3004,6 +3029,8 @@ struct Converter { MemoryPool* pool = getPool(src); return ObjectRef(pool, data != 0 ? data->asObject() : 0); } + static InvalidConversion fromJson( + VariantConstRef); static bool checkJson(VariantConstRef) { return false; } @@ -3031,8 +3058,8 @@ struct VariantTo { }; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4522) +# pragma warning(push) +# pragma warning(disable : 4522) #endif namespace ARDUINOJSON_NAMESPACE { template @@ -3158,11 +3185,11 @@ class ElementProxy : public VariantOperators >, }; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4522) +# pragma warning(push) +# pragma warning(disable : 4522) #endif namespace ARDUINOJSON_NAMESPACE { template @@ -3292,7 +3319,7 @@ class MemberProxy : public VariantOperators >, }; } // namespace ARDUINOJSON_NAMESPACE #ifdef _MSC_VER -#pragma warning(pop) +# pragma warning(pop) #endif namespace ARDUINOJSON_NAMESPACE { class JsonDocument : public Visitable { @@ -3311,7 +3338,7 @@ class JsonDocument : public Visitable { } void clear() { _pool.clear(); - _data.setNull(); + _data.init(); } template bool is() { @@ -3489,13 +3516,13 @@ class JsonDocument : public Visitable { } protected: JsonDocument() : _pool(0, 0) { - _data.setNull(); + _data.init(); } JsonDocument(MemoryPool pool) : _pool(pool) { - _data.setNull(); + _data.init(); } JsonDocument(char* buf, size_t capa) : _pool(buf, capa) { - _data.setNull(); + _data.init(); } ~JsonDocument() {} void replacePool(MemoryPool pool) { @@ -4491,22 +4518,22 @@ typename enable_if::value, T>::type pgm_read( return pgm_read_dword(p); } } // namespace ARDUINOJSON_NAMESPACE -#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY -#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ - static type const name[] PROGMEM = value; -#endif -#ifndef ARDUINOJSON_READ_STATIC_ARRAY -#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ - pgm_read(name + index) -#endif +# ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +# define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] PROGMEM = value; +# endif +# ifndef ARDUINOJSON_READ_STATIC_ARRAY +# define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) \ + pgm_read(name + index) +# endif #else // i.e. ARDUINOJSON_ENABLE_PROGMEM == 0 -#ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY -#define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ - static type const name[] = value; -#endif -#ifndef ARDUINOJSON_READ_STATIC_ARRAY -#define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] -#endif +# ifndef ARDUINOJSON_DEFINE_STATIC_ARRAY +# define ARDUINOJSON_DEFINE_STATIC_ARRAY(type, name, value) \ + static type const name[] = value; +# endif +# ifndef ARDUINOJSON_READ_STATIC_ARRAY +# define ARDUINOJSON_READ_STATIC_ARRAY(type, name, index) name[index] +# endif #endif namespace ARDUINOJSON_NAMESPACE { template @@ -4898,6 +4925,9 @@ inline VariantConstRef operator|(VariantConstRef preferedValue, VariantConstRef defaultValue) { return preferedValue ? preferedValue : defaultValue; } +inline bool VariantRef::set(char value) const { + return set(value); +} } // namespace ARDUINOJSON_NAMESPACE #if ARDUINOJSON_ENABLE_STD_STREAM #include @@ -5274,8 +5304,7 @@ class StringCopier { private: MemoryPool* _pool; char* _ptr; - size_t _size; - size_t _capacity; + size_t _size, _capacity; }; class StringMover { public: @@ -5408,7 +5437,7 @@ class Latch { _loaded = true; } TReader _reader; - char _current; + char _current; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject) bool _loaded; #if ARDUINOJSON_DEBUG bool _ended; @@ -5416,10 +5445,10 @@ class Latch { }; } // namespace ARDUINOJSON_NAMESPACE #if defined(__GNUC__) -#if __GNUC__ >= 7 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif +# if __GNUC__ >= 7 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +# endif #endif namespace ARDUINOJSON_NAMESPACE { namespace Utf16 { @@ -5431,7 +5460,7 @@ inline bool isLowSurrogate(uint16_t codeunit) { } class Codepoint { public: - Codepoint() : _highSurrogate(0) {} + Codepoint() : _highSurrogate(0), _codepoint(0) {} bool append(uint16_t codeunit) { if (isHighSurrogate(codeunit)) { _highSurrogate = codeunit & 0x3FF; @@ -5455,9 +5484,9 @@ class Codepoint { } // namespace Utf16 } // namespace ARDUINOJSON_NAMESPACE #if defined(__GNUC__) -#if __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif +# if __GNUC__ >= 8 +# pragma GCC diagnostic pop +# endif #endif namespace ARDUINOJSON_NAMESPACE { namespace Utf8 { @@ -6220,7 +6249,6 @@ class TextFormatter { } protected: CountingDecorator _writer; - size_t _length; private: TextFormatter &operator=(const TextFormatter &); // cannot be assigned }; @@ -6312,10 +6340,10 @@ class Writer< ::String, void> { flush(); } size_t write(uint8_t c) { - ARDUINOJSON_ASSERT(_size < bufferCapacity); - _buffer[_size++] = static_cast(c); if (_size + 1 >= bufferCapacity) - flush(); + if (flush() != 0) + return 0; + _buffer[_size++] = static_cast(c); return 1; } size_t write(const uint8_t *s, size_t n) { @@ -6324,13 +6352,14 @@ class Writer< ::String, void> { } return n; } - private: - void flush() { + size_t flush() { ARDUINOJSON_ASSERT(_size < bufferCapacity); _buffer[_size] = 0; - *_destination += _buffer; - _size = 0; + if (_destination->concat(_buffer)) + _size = 0; + return _size; } + private: ::String *_destination; char _buffer[bufferCapacity]; size_t _size; @@ -6638,7 +6667,6 @@ class MsgPackDeserializer { return _foundSomething ? _error : DeserializationError::EmptyInput; } private: - MsgPackDeserializer &operator=(const MsgPackDeserializer &); bool invalidInput() { _error = DeserializationError::InvalidInput; return false; diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 21a7de8d0..5669f2f30 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -74,6 +74,10 @@ #include "../usermods/EleksTube_IPS/usermod_elekstube_ips.h" #endif +#ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR +#include "../usermods/usermod_rotary_brightness_color/usermod_rotary_brightness_color.h" +#endif + void registerUsermods() { /* @@ -143,4 +147,8 @@ void registerUsermods() #ifdef USERMOD_ELEKSTUBE_IPS usermods.add(new ElekstubeIPSUsermod()); #endif + + #ifdef USERMOD_ROTARY_ENCODER_BRIGHTNESS_COLOR + usermods.add(new RotaryEncoderBrightnessColor()); + #endif } diff --git a/wled00/wled.h b/wled00/wled.h index 06e0f2918..25f17a6d2 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2107042 +#define VERSION 2107061 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG