
/*
**    Ring Light
**
**   Copyright 2021 Guido Mersmann <geit@geit.de>
**   All rights reserved.
**
*/

This is the main software used to drive my Ringlight designs on Thingiverse.com:

Ring Light V1          https://www.thingiverse.com/thing:4817409
Ring Light V2 (Dual)   https://www.thingiverse.com/thing:4877991
Ring Light V3 (Halo)   https://www.thingiverse.com/thing:4904677

This software is delivered as it is. I am not responsible for any damages caused
by using a device driven by this firmware, nor for any network insecurity caused
by this source code.

-------------------------------------------------------------------------------------------------------------------

Note:
-----

This software is under constant development. If you find bugs or issues, then
feel free to report them. Just make sure you check the latest version before
sending any messages about your findings. Maybe the issue is already gone
with the latest version.

-------------------------------------------------------------------------------------------------------------------

Changelog:
----------

1.00
    First working version.
1.01
    Added basic web interface.
1.02
    Added sound support.
    Added 30 and 60 minute gong.
1.03 
    Added Rainbow and Twinkel animations.
1.04
    Added random animation change. (per effect setting)
1.05
    Cleanups and source refraction.
1.06
    Settings load/save and reset support.
1.07
    Using second core for all network related processing. This prevents
      animations from loosing frames during external network access.
1.08
    Added timed power configuration.
1.09
    Added timed brightness configuration.
1.10
    Added timed sound volume configuration.
1.11
    Added login to web interface.
1.12
    Now it is possible to configure the SSID and the WifI Password.
1.13
    Fixed random crash caused by using the wrong index in some animations.
1.14
    Added Race, Color Comet and Color Comet static.
    Cleaned and unified debug output.
1.15
    Added Rainbow Sparkle animation.
    Added "Logout" and "Reboot" buttons to misc settings.
    Added login status to the status page.
1.16
    Massive code cleanup to the code and backport to giant clock project.
1.17
    Reworked WiFi code to reconnect, when WiFi connection gets lost. The
      Access point mode get activated inbetween.
1.18 
    Reworked the status page creation to be more flexible.
1.19
    Added support for Amazon devices.
1.20
    Added device name to the status page.
1.21
    Added on the fly renaming of the Alexa device name.
1.22
    Regrouped webpage creation.
1.23
    Fixed website buttons.
    Fixed hostname handling.
    Added hostname settings.
    Added button support (global modes, swap network and factory reset can 
      be used via button control).
    Added led feedback support (button feedback, ESP LED).
    Added swap network function.
    Fixed and simplified audio volume control.
1.24
    The "include/credentials.h" file is now mandatory. Store your credentials
    and other data there. Please note that the archive contains the file with
    "_" at the end. You need to rename the file. This ensures your credential
    file stays intact, when updating the source.
1.25
    Start sound failed to play since I reworked WiFi code, due to the new
      async nature. 
    Fixed long standing issue where the hour gong was played after start
    sound Optimized startup code.
    Fixed long standing issue where sound was played even when the device
      was switched off. Timed audio settings now only work inside the
      limits of the power state.
    Fixed cached login forwarding causing trouble on webkit based browsers.
1.26
    Fixed power consumption output on status page.
1.27
    Reworked configuration. Credentials.h is no more.
1.28
    Added support for a second led strip.
    Fire: Simplified the code by using HeadColor() function provides by FastLED.
    Static: Secondary color used for secondary strip
1.29
    Added "Race (Loop)" animation mode
    Reworked animation handling
    Fader between animations is now global.
    Brightness control handling reworked to reduce CPU load.
    Implemented RandomSync mode
1.30
    Added default LED number for R100 and R165 rings to configuration 
1.31
    Added Testmodes for dual ring configuration.
    Outer ring default mode is now ANIMATION_RANDOMSYNC.
    Even without internet and therefor no valid NTP time animations are now
      changing every 15 minutes.
