From 42a950b32e22c1e920c1b7354036d0504634b078 Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:12:53 +1100 Subject: [PATCH 01/10] Moved modes to Mode Registry folder --- {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeCircle.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeColorWipe.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeConfetti.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeSparkle.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeVisualiser.ino | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeCircle.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeColorWipe.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeConfetti.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeSparkle.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeVisualiser.ino (100%) diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeCircle.ino b/Mode Registry/ModeCircle.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeCircle.ino rename to Mode Registry/ModeCircle.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeColorWipe.ino b/Mode Registry/ModeColorWipe.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeColorWipe.ino rename to Mode Registry/ModeColorWipe.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeConfetti.ino b/Mode Registry/ModeConfetti.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeConfetti.ino rename to Mode Registry/ModeConfetti.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeSparkle.ino b/Mode Registry/ModeSparkle.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeSparkle.ino rename to Mode Registry/ModeSparkle.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeVisualiser.ino b/Mode Registry/ModeVisualiser.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeVisualiser.ino rename to Mode Registry/ModeVisualiser.ino From f01e09c6271c564b7f0c7ee96975b452bce894e0 Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:13:08 +1100 Subject: [PATCH 02/10] Made mode registry readme --- Mode Registry/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Mode Registry/README.md diff --git a/Mode Registry/README.md b/Mode Registry/README.md new file mode 100644 index 0000000..de1b772 --- /dev/null +++ b/Mode Registry/README.md @@ -0,0 +1,41 @@ +# Mode Registry + +In this folder are all the modes created by contributors which work out of the box with the sketch. If you would like to add these modes simply follow the directions below. + +## Installing Modes + +#### Copy Mode .ino file to the main sketch folder + +Simply move the .ino file of your choice from the __External Modes__ folder into the sketch main folder. This will be the "__Super_Simple_RGB_WiFi_Lamp__" folder with the main .ino file. + +![MoveFiles](../Pictures/MoveFiles.png) + +#### Install any new libraries mentioned + +Some modes may require a new library to be installed. This should be mentioned at the top of any new mode file. You will need to install these before the mode will work. For example; the visualiser mode requires the FFT library to be installed before it will work. + +![MoveFiles](../Pictures/InstallLibraries.png) + +#### Add mode to the mode registry in the sketch + +In the mode_registry.ino file you must add your mode so that the sketch knows it should use it. Failure to do so will result in your mode not being rendered. To add the mode in the registry simply copy and paste the following replacing NEW_MODE_NAME with the name of the mode, and NEW_MODE_CONSTRUCTOR with the name of the mode as well (this must match details in the mode's .ino file) + +`modes["NEW_MODE_NAME"] = new NEW_MODE_CONSTRUCTOR();` + +#### Compile and upload + +After adding the file to the main sketch folder, installing any new libraries that are required, and adding the mode to the registry, simply compile and upload the sketch to your ESP8266. + +#### Issues with new modes + +If you run into any issues with new modes, please create an issue and provide as much information as possible so we can help identify the issue. + +## Creating New Modes + +While there is no guide currently on how to add a mode yourself, you may be able to create one by reading how one of the other modes is implemented. I suggest having a read of how the colour mode is implemented first. + +## TODO + +- Show how to add the mode in the arduino environment +- Show how to add the mode to the webpage +- Make a new mode pull request template \ No newline at end of file From 986f37618b5f6f6ecd7cfa7ad99d08740c62adfd Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:13:29 +1100 Subject: [PATCH 03/10] removed modes from mode_registry.ino --- Super_Simple_RGB_WiFi_Lamp/mode_registry.ino | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino b/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino index 09d2393..29bb5a0 100644 --- a/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino +++ b/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino @@ -10,10 +10,5 @@ void ledModeInit() { modes["Clock"] = new ModeClock(); modes["Bell Curve"] = new ModeBellCurve(); modes["Night Rider"] = new ModeNightRider(); - modes["Circle"] = new ModeCircle(); - modes["Sparkle"] = new ModeSparkle(); - modes["Color Wipe"] = new ModeColorWipe(); - modes["Confetti"] = new ModeConfetti(); - modes["Visualiser"] = new ModeVisualiser(); } From d1e6c576c79c062b4520d9c7bdce840211e0b261 Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:12:53 +1100 Subject: [PATCH 04/10] Moved modes to Mode Registry folder --- {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeCircle.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeColorWipe.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeConfetti.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeSparkle.ino | 0 {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeVisualiser.ino | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeCircle.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeColorWipe.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeConfetti.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeSparkle.ino (100%) rename {Super_Simple_RGB_WiFi_Lamp => Mode Registry}/ModeVisualiser.ino (100%) diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeCircle.ino b/Mode Registry/ModeCircle.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeCircle.ino rename to Mode Registry/ModeCircle.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeColorWipe.ino b/Mode Registry/ModeColorWipe.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeColorWipe.ino rename to Mode Registry/ModeColorWipe.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeConfetti.ino b/Mode Registry/ModeConfetti.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeConfetti.ino rename to Mode Registry/ModeConfetti.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeSparkle.ino b/Mode Registry/ModeSparkle.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeSparkle.ino rename to Mode Registry/ModeSparkle.ino diff --git a/Super_Simple_RGB_WiFi_Lamp/ModeVisualiser.ino b/Mode Registry/ModeVisualiser.ino similarity index 100% rename from Super_Simple_RGB_WiFi_Lamp/ModeVisualiser.ino rename to Mode Registry/ModeVisualiser.ino From 9224d4ed9c5363926ab1730cdc09f79fcaa3a991 Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:13:08 +1100 Subject: [PATCH 05/10] Made mode registry readme --- Mode Registry/README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Mode Registry/README.md diff --git a/Mode Registry/README.md b/Mode Registry/README.md new file mode 100644 index 0000000..de1b772 --- /dev/null +++ b/Mode Registry/README.md @@ -0,0 +1,41 @@ +# Mode Registry + +In this folder are all the modes created by contributors which work out of the box with the sketch. If you would like to add these modes simply follow the directions below. + +## Installing Modes + +#### Copy Mode .ino file to the main sketch folder + +Simply move the .ino file of your choice from the __External Modes__ folder into the sketch main folder. This will be the "__Super_Simple_RGB_WiFi_Lamp__" folder with the main .ino file. + +![MoveFiles](../Pictures/MoveFiles.png) + +#### Install any new libraries mentioned + +Some modes may require a new library to be installed. This should be mentioned at the top of any new mode file. You will need to install these before the mode will work. For example; the visualiser mode requires the FFT library to be installed before it will work. + +![MoveFiles](../Pictures/InstallLibraries.png) + +#### Add mode to the mode registry in the sketch + +In the mode_registry.ino file you must add your mode so that the sketch knows it should use it. Failure to do so will result in your mode not being rendered. To add the mode in the registry simply copy and paste the following replacing NEW_MODE_NAME with the name of the mode, and NEW_MODE_CONSTRUCTOR with the name of the mode as well (this must match details in the mode's .ino file) + +`modes["NEW_MODE_NAME"] = new NEW_MODE_CONSTRUCTOR();` + +#### Compile and upload + +After adding the file to the main sketch folder, installing any new libraries that are required, and adding the mode to the registry, simply compile and upload the sketch to your ESP8266. + +#### Issues with new modes + +If you run into any issues with new modes, please create an issue and provide as much information as possible so we can help identify the issue. + +## Creating New Modes + +While there is no guide currently on how to add a mode yourself, you may be able to create one by reading how one of the other modes is implemented. I suggest having a read of how the colour mode is implemented first. + +## TODO + +- Show how to add the mode in the arduino environment +- Show how to add the mode to the webpage +- Make a new mode pull request template \ No newline at end of file From 9e2c5bdca86b0c5abca192042b1b85c2c080e7f4 Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Mon, 2 Dec 2019 21:13:29 +1100 Subject: [PATCH 06/10] removed modes from mode_registry.ino --- Super_Simple_RGB_WiFi_Lamp/mode_registry.ino | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino b/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino index 09d2393..29bb5a0 100644 --- a/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino +++ b/Super_Simple_RGB_WiFi_Lamp/mode_registry.ino @@ -10,10 +10,5 @@ void ledModeInit() { modes["Clock"] = new ModeClock(); modes["Bell Curve"] = new ModeBellCurve(); modes["Night Rider"] = new ModeNightRider(); - modes["Circle"] = new ModeCircle(); - modes["Sparkle"] = new ModeSparkle(); - modes["Color Wipe"] = new ModeColorWipe(); - modes["Confetti"] = new ModeConfetti(); - modes["Visualiser"] = new ModeVisualiser(); } From 4c15f66155f5090f55881b7f0cb4aa34168d9e92 Mon Sep 17 00:00:00 2001 From: thebigpotatoe <17895072+thebigpotatoe@users.noreply.github.com> Date: Sat, 7 Dec 2019 20:52:20 +1100 Subject: [PATCH 07/10] Made modes update dynamically on the webpage --- Mode Registry/ModeCircle.ino | 106 +- Mode Registry/ModeColorWipe.ino | 171 +- Mode Registry/ModeConfetti.ino | 164 +- Mode Registry/ModeSparkle.ino | 163 +- Mode Registry/ModeVisualiser.ino | 414 +++- Super_Simple_RGB_WiFi_Lamp/ModeBellCurve.ino | 145 +- Super_Simple_RGB_WiFi_Lamp/ModeClock.ino | 263 ++- Super_Simple_RGB_WiFi_Lamp/ModeColour.ino | 152 +- Super_Simple_RGB_WiFi_Lamp/ModeNightRider.ino | 61 +- Super_Simple_RGB_WiFi_Lamp/ModeRainbow.ino | 210 +- .../Super_Simple_RGB_WiFi_Lamp.ino | 1 + Super_Simple_RGB_WiFi_Lamp/Web_Page.ino | 1505 ++----------- Super_Simple_RGB_WiFi_Lamp/Websockets.ino | 5 + Super_Simple_RGB_WiFi_Lamp/mode_registry.ino | 3 +- Website/Class_HTML_Input.html | 0 Website/Class_Script_Input.js | 0 Website/Create_Class_HTML_String.py | 26 + Website/Create_Class_JS_String.py | 26 + ...te_website.py => Create_Sketch_Website.py} | 6 +- Website/Exported_Class_HTML.ino | 0 Website/Exported_Class_Script.ino | 0 .../{Website.html => _Complete_Website.html} | 1878 +++++++++-------- Website/_Developement_Website copy.html | 387 ++++ Website/_Static_Website.html | 388 ++++ 24 files changed, 3493 insertions(+), 2581 deletions(-) create mode 100644 Website/Class_HTML_Input.html create mode 100644 Website/Class_Script_Input.js create mode 100644 Website/Create_Class_HTML_String.py create mode 100644 Website/Create_Class_JS_String.py rename Website/{update_website.py => Create_Sketch_Website.py} (74%) mode change 100755 => 100644 create mode 100644 Website/Exported_Class_HTML.ino create mode 100644 Website/Exported_Class_Script.ino rename Website/{Website.html => _Complete_Website.html} (57%) create mode 100644 Website/_Developement_Website copy.html create mode 100644 Website/_Static_Website.html diff --git a/Mode Registry/ModeCircle.ino b/Mode Registry/ModeCircle.ino index 20c63f3..43abcf1 100644 --- a/Mode Registry/ModeCircle.ino +++ b/Mode Registry/ModeCircle.ino @@ -1,49 +1,73 @@ class ModeCircle : public ModeBase { private: - int circleActiveLedNumber = 0; + int circleActiveLedNumber = 0; + public: - ModeCircle() {} - virtual void render() { - // First bring our logical arrays into a list of led numbers to iterate over - int i; - int ledIter = 0; - int leds[NUM_LEDS]; - for (i = 0; i < bottomNumLeds; i++) { - leds[ledIter++] = bottomLeds[i]; - } - for (i = leftNumLeds-1; i >= 0 ; i--) { - leds[ledIter++] = leftLeds[i]; - } - for (i = topNumLeds-1; i >= 0 ; i--) { - leds[ledIter++] = topLeds[i]; - } - for (i = rightNumLeds-1; i >= 0 ; i--) { - leds[ledIter++] = rightLeds[i]; - } - - // Update the active LED index - EVERY_N_MILLISECONDS(40) { - circleActiveLedNumber += 1; - if (circleActiveLedNumber == NUM_LEDS) - circleActiveLedNumber = 0; - - Serial.print("Active number: "); - Serial.println(circleActiveLedNumber); - - // Darken all LEDs to slightly dim the previous active LEDs - fadeToBlackBy(ledString, NUM_LEDS, 80); - }; - - // And now highlight the active index - for (i = 0; i < NUM_LEDS; i++) { - if (i == circleActiveLedNumber) { - ledString[leds[i]] = CRGB::Red; - } - } + ModeCircle() {} + virtual void render() + { + // First bring our logical arrays into a list of led numbers to iterate over + int i; + int ledIter = 0; + int leds[NUM_LEDS]; + for (i = 0; i < bottomNumLeds; i++) + { + leds[ledIter++] = bottomLeds[i]; + } + for (i = leftNumLeds - 1; i >= 0; i--) + { + leds[ledIter++] = leftLeds[i]; + } + for (i = topNumLeds - 1; i >= 0; i--) + { + leds[ledIter++] = topLeds[i]; } + for (i = rightNumLeds - 1; i >= 0; i--) + { + leds[ledIter++] = rightLeds[i]; + } + + // Update the active LED index + EVERY_N_MILLISECONDS(40) + { + circleActiveLedNumber += 1; + if (circleActiveLedNumber == NUM_LEDS) + circleActiveLedNumber = 0; - virtual void applyConfig(JsonVariant& settings) { + // Serial.print("Active number: "); + // Serial.println(circleActiveLedNumber); + // Darken all LEDs to slightly dim the previous active LEDs + fadeToBlackBy(ledString, NUM_LEDS, 80); + }; + + // And now highlight the active index + for (i = 0; i < NUM_LEDS; i++) + { + if (i == circleActiveLedNumber) + { + ledString[leds[i]] = CRGB::Red; + } } -}; + } + + virtual void applyConfig(JsonVariant &settings) {} + + virtual void sendWebsiteData(WebSocketsServer &_webSocketServer) + { + const char *modeName = "Circle"; + const char *tabHtml = PSTR("

Circle Mode<\\/h2>" + "

A simple dot moving round the lamp.<\\/p>"); + const char *tabScript = PSTR("messageEventList.push(handleCircleMessage);\\r\\n" + "function handleCircleMessage(jsonMessage) {\\r\\n" + " if (\\\"Circle\\\" in jsonMessage) {\\r\\n" + " jsonMessage = jsonMessage.Circle\\r\\n" + " if (typeof jsonMessage === \\\"object\\\") {}\\r\\n" + " }\\r\\n" + " }\\r\\n"); + String htmlJSON = String("{\"Tab\" : {") + "\"Name\": \"" + modeName + "\", \"tabHtml\" : \"" + tabHtml + "\", \"tabScript\" : \"" + tabScript + "\"}}"; + + _webSocketServer.broadcastTXT(htmlJSON.c_str()); + } +}; \ No newline at end of file diff --git a/Mode Registry/ModeColorWipe.ino b/Mode Registry/ModeColorWipe.ino index 8a71391..18bff14 100644 --- a/Mode Registry/ModeColorWipe.ino +++ b/Mode Registry/ModeColorWipe.ino @@ -1,39 +1,150 @@ class ModeColorWipe : public ModeBase { private: - int colorWipePosition = -1; - bool TurningOn = true; - int colorWipeRed = 255; - int colorWipeGreen = 0; - int colorWipeBlue = 255; - int colorWipeSpeed = 20; + int colorWipePosition = -1; + bool TurningOn = true; + int colorWipeRed = 255; + int colorWipeGreen = 0; + int colorWipeBlue = 255; + int colorWipeSpeed = 20; public: - ModeColorWipe() {} - virtual void render() { - EVERY_N_MILLISECONDS(colorWipeSpeed) { - colorWipePosition++; - if (TurningOn) { - fill_solid(ledString, colorWipePosition, CRGB(colorWipeRed, colorWipeGreen, colorWipeBlue)); - if (colorWipePosition == NUM_LEDS) { - TurningOn = false; - colorWipePosition = -1; - } - } - else { - fill_solid(ledString, colorWipePosition, CRGB( 0, 0, 0)); - if (colorWipePosition == NUM_LEDS) { - TurningOn = true; - colorWipePosition = -1; - } - } + ModeColorWipe() {} + virtual void render() + { + EVERY_N_MILLISECONDS(colorWipeSpeed) + { + colorWipePosition++; + if (TurningOn) + { + fill_solid(ledString, colorWipePosition, CRGB(colorWipeRed, colorWipeGreen, colorWipeBlue)); + if (colorWipePosition == NUM_LEDS) + { + TurningOn = false; + colorWipePosition = -1; } + } + else + { + fill_solid(ledString, colorWipePosition, CRGB(0, 0, 0)); + if (colorWipePosition == NUM_LEDS) + { + TurningOn = true; + colorWipePosition = -1; + } + } } + } - virtual void applyConfig(JsonVariant& settings) { - settings["Red"] = colorWipeRed = settings["Red"] | colorWipeRed; - settings["Green"]= colorWipeGreen = settings["Green"] | colorWipeGreen; - settings["Blue"] = colorWipeBlue = settings["Blue"] | colorWipeBlue; - settings["Speed"] = colorWipeSpeed = settings["Speed"] | colorWipeSpeed; - } + virtual void applyConfig(JsonVariant &settings) + { + settings["Red"] = colorWipeRed = settings["Red"] | colorWipeRed; + settings["Green"] = colorWipeGreen = settings["Green"] | colorWipeGreen; + settings["Blue"] = colorWipeBlue = settings["Blue"] | colorWipeBlue; + settings["Speed"] = colorWipeSpeed = settings["Speed"] | colorWipeSpeed; + } + + virtual void sendWebsiteData(WebSocketsServer &_webSocketServer) + { + const char *modeName = "Colour Wipe"; + const char *tabHtml = PSTR("

Color Wipe Mode<\\/h2>\\r\\n" + "

Color Wipe will fill the light with a color in a wiping fashion then wipe the light away.<\\/p>\\r\\n" + "

\\r\\n" + " <\\/input>\\r\\n" + "<\\/div>\\r\\n"); + const char *tabScript = PSTR("var colorWipeLastMessage = \\\"\\\"\\r\\n" + "var colorWipeRed = 0\\r\\n" + "var colorWipeGreen = 0\\r\\n" + "var colorWipeBlue = 0\\r\\n" + "var colorWipeDebunce = Date.now()\\r\\n" + "\\r\\n" + "messageEventList.push(handleColorWipeMessage)\\r\\n" + "\\r\\n" + "var colorWipeSelectButton = $('#colorWipeSelectButton').colorPicker({\\r\\n" + " customBG: '#222',\\r\\n" + " margin: '4px -2px 0',\\r\\n" + " doRender: 'div div',\\r\\n" + " preventFocus: true,\\r\\n" + " animationSpeed: 150,\\r\\n" + " forceAlpha: false,\\r\\n" + "\\r\\n" + " // demo on how to make plugins... mobile support plugin\\r\\n" + " buildCallback: function ($elm) {\\r\\n" + " this.$colorPatch = $elm.prepend('
').find('.cp-disp');\\r\\n" + " },\\r\\n" + " cssAddon: '.cp-disp {padding:10px; margin-bottom:6px; font-size:19px; height:20px; line-height:20px}' +\\r\\n" + " '.cp-xy-slider {width:200px; height:200px;}' +\\r\\n" + " '.cp-xy-cursor {width:16px; height:16px; border-width:2px; margin:-8px}' +\\r\\n" + " '.cp-z-slider {height:200px; width:40px;}' +\\r\\n" + " '.cp-z-cursor {border-width:8px; margin-top:-8px;}' +\\r\\n" + " '.cp-alpha {height:40px;}' +\\r\\n" + " '.cp-alpha-cursor {border-width:8px; margin-left:-8px;}',\\r\\n" + "\\r\\n" + " renderCallback: function ($elm, toggled) {\\r\\n" + " var colors = this.color.colors;\\r\\n" + " onColorWipeButtonEvent(Math.round(colors.rgb.r * 255), Math.round(colors.rgb.g * 255), Math.round(colors.rgb.b * 255))\\r\\n" + "\\r\\n" + " setPickerColor(colorWipeSelectButton, Math.round(colors.rgb.r * 255), Math.round(colors.rgb.g * 255), Math.round(colors.rgb.b * 255))\\r\\n" + " }\\r\\n" + "})\\r\\n" + "\\r\\n" + "function handleColorWipeMessage(jsonMessage) {\\r\\n" + " if (\\\"Color Wipe\\\" in jsonMessage) {\\r\\n" + " jsonMessage = jsonMessage[\\\"Color Wipe\\\"]\\r\\n" + " if (typeof jsonMessage === \\\"object\\\") {\\r\\n" + " var newRed = currentRed\\r\\n" + " var newGreen = currentGreen\\r\\n" + " var newBlue = currentBlue\\r\\n" + "\\r\\n" + " if ((\\\"Red\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Red === \\\"number\\\") {\\r\\n" + " newRed = jsonMessage.Red\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if ((\\\"Green\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Green === \\\"number\\\") {\\r\\n" + " newGreen = jsonMessage.Green\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if ((\\\"Blue\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Blue === \\\"number\\\") {\\r\\n" + " newBlue = jsonMessage.Blue\\r\\n" + " }\\r\\n" + " }\\r\\n" + " setPickerColor(colorWipeSelectButton, newRed, newGreen, newBlue);\\r\\n" + " }\\r\\n" + " }\\r\\n" + "}\\r\\n" + "\\r\\n" + "function onColorWipeButtonEvent(red, green, blue) {\\r\\n" + " if (currentRed != red || currentGreen != green || currentBlue != blue) {\\r\\n" + " currentRed = red\\r\\n" + " currentGreen = green\\r\\n" + " currentBlue = blue\\r\\n" + "\\r\\n" + " msg = {\\r\\n" + " \\\"State\\\": true,\\r\\n" + " \\\"Mode\\\": \\\"Color Wipe\\\",\\r\\n" + " \\\"Color Wipe\\\": {\\r\\n" + " \\\"Red\\\": red,\\r\\n" + " \\\"Green\\\": green,\\r\\n" + " \\\"Blue\\\": blue\\r\\n" + " }\\r\\n" + " }\\r\\n" + "\\r\\n" + " if (Date.now() - colorWipeDebunce > 50) {\\r\\n" + " colorWipeDebunce = Date.now()\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + " if (msg != colorWipeLastMessage && Date.now() - colorWipeDebunce > 50) {\\r\\n" + " colorWipeDebunce = Date.now()\\r\\n" + " colorWipeLastMessage = msg\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + " }\\r\\n" + "}\\r\\n"); + String htmlJSON = String("{\"Tab\" : {") + "\"Name\": \"" + modeName + "\", \"tabHtml\" : \"" + tabHtml + "\", \"tabScript\" : \"" + tabScript + "\"}}"; + + _webSocketServer.broadcastTXT(htmlJSON.c_str()); + } }; diff --git a/Mode Registry/ModeConfetti.ino b/Mode Registry/ModeConfetti.ino index 194a3ad..a1e0202 100644 --- a/Mode Registry/ModeConfetti.ino +++ b/Mode Registry/ModeConfetti.ino @@ -1,28 +1,152 @@ class ModeConfetti : public ModeBase { private: - bool confettiActive = true; - int confettiSpeed = 100; - int confettiPixel = random(NUM_LEDS); + bool confettiActive = true; + int confettiSpeed = 100; + int confettiPixel = random(NUM_LEDS); public: - ModeConfetti() {} - virtual void render() { - EVERY_N_MILLISECONDS(confettiSpeed) { - if (confettiActive) { - confettiPixel = random(NUM_LEDS); - fadeToBlackBy(ledString, NUM_LEDS, 10); - uint8_t pos = random8(NUM_LEDS); - ledString[pos] += CHSV(random8(), random8(), random8()); - } - } + ModeConfetti() {} + virtual void render() + { + EVERY_N_MILLISECONDS(confettiSpeed) + { + if (confettiActive) + { + confettiPixel = random(NUM_LEDS); + fadeToBlackBy(ledString, NUM_LEDS, 10); + uint8_t pos = random8(NUM_LEDS); + ledString[pos] += CHSV(random8(), random8(), random8()); + } } + } - virtual void applyConfig(JsonVariant& settings) { - // Are not used - //settings["Red"] = confettiRed = settings["Red"] | confettiRed; - //settings["Green"]= confettiGreen = settings["Green"] | confettiGreen; - //settings["Blue"] = confettiBlue = settings["Blue"] | confettiBlue; - settings["Speed"] = confettiSpeed = settings["Speed"] | confettiSpeed; - } + virtual void applyConfig(JsonVariant &settings) + { + // Are not used + //settings["Red"] = confettiRed = settings["Red"] | confettiRed; + //settings["Green"]= confettiGreen = settings["Green"] | confettiGreen; + //settings["Blue"] = confettiBlue = settings["Blue"] | confettiBlue; + settings["Speed"] = confettiSpeed = settings["Speed"] | confettiSpeed; + } + + virtual void sendWebsiteData(WebSocketsServer &_webSocketServer) + { + const char *modeName = "Confetti"; + const char *tabHtml = PSTR("

Confetti Mode<\\/h2>\\r\\n" + "

Confetti will flash random colors to emulate confetti.<\\/p>\\r\\n"); + const char *tabScript = PSTR("var confettiLastMessage = \\\"\\\"\\r\\n" + " var confettiRed = 0;\\r\\n" + " var confettiGreen = 0;\\r\\n" + " var confettiBlue = 0;\\r\\n" + " var confettiDebunce = Date.now()\\r\\n" + "\\r\\n" + " messageEventList.push(handleConfettiMessage)\\r\\n" + "\\r\\n" + " var confettiSelectButton = $('#confettiSelectButton').colorPicker({\\r\\n" + " customBG: '#222',\\r\\n" + " margin: '4px -2px 0',\\r\\n" + " doRender: 'div div',\\r\\n" + " preventFocus: true,\\r\\n" + " animationSpeed: 150,\\r\\n" + " forceAlpha: false,\\r\\n" + "\\r\\n" + " // demo on how to make plugins... mobile support plugin\\r\\n" + " buildCallback: function ($elm) {\\r\\n" + " this.$colorPatch = $elm.prepend('

').find('.cp-disp');\\r\\n" + " },\\r\\n" + " cssAddon:\\r\\n" + " '.cp-xy-slider {width:200px; height:200px;}' +\\r\\n" + " '.cp-xy-cursor {width:16px; height:16px; border-width:2px; margin:-8px}' +\\r\\n" + " '.cp-z-slider {height:200px; width:40px;}' +\\r\\n" + " '.cp-z-cursor {border-width:8px; margin-top:-8px;}' +\\r\\n" + " '.cp-alpha {height:40px;}' +\\r\\n" + " '.cp-alpha-cursor {border-width:8px; margin-left:-8px;}',\\r\\n" + "\\r\\n" + " renderCallback: function ($elm, toggled) {\\r\\n" + " var colors = this.color.colors;\\r\\n" + " onConfettiButtonEvent(Math.round(colors.rgb.r * 255), Math.round(colors.rgb.g * 255), Math.round(colors.rgb.b * 255))\\r\\n" + " setPickerColor(confettiSelectButton, Math.round(colors.rgb.r * 255), Math.round(colors.rgb.g * 255), Math.round(colors.rgb.b * 255))\\r\\n" + " }\\r\\n" + " })\\r\\n" + "\\r\\n" + " function onConfettiEvent() {\\r\\n" + " let currentSpeedValue = parseFloat($(\\\"#confettiSpeed\\\").val())\\r\\n" + "\\r\\n" + " $(\\\"#confettiSpeedLabel\\\").html(currentSpeedValue)\\r\\n" + "\\r\\n" + " msg = {\\r\\n" + " \\\"State\\\": true,\\r\\n" + " \\\"Mode\\\": \\\"Confetti\\\",\\r\\n" + " \\\"Confetti\\\": {\\r\\n" + " \\\"Speed\\\": currentSpeedValue,\\r\\n" + " }\\r\\n" + " }\\r\\n" + "\\r\\n" + " if (msg != confettiLastMessage && Date.now() - confettiDebunce > 50) {\\r\\n" + " confettiDebunce = Date.now()\\r\\n" + " confettiLastMessage = msg\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + " }\\r\\n" + "\\r\\n" + " function handleConfettiMessage(jsonMessage) {\\r\\n" + " if (\\\"Confetti\\\" in jsonMessage) {\\r\\n" + " jsonMessage = jsonMessage.Confetti\\r\\n" + " if (typeof jsonMessage === \\\"object\\\") {\\r\\n" + " var newRed = currentRed\\r\\n" + " var newGreen = currentGreen\\r\\n" + " var newBlue = currentBlue\\r\\n" + "\\r\\n" + " if ((\\\"Red\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Red === \\\"number\\\") {\\r\\n" + " newRed = jsonMessage.Red\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if ((\\\"Green\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Green === \\\"number\\\") {\\r\\n" + " newGreen = jsonMessage.Green\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if ((\\\"Blue\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Blue === \\\"number\\\") {\\r\\n" + " newBlue = jsonMessage.Blue\\r\\n" + " }\\r\\n" + " }\\r\\n" + " setPickerColor(confettiSelectButton, newRed, newGreen, newBlue);\\r\\n" + " }\\r\\n" + " }\\r\\n" + " }\\r\\n" + "\\r\\n" + " function onConfettiButtonEvent(red, green, blue) {\\r\\n" + " if (currentRed != red || currentGreen != green || currentBlue != blue) {\\r\\n" + " currentRed = red\\r\\n" + " currentGreen = green\\r\\n" + " currentBlue = blue\\r\\n" + "\\r\\n" + " msg = {\\r\\n" + " \\\"State\\\": true,\\r\\n" + " \\\"Mode\\\": \\\"Confetti\\\",\\r\\n" + " \\\"Confetti\\\": {\\r\\n" + " \\\"Red\\\": red,\\r\\n" + " \\\"Green\\\": green,\\r\\n" + " \\\"Blue\\\": blue\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if (Date.now() - confettiDebunce > 50) {\\r\\n" + " confettiDebunce = Date.now()\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if (msg != confettiLastMessage && Date.now() - confettiDebunce > 50) {\\r\\n" + " confettiDebunce = Date.now()\\r\\n" + " confettiLastMessage = msg\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + " }\\r\\n"); + + String htmlJSON = String("{\"Tab\" : {") + "\"Name\": \"" + modeName + "\", \"tabHtml\" : \"" + tabHtml + "\", \"tabScript\" : \"" + tabScript + "\"}}"; + + _webSocketServer.broadcastTXT(htmlJSON.c_str()); + } }; diff --git a/Mode Registry/ModeSparkle.ino b/Mode Registry/ModeSparkle.ino index 7a69b42..98ef402 100644 --- a/Mode Registry/ModeSparkle.ino +++ b/Mode Registry/ModeSparkle.ino @@ -2,31 +2,166 @@ class ModeSparkle : public ModeBase { private: - int sparkleSpeed = 30; + int sparkleSpeed = 30; bool sparkleActive = true; - int sparkleRed = 128; - int sparkleGreen = 128; - int sparkleBlue = 128; - int sparklePixel = random(NUM_LEDS); + int sparkleRed = 128; + int sparkleGreen = 128; + int sparkleBlue = 128; + int sparklePixel = random(NUM_LEDS); + public: ModeSparkle() {} - virtual void render() { - EVERY_N_MILLISECONDS(sparkleSpeed) { - if (sparkleActive) { - sparklePixel = random(NUM_LEDS); - ledString[sparklePixel] = CRGB(sparkleRed, sparkleGreen, sparkleBlue); + virtual void render() + { + EVERY_N_MILLISECONDS(sparkleSpeed) + { + if (sparkleActive) + { + sparklePixel = random(NUM_LEDS); + ledString[sparklePixel] = CRGB(sparkleRed, sparkleGreen, sparkleBlue); } - else { - ledString[sparklePixel] = CRGB(0, 0, 0); + else + { + ledString[sparklePixel] = CRGB(0, 0, 0); } sparkleActive = !sparkleActive; } } - virtual void applyConfig(JsonVariant& settings) { + virtual void applyConfig(JsonVariant &settings) + { settings["Red"] = sparkleRed = settings["Red"] | sparkleRed; - settings["Green"]= sparkleGreen = settings["Green"] | sparkleGreen; + settings["Green"] = sparkleGreen = settings["Green"] | sparkleGreen; settings["Blue"] = sparkleBlue = settings["Blue"] | sparkleBlue; settings["Speed"] = sparkleSpeed = settings["Speed"] | sparkleSpeed; } + + virtual void sendWebsiteData(WebSocketsServer &_webSocketServer) + { + const char *modeName = "Sparkle"; + const char *tabHtml = PSTR("

Sparkle Mode<\\/h2>\\r\\n" + "

This is the Sparkle mode.<\\/p>\\r\\n" + "

\\r\\n" + " <\\/input>\\r\\n" + "<\\/div>\\r\\n"); + const char *tabScript = PSTR("var sparkleLastMessage = \\\"\\\"\\r\\n" + "var sparkleRed = 0;\\r\\n" + "var sparkleGreen = 0;\\r\\n" + "var sparkleBlue = 0;\\r\\n" + "var sparkleDebunce = Date.now()\\r\\n" + "\\r\\n" + "messageEventList.push(handleSparkleMessage)\\r\\n" + "\\r\\n" + "var sparkleSelectButton = $('#sparkleSelectButton').colorPicker({\\r\\n" + " customBG: '#222',\\r\\n" + " margin: '4px -2px 0',\\r\\n" + " doRender: 'div div',\\r\\n" + " preventFocus: true,\\r\\n" + " animationSpeed: 150,\\r\\n" + " forceAlpha: false,\\r\\n" + "\\r\\n" + " // demo on how to make plugins... mobile support plugin\\r\\n" + " buildCallback: function ($elm) {\\r\\n" + " this.$colorPatch = $elm.prepend('
').find('.cp-disp');\\r\\n" + " },\\r\\n" + " cssAddon: '.cp-xy-slider {width:200px; height:200px;}' +\\r\\n" + " '.cp-xy-cursor {width:16px; height:16px; border-width:2px; margin:-8px}' +\\r\\n" + " '.cp-z-slider {height:200px; width:40px;}' +\\r\\n" + " '.cp-z-cursor {border-width:8px; margin-top:-8px;}' +\\r\\n" + " '.cp-alpha {height:40px;}' +\\r\\n" + " '.cp-alpha-cursor {border-width:8px; margin-left:-8px;}',\\r\\n" + "\\r\\n" + " renderCallback: function ($elm, toggled) {\\r\\n" + " var colors = this.color.colors;\\r\\n" + " onSparkleButtonEvent(Math.round(colors.rgb.r * 255), Math.round(colors.rgb.g * 255), Math.round(colors.rgb.b * 255))\\r\\n" + " setPickerColor(sparkleSelectButton, Math.round(colors.rgb.r * 255), Math.round(colors.rgb.g * 255), Math.round(colors.rgb.b * 255))\\r\\n" + " }\\r\\n" + "})\\r\\n" + "$(\\\"#sparkleSpeed\\\").on(\\\"input\\\", function () {\\r\\n" + " onSparkleEvent()\\r\\n" + "});\\r\\n" + "$(\\\"#sparkleSpeed\\\").on(\\\"change\\\", function () {\\r\\n" + " onSparkleEvent()\\r\\n" + "});\\r\\n" + "\\r\\n" + "\\r\\n" + "function handleSparkleMessage(jsonMessage) {\\r\\n" + " if (\\\"Sparkle\\\" in jsonMessage) {\\r\\n" + " jsonMessage = jsonMessage.Sparkle\\r\\n" + " if (typeof jsonMessage === \\\"object\\\") {\\r\\n" + " var newRed = currentRed\\r\\n" + " var newGreen = currentGreen\\r\\n" + " var newBlue = currentBlue\\r\\n" + "\\r\\n" + " if ((\\\"Red\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Red === \\\"number\\\") {\\r\\n" + " newRed = jsonMessage.Red\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if ((\\\"Green\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Green === \\\"number\\\") {\\r\\n" + " newGreen = jsonMessage.Green\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if ((\\\"Blue\\\" in jsonMessage)) {\\r\\n" + " if (typeof jsonMessage.Blue === \\\"number\\\") {\\r\\n" + " newBlue = jsonMessage.Blue\\r\\n" + " }\\r\\n" + " }\\r\\n" + " setPickerColor(sparkleSelectButton, newRed, newGreen, newBlue);\\r\\n" + " }\\r\\n" + " }\\r\\n" + "}\\r\\n" + "\\r\\n" + "function onSparkleEvent() {\\r\\n" + " let currentSpeedValue = parseFloat($(\\\"#sparkleSpeed\\\").val())\\r\\n" + "\\r\\n" + " $(\\\"#sparkleSpeedLabel\\\").html(currentSpeedValue)\\r\\n" + "\\r\\n" + " msg = {\\r\\n" + " \\\"State\\\": true,\\r\\n" + " \\\"Mode\\\": \\\"Sparkle\\\",\\r\\n" + " \\\"Sparkle\\\": {\\r\\n" + " \\\"Speed\\\": currentSpeedValue,\\r\\n" + " }\\r\\n" + " }\\r\\n" + "\\r\\n" + " if (msg != sparkleLastMessage && Date.now() - sparkleDebunce > 50) {\\r\\n" + " sparkleDebunce = Date.now()\\r\\n" + " sparkleLastMessage = msg\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + "}\\r\\n" + "\\r\\n" + "function onSparkleButtonEvent(red, green, blue) {\\r\\n" + " if (currentRed != red || currentGreen != green || currentBlue != blue) {\\r\\n" + " currentRed = red\\r\\n" + " currentGreen = green\\r\\n" + " currentBlue = blue\\r\\n" + "\\r\\n" + " msg = {\\r\\n" + " \\\"State\\\": true,\\r\\n" + " \\\"Mode\\\": \\\"Sparkle\\\",\\r\\n" + " \\\"Sparkle\\\": {\\r\\n" + " \\\"Red\\\": red,\\r\\n" + " \\\"Green\\\": green,\\r\\n" + " \\\"Blue\\\": blue\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if (Date.now() - sparkleDebunce > 50) {\\r\\n" + " sparkleDebunce = Date.now()\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + " }\\r\\n" + " if (msg != sparkleLastMessage && Date.now() - sparkleDebunce > 50) {\\r\\n" + " sparkleDebunce = Date.now()\\r\\n" + " sparkleLastMessage = msg\\r\\n" + " sendMessage(msg)\\r\\n" + " }\\r\\n" + "}\\r\\n"); + + String htmlJSON = String("{\"Tab\" : {") + "\"Name\": \"" + modeName + "\", \"tabHtml\" : \"" + tabHtml + "\", \"tabScript\" : \"" + tabScript + "\"}}"; + + _webSocketServer.broadcastTXT(htmlJSON.c_str()); + } }; diff --git a/Mode Registry/ModeVisualiser.ino b/Mode Registry/ModeVisualiser.ino index 8e29610..401f4b0 100644 --- a/Mode Registry/ModeVisualiser.ino +++ b/Mode Registry/ModeVisualiser.ino @@ -3,126 +3,312 @@ class ModeVisualiser : public ModeBase { private: - ADC_MODE(ADC_TOUT); - arduinoFFT FFT = arduinoFFT(); - double visualiserRealSamples[VISUALISER_NUM_SAMPLES]; - double visualiserImaginarySamples[VISUALISER_NUM_SAMPLES]; - unsigned long visualiserLastSampleTime = 0; - uint16_t visualiserPeriod = 250; - uint16_t visualiserMinThreshold = 100; - uint16_t visualiserMaxThreshold = 750; - uint8_t visualiserNumBinsToSkip = 3; - uint8_t visualiserFadeUp = 32; - uint8_t visualiserFadeDown = 32; - uint8_t visualiserHueOffset = 170; + ADC_MODE(ADC_TOUT); + arduinoFFT FFT = arduinoFFT(); + double visualiserRealSamples[VISUALISER_NUM_SAMPLES]; + double visualiserImaginarySamples[VISUALISER_NUM_SAMPLES]; + unsigned long visualiserLastSampleTime = 0; + uint16_t visualiserPeriod = 250; + uint16_t visualiserMinThreshold = 100; + uint16_t visualiserMaxThreshold = 750; + uint8_t visualiserNumBinsToSkip = 3; + uint8_t visualiserFadeUp = 32; + uint8_t visualiserFadeDown = 32; + uint8_t visualiserHueOffset = 170; + public: - ModeVisualiser() {} - virtual void render() { - // Only use visualiser when not trying to access the NTP server - if (((WiFi.isConnected() && ntpTimeSet) || softApStarted) && !webSocketConnecting) { - // ************* ADC Reading ************* - // Turn off interupts - system_soft_wdt_stop(); - ets_intr_lock( ); //close interrupt - noInterrupts(); - - // Set up the buffer - int sampleNumber = 0; - uint16_t sampleBuffer[1]; - - // Read the first value - seems to be invalid on first read? - system_adc_read_fast(sampleBuffer, 1, 8); - - // Constrain the period - visualiserPeriod = constrain(visualiserPeriod, 0, 2000); - - // Sample the ADC until buffer is full - unsigned long adcBufferTime = micros(); - while (sampleNumber < VISUALISER_NUM_SAMPLES) { - // Get the ADC reading - adcBufferTime = micros(); - system_adc_read_fast(sampleBuffer, 1, 8); - - // If the correct period of time has passed store the reading - if (sampleNumber < VISUALISER_NUM_SAMPLES && adcBufferTime - visualiserLastSampleTime > visualiserPeriod) { - visualiserRealSamples[sampleNumber] = sampleBuffer[0]; - visualiserImaginarySamples[sampleNumber] = 0.0; - visualiserLastSampleTime = adcBufferTime; - sampleNumber++; + ModeVisualiser() {} + virtual void render() + { + // Only use visualiser when not trying to access the NTP server + if (((WiFi.isConnected() && ntpTimeSet) || softApStarted) && !webSocketConnecting) + { + // ************* ADC Reading ************* + // Turn off interupts + system_soft_wdt_stop(); + ets_intr_lock(); //close interrupt + noInterrupts(); + + // Set up the buffer + int sampleNumber = 0; + uint16_t sampleBuffer[1]; + + // Read the first value - seems to be invalid on first read? + system_adc_read_fast(sampleBuffer, 1, 8); + + // Constrain the period + visualiserPeriod = constrain(visualiserPeriod, 0, 2000); + + // Sample the ADC until buffer is full + unsigned long adcBufferTime = micros(); + while (sampleNumber < VISUALISER_NUM_SAMPLES) + { + // Get the ADC reading + adcBufferTime = micros(); + system_adc_read_fast(sampleBuffer, 1, 8); + + // If the correct period of time has passed store the reading + if (sampleNumber < VISUALISER_NUM_SAMPLES && adcBufferTime - visualiserLastSampleTime > visualiserPeriod) + { + visualiserRealSamples[sampleNumber] = sampleBuffer[0]; + visualiserImaginarySamples[sampleNumber] = 0.0; + visualiserLastSampleTime = adcBufferTime; + sampleNumber++; + } + } + + // Turn interupts back on + interrupts(); + ets_intr_unlock(); //open interrupt + system_soft_wdt_restart(); + + // Debug for ADC - Should be centered around 512 + // for (int i = 0; i < VISUALISER_NUM_SAMPLES; i++) { + // Serial.println(visualiserRealSamples[i]); + // } + + // ************* Calculate FFT ************* + FFT.Windowing(visualiserRealSamples, VISUALISER_NUM_SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); + FFT.Compute(visualiserRealSamples, visualiserImaginarySamples, VISUALISER_NUM_SAMPLES, FFT_FORWARD); + FFT.ComplexToMagnitude(visualiserRealSamples, visualiserImaginarySamples, VISUALISER_NUM_SAMPLES); + + // ************* Set the LED's ************* + // Set the colour of each light based on the values calculated + for (int ledNum = 0; ledNum < topNumLeds; ledNum++) + { + // Map to the bin number, skip all bins required. Start at the second bin to avoid DC + uint8_t binNumber = (ledNum < visualiserNumBinsToSkip) ? visualiserNumBinsToSkip : constrain(ledNum, 0, VISUALISER_NUM_SAMPLES / 2); + // Serial.print(binNumber); + // Serial.print("\t"); + + // Subract the minium value chosen for reduction of artifacts + double adjustedBinValue = (visualiserRealSamples[binNumber] > visualiserMinThreshold) ? visualiserRealSamples[binNumber] - visualiserMinThreshold : 0.0; + // Serial.print(adjustedBinValue); + // Serial.print("\t"); + + // Set if visualiserRealSamples[binNumber] is above 0 + if (adjustedBinValue > 0) + { + // Map the float values to 8 bit integers + uint8_t brightnessValue = map(adjustedBinValue, 0, visualiserMaxThreshold, 0, 255); + // Serial.println(brightnessValue); + + // Get the current hue of the rainbow for the specific LED + uint8_t ledHue = int(255.0 / (topNumLeds - 1) * ledNum + visualiserHueOffset) % 255; + CRGB newColour = CRGB(CHSV(ledHue, 255, 255)).nscale8(brightnessValue * (visualiserFadeUp / 255.00)); + + // Add the new colour to the current LED + ledString[topLeds[ledNum]] = ledString[bottomLeds[ledNum]] += newColour; + + // If the LED num is the first or last, use it to set the sides + if (ledNum == 0) + { + for (int sideLedNum = 0; sideLedNum < rightNumLeds; sideLedNum++) + { + ledString[rightLeds[sideLedNum]] += newColour; } } - - // Turn interupts back on - interrupts(); - ets_intr_unlock(); //open interrupt - system_soft_wdt_restart(); - - // Debug for ADC - Should be centered around 512 - // for (int i = 0; i < VISUALISER_NUM_SAMPLES; i++) { - // Serial.println(visualiserRealSamples[i]); - // } - - // ************* Calculate FFT ************* - FFT.Windowing(visualiserRealSamples, VISUALISER_NUM_SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); - FFT.Compute(visualiserRealSamples, visualiserImaginarySamples, VISUALISER_NUM_SAMPLES, FFT_FORWARD); - FFT.ComplexToMagnitude(visualiserRealSamples, visualiserImaginarySamples, VISUALISER_NUM_SAMPLES); - - // ************* Set the LED's ************* - // Set the colour of each light based on the values calculated - for (int ledNum = 0; ledNum < topNumLeds; ledNum++) { - // Map to the bin number, skip all bins required. Start at the second bin to avoid DC - uint8_t binNumber = (ledNum < visualiserNumBinsToSkip) ? visualiserNumBinsToSkip : constrain(ledNum, 0, VISUALISER_NUM_SAMPLES/2); - // Serial.print(binNumber); - // Serial.print("\t"); - - // Subract the minium value chosen for reduction of artifacts - double adjustedBinValue = (visualiserRealSamples[binNumber] > visualiserMinThreshold) ? visualiserRealSamples[binNumber]-visualiserMinThreshold : 0.0; - // Serial.print(adjustedBinValue); - // Serial.print("\t"); - - // Set if visualiserRealSamples[binNumber] is above 0 - if (adjustedBinValue > 0) { - // Map the float values to 8 bit integers - uint8_t brightnessValue = map(adjustedBinValue, 0, visualiserMaxThreshold, 0, 255); - // Serial.println(brightnessValue); - - // Get the current hue of the rainbow for the specific LED - uint8_t ledHue = int(255.0/(topNumLeds - 1) * ledNum + visualiserHueOffset) % 255; - CRGB newColour = CRGB(CHSV(ledHue, 255, 255)).nscale8(brightnessValue*(visualiserFadeUp/255.00)); - - // Add the new colour to the current LED - ledString[topLeds[ledNum]] = ledString[bottomLeds[ledNum]] += newColour; - - // If the LED num is the first or last, use it to set the sides - if (ledNum == 0) { - for (int sideLedNum = 0; sideLedNum < rightNumLeds; sideLedNum++){ - ledString[rightLeds[sideLedNum]] += newColour; - } - } - else if (ledNum == topNumLeds-1) { - for (int sideLedNum = 0; sideLedNum < leftNumLeds; sideLedNum++){ - ledString[leftLeds[sideLedNum]] += newColour; - } - } + else if (ledNum == topNumLeds - 1) + { + for (int sideLedNum = 0; sideLedNum < leftNumLeds; sideLedNum++) + { + ledString[leftLeds[sideLedNum]] += newColour; } } - - // Fade all leds gradually for a smooth effect - fadeToBlackBy(ledString, NUM_LEDS, visualiserFadeDown); - // fadeLightBy(ledString, NUM_LEDS, visualiserFadeDown); - } - else { - // Serial.println("Websockets Connecting"); - delay(1000); } - } + } - virtual void applyConfig(JsonVariant& settings) { - settings["Period"] = visualiserPeriod = settings["Period"] | visualiserPeriod; - settings["MinThreshold"] = visualiserMinThreshold = settings["MinThreshold"] | visualiserMinThreshold; - settings["MaxThreshold"] = visualiserMaxThreshold = settings["MaxThreshold"] | visualiserMaxThreshold; - settings["FadeUp"] = visualiserFadeUp = settings["FadeUp"] | visualiserFadeUp; - settings["FadeDown"] = visualiserFadeDown = settings["FadeDown"] | visualiserFadeDown; - settings["HueOffset"] = visualiserHueOffset = settings["HueOffset"] | visualiserHueOffset; + // Fade all leds gradually for a smooth effect + fadeToBlackBy(ledString, NUM_LEDS, visualiserFadeDown); + // fadeLightBy(ledString, NUM_LEDS, visualiserFadeDown); + } + else + { + // Serial.println("Websockets Connecting"); + delay(1000); } + } + + virtual void applyConfig(JsonVariant &settings) + { + settings["Period"] = visualiserPeriod = settings["Period"] | visualiserPeriod; + settings["MinThreshold"] = visualiserMinThreshold = settings["MinThreshold"] | visualiserMinThreshold; + settings["MaxThreshold"] = visualiserMaxThreshold = settings["MaxThreshold"] | visualiserMaxThreshold; + settings["FadeUp"] = visualiserFadeUp = settings["FadeUp"] | visualiserFadeUp; + settings["FadeDown"] = visualiserFadeDown = settings["FadeDown"] | visualiserFadeDown; + settings["HueOffset"] = visualiserHueOffset = settings["HueOffset"] | visualiserHueOffset; + } + + virtual void sendWebsiteData(WebSocketsServer &_webSocketServer) + { + const char *modeName = "Visualiser"; + const char *tabHtml = PSTR("

Visualiser Mode<\\/h2>\\r\\n" + "

Here you can set the mode to Visualiser. This mode does an FFT on the ADC of the ESP8266 and maps the\\r\\n" + " frequencies\\r\\n" + " to the number of top and bottom LED's. To use this mode, an input source must be present on the ADC such\\r\\n" + " as an amplified mic\\r\\n" + " or an input from a music source such as a Chromecast.\\r\\n" + "<\\/p>\\r\\n" + "

\\r\\n" + "