1.32
    Adapted race fade depending on the led strip length for less long racers 
      on small diameter rings.
    Fixed build, when Fauxmo support gets disabled.
    Fixed build, when single strip (V1) ring is active (random async).
    Fixed crash, when single strip (V1) ring is active.
1.33
    Adapted race loop speed.
    Optimized core0 OTA task handling.
1.34
    Added new "off" animation mode, so a single ring (v2 and up model) can 
      easily disabled.
    Added new "Brick Wall" and "Brick Wall (Static)" modes.
    The inner rings effect can now be mirrored. (per effect setting)
    Fixed issue when less LEDs are defined than available. Up to 8 LEDs
      now get ignored per strip, but cleared on startup.
    Reduced the fader speed between effects, so it actually becomes visible.
    Reworked and cleaned the web interface 
1.35
    Tweaked "Brick Wall" mode to build the next cycle on top of the existing 
      wall.
    Added "Brick Wall (Classic)" mode to ressemble the original style.
    Tweaked "Race" mode to look better on smaller rings.
    Fixed mirror option as it overstepped its mirroring and swapped one LED
      back at the rings top.
1.36
    Reworked, cleaned and simplified rendering and display code.
    Added LEDs per ring configuration, so the default can be adjusted.
      Please note that the number can only be adjusted between 20 and the
      longest LEDs strip defined in configuration.h plus 5. This is currently
      a limitation as the fire/race animations need buffers per led, which is
      contained inside a fixed structure generated at compile time. This
      probably will be changed in the future, but currently thats the limit
      and should be ok.
1.37
    Added new modes "Color Wipe", "Color Wipe (Static)", "Signal Wipe" and
      "Signal Wipe (Static)".
    Fixed adaptive speed for "Race (Loop)".
1.38
    Fixed a potential crash in "Race (Loop)", where the calculated number 
      of racers per srtip exceed the array size.

-------------------------------------------------------------------------------------------------------------------

Configuration:
--------------

The project drawer contains a file named "configuration.h_". This file allows
to setup some important network features like WiFi SSID and WiFi password, the 
login password, OTA programming password and the optional default NTP server 
to use.

The number of LEDs used in your LED strips as well as the pins to connect the
LED data line and other hardware configuration is specified here, too 

For more default configuration check the file "rl_global.cpp" and the related
"rl_global.h"

If you want to add the DFPlayer sound module, you will find the used pins to 
connect it to in "rl_sound.h". The used samples are defined there, too. Just 
make sure to change the related table in "rl_wifi.h", so the web server 
selection matches the specified samples.

When using the identical pins specified in source, you probably only need to
change the number of LEDs to compile a proper firmware.

-------------------------------------------------------------------------------------------------------------------

Compile:
--------

To compile you need VSCode with the "PlatformIO" plugin installed. Before you
can compile the source you need to create a configuration.h file containing all
hardware and WiFi information to operate the device within your home network.
Lucky for you I already wrote such file and it is already included. All you
need to do is to change the default values with your personal data. The last step
is to rename the file and remove the appended "_".

Now open the "RingLight" folder and hit the compile and upload button. 

-------------------------------------------------------------------------------------------------------------------

Usage:
------

If you did not configure the WiFi information inside "configuration.h" file, the
RingLight will be unable to connect to the internet. However, it will open an
access point named "ESP_RINGLIGHT" after some time. Use "http://192.168.0.1:81"
when the access point mode is running and you are connected to it.

Use your router or a network device scanning application to find the newly added
device. Please note that you need to access via port 81 due to the Alexa support.
I am checking ways to avoid this, but currently port 81 it is. So if your device
was located at "192.168.0.24", use "http://192.168.0.24:81" to connect. Please
note that some browsers modify your address from "http" to "https" on errors.
https is not supported, so you may need to remove the "s" again, before 
performing a retry.

Use a computer or a mobile phone and log into the device using the default
password "123456". Once done you can specify the SSID and PASSWORD. Hit
"Save and Reconnect". After a few seconds the RingLight will appear in your home
network. If the connection gets lost for some time, the build in AP  will
reappear, but only until it is able to reconnect or the WiFi gets configured
to the new network. No flashing is required.

The default password to log into the device is "123456" and can be changed once
the device is logged into your home network.

The web server has a simple design. At the top is menu for selecting the different 
configuration page groups.

-------------------------------------------------------------------------------------------------------------------

Button Support:
---------------

By default the firmware enables button support on GPIO0. If your ESP module has a
boot button, thats it. 

Power on Reset: Factory reset. Hold the button and turn/power it on. After a five 
                second delay the system will reboot on its own. If the LED is 
                connected and configured it will blink, when you can release the 
                button.

There are two types of actions available: Pressing a specific number of times 
and pressing a specific number of time while holding the last press for five 
seconds.

P = Press, H = hold the last press. The number is the number of presses.
P7 is pressing 7 times, while PH4 is press 4 times and hold the last press for
two seconds.

P1              Global mode gets switched to "ON"
P2              Global mode gets switched to "AUTO"
P1H             Global mode gets switched to "OFF"
P4              The device will swap to the alternate WiFi configuration as
                specified in the credentials.h file.
P4H             Factory reset

So pressing the button once will force the device on, while pressing and
holding it turns the device off again.

-------------------------------------------------------------------------------------------------------------------

Alexa Support:
--------------

When using the device with Amazon voice controlled devices you have the
following options. "Alexa turn <devicename> on!". This activates the timerless
global mode ALWAYS_ON. "Alexa turn <devicename> off!" switches the device into
the global mode ALLWAYS_OFF mode. You can specify the brightness from 0 to
100%: "Alexa turn <devicename> brightness to 75%!". *** Please note that
the value 99% is used as a special control word. It switches the global
mode back to its default AUTO mode. 

There is one little caveat. The Hue system seems to send an "On" command
when changing the brightness. So setting the brightness without changing
the global mode is impossible. So if you change the brightness using your
voice you need to command the brightness to 99% again to switch to auto 
mode again. There is no way around as the software cannot detect if the 
ON-command came from Hue-System or your voice.

To specify the name, enter the network settings and type in the name you
want to use. Do avoid spaces or other non alphabetic characters. Press 
the button below. The new name is set and will be used by the device.

Now tell Alexa to search for new devices or press search in the web interface.
The amazon web interface can be found here: https://alexa.amazon.?? enter the
smart home section and select devices. At the bottom of the list you will find
a search button. Next to each entry is a delete button to erase a prior device
and its name. Do not use the "delete/remove all" button. It is broken. 

The mobile app is garbage in general. It drains your battery and is slow. 
If possible use a desktop browser. Use the delete/remove option next to 
each of the devices in the device list to remove it.

The name must be changed and saved, before using Alexa to find new devices. 
Keep in mind to delete old and unused names, as Alexa is still using them.
The currently used name is shown on the status page.

-------------------------------------------------------------------------------------------------------------------

Web Interface Overview:
-----------------------

Status:
              Shows general information about the device operation.
Visual:
    Visual Configuration
              Configures the animation modes available, the overall brightness and color
              information

        Mode: (Inner Ring:)
              This is the animation mode used for the device. Random is special as it will
              pick a random animation mode every 15 minutes and the selection is defined
              by the "Favorite" box.

        Favorite:
              The favorite checkbox is special. It is available per inner ring mode. All
              modes where favorite is set, will show up randomly, when the mode is set
              to "Random".

        Mirror:
              This setting is per inner ring mode. For each mode you can set if the effect
              should be mirrored. This makes no sense for a single ring, but for the dual 
              and the halo rings, where inside and outside can operate in the same 
              direction. This option also fixes wrongly assembled rings, where the data
              direction of both rings is the same. If you have a broken ring, select all
              modes one by one and enable the mirror setting.

        Outer Ring:
              Only available when the secondary LED strip got enabled. It works like the
              inner ring mode explained above, just for the outer rings LED strip.

        Brightness:
              Brightness used for the entire display. Operates within the specified limits
              of the day/night brightness configuration. 8% at day and this set to 50% will
              result in 4% total brightness.

        Color:
              This color information is used by some modes as foreground and background color.
              (e.g. "Static", "Color Comet Static")

Sound:
    Sound Configuration
              Audio output is only available, when a DFPlayer module is installed.

        Sound:
              Turns audio output on or off.

        Night Start:
              Beginning at the specified hour of day the device uses night time volume settings.

        Volume at night:
              Volume in % to be used at night time.

        Day Start:
              Beginning at the specified hour of day the device uses day time volume settings.

        Volume at day:
              Volume in % to be used at day time.

        Boot Sample:
              Sample to be played on power up or reboot.

        Hour:
              Sample to be played at the beginning of every new hour.

        Half Hour:
              Sample to be played at every half hour mark.

    Test Section
        Play Testsound1
              Just a simple way to play test samples.

        Play Testsound2
              Just a simple way to play test samples.

Global: 
    Global
        Mode: 
              "Auto": activates the timed power settings of the device. It turns the device on and
              off at the specified hours. "Always Off" mode disables the device permanently and
              "Always on" makes it run 24/7. This setting is not saved. After power loss or reset it
              turns to "Auto" mode again. This is just to turn it temporary on or off on demand, so
              you can turn it on beyond it default day time setup during a party or turn it off if
              you go to sleep early without modifying the actual settings.

        Status LED Mode:
              Turns the first LED into a WiFi status LED. Currently not much use.

        Inner Ring LEDs:
              Allows to specify the number of LEDs used for this ring. Any additional LEDs at the 
              end of the strip will be ignored if the value is smaller. If the value is bigger than
              the actual number of LEDs the device will act like there are more and effects will
              render within the invisible area.

        Outer Ring LEDs:
              Only available when the secondary LED strip got enabled. Works like the inner ring
              configuration.

    Color Configuration
        LED Color Correction:
              Color correction modes provided by the FastLED library.

        LED Color Temperature:
              Color temperature correction modes provided by the FastLED library.

    Power Configuration
        Night Start:
              Beginning at the specified hour of day the device turns off.

        Day Start:
              Beginning at the specified hour of day the device turns on.

    Brightness Configuration
        Night Start:
              Beginning at the specified hour of day the device uses brightness for night mode.

        Day Start:
              Beginning at the specified hour of day the device uses brightness for day mode.

Misc:
    Settings
        Save:
              Stores settings in flash.

        Load:
              Loads previously stored settings from flash file system and uses them.

        Factory Reset:
              Loads and uses predefined factory settings.

        Swap Networks
              Swap between the predefined wifi settings in "credentials.h"
              This is just temporary unless you hit save settings afterwards.
              One use case for this button is, if you have the device in your
              IoT-Network and your computer in your private network. To flash
              you log in via a phone, push this button and once the device
              appears in your private network you can update it using your
              conputer.

    System
        Logout
              Logs out and asks for the device password again.

        Reboot
              Performs a software reset.

Network:
    SSID Settings
        SSID:
              Name of the WiFi network to connect to.

        Password:
              Password for the specified WiFi network.

        Save and Connect:
              Saves settings and connects with the specified network.

    Login Configuration
        Password:
              Password to log into the device.

        Repeat:
              Same as password. Must be equal. While the passwords are not equal or are shorter
              than 6 characters a warning will appear and the "update and save" button is disabled.
              Once the password is right, the text fields will reset and the button below will be
              activated.

        Update and Save:
              Only available, when the "Password" and "Repeat" field got the same password with a
              minimal length of 6 characters.

    Alexa Support
        Name:
              This is the name you call the device. See Alexa support section for detailed
              information.
        Update and Save:
              Save the new device name and anounce it to the network. You need to run a device
              scan on Alexa to find it again.

    Miscellaneous
        Host Name:
              Defines the host name of the device. Please note that it usually displays fine in
              routers, but access is a little wacky. You need to save settings and reboot to
              make the new host name available to the network.

-------------------------------------------------------------------------------------------------------------------
