├── .clang-format ├── .github ├── autolabeler.yml ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── feature-request.md │ └── bug.md ├── invite-contributors.yml ├── PULL_REQUEST_TEMPLATE.md ├── potential-duplicates.yml ├── move.yml ├── CONTRIBUTING.md ├── support.yml ├── lock.yml ├── no-response.yml ├── stale.yml ├── config.yml ├── CODE_OF_CONDUCT.md └── settings.yml ├── renovate.json ├── diagrams ├── neopixel_ring_ws2812_5v_usb.fzz ├── neopixel_strip_string_ws2811_5v_psu.fzz └── neopixel_strip_string_ws2811_5v_psu.svg ├── .gitignore ├── .vscode └── extensions.json ├── .travis.yml ├── platformio.ini ├── src ├── setup-template.h └── main.cpp ├── .gitlab-ci.yml ├── LICENSE.md ├── lib └── readme.txt └── README.md /.clang-format: -------------------------------------------------------------------------------- 1 | ColumnLimit: 0 2 | IndentWidth: 2 -------------------------------------------------------------------------------- /.github/autolabeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | "Type: Documentation": ["*.md", "*.j2"] 3 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /diagrams/neopixel_ring_ws2812_5v_usb.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timmo001/ESP8266-MQTT-JSON-Lights/HEAD/diagrams/neopixel_ring_ws2812_5v_usb.fzz -------------------------------------------------------------------------------- /diagrams/neopixel_strip_string_ws2811_5v_psu.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/timmo001/ESP8266-MQTT-JSON-Lights/HEAD/diagrams/neopixel_strip_string_ws2811_5v_psu.fzz -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Require maintainer's :+1: for changes to the .github/ repo-config files 2 | # mainly due to https://github.com/probot/settings privilege escalation 3 | .github/* @timmo001 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .clang_complete 4 | .gcc-flags.json 5 | .vscode/.browse.c_cpp.db* 6 | .vscode/c_cpp_properties.json 7 | .vscode/launch.json 8 | .vscode/settings.json 9 | src/setup.h 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ] 7 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Feature request' 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | # Description 7 | 8 | 9 | 10 | ## Suggested Actions 11 | 12 | 13 | 14 | ## Additional 15 | 16 | 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | 5 | sudo: false 6 | cache: 7 | directories: 8 | - "~/.platformio" 9 | 10 | install: 11 | - pip install -U platformio 12 | - platformio update 13 | 14 | script: 15 | - mv src/setup-template.h src/setup.h 16 | - platformio run 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Bug' 3 | about: A bug found the application. This is not a support question. Please 4 | ask these via the support channels. 5 | --- 6 | 7 | # Description 8 | 9 | 10 | 11 | ## How to reproduce the issue (if applicable) 12 | 13 | 14 | 15 | ## Additional information 16 | 17 | 18 | -------------------------------------------------------------------------------- /.github/invite-contributors.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # If true, this will add new contributors as outside collaborators 3 | # to the repo their PR was merged in. Team name is ignored if this 4 | # flag is set to true. 5 | isOutside: false 6 | 7 | # Specify team name to add new contributors to a specific team 8 | # within your organization. 9 | # Use team name or team-name-slug 10 | team: Contributors 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | 4 | 5 | ## Related issues this fixes 6 | 7 | 8 | 9 | ## Checklist 10 | 11 | 12 | 13 | - [ ] Change has been tested and works on my device(s). 14 | - [ ] Linters have been run. 15 | - [ ] I am ready to merge. 16 | -------------------------------------------------------------------------------- /.github/potential-duplicates.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Label name and color to set, when potential duplicates are detected 3 | issueLabel: "Potential duplicate" 4 | labelColor: e6e6e6 5 | 6 | # If similarity is higher than this threshold, issue will be marked as duplicate 7 | threshold: 0.70 8 | 9 | # Comment to post when potential duplicates are detected 10 | referenceComment: > 11 | Potential duplicates found: 12 | {{#issues}} 13 | - [#{{ number }}] {{ title }} ({{ accuracy }}%) 14 | {{/issues}} 15 | -------------------------------------------------------------------------------- /.github/move.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Delete the command comment when it contains no other content 3 | deleteCommand: true 4 | 5 | # Close the source issue after moving 6 | closeSourceIssue: true 7 | 8 | # Lock the source issue after moving 9 | lockSourceIssue: true 10 | 11 | # Mention issue and comment authors 12 | mentionAuthors: true 13 | 14 | # Preserve mentions in the issue content 15 | keepContentMentions: false 16 | 17 | # Set custom aliases for targets 18 | # aliases: 19 | # r: repo 20 | # or: owner/repo 21 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; http://docs.platformio.org/page/projectconf.html 10 | 11 | [env:nodemcuv2] 12 | platform = espressif8266 13 | board = nodemcuv2 14 | framework = arduino 15 | lib_deps = ArduinoJson, PubSubClient, WS2812FX 16 | monitor_baud = 115200 17 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | You are welcome to edit, fork and create pull requests as you like. 4 | 5 | - If you make a change, make sure to refer to any issues that it fixes. 6 | - Make sure you have used linters and tested what you have added/changed 7 | works. 8 | - Any pull request will be verified by the bots, so make sure you fix any 9 | issues the bots find. 10 | - I, and any other users I approve will be able to merge your changes so 11 | be patient. 12 | 13 | ## Docs 14 | 15 | Feel free to improve documentation as you like by making a pull request in 16 | `/docs`. Once merged into the master branch, my ci server will update the 17 | docs in the `gh-pages` branch. 18 | -------------------------------------------------------------------------------- /.github/support.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration for support-requests - https://github.com/dessant/support-requests 3 | 4 | # Label used to mark issues as support requests 5 | supportLabel: "Status: Support" 6 | 7 | # Comment to post on issues marked as support requests. Add a link 8 | # to a support page, or set to `false` to disable 9 | supportComment: > 10 | :wave: We use the issue tracker exclusively for bug reports and feature requests. 11 | However, this issue appears to be a support request. Please use our 12 | support channels to get help with the project. 13 | 14 | # Close issues marked as support requests 15 | close: true 16 | 17 | # Lock issues marked as support requests 18 | lock: false 19 | -------------------------------------------------------------------------------- /.github/lock.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration for lock-threads - https://github.com/dessant/lock-threads 3 | # Number of days of inactivity before a closed issue or pull request is locked 4 | daysUntilLock: 30 5 | 6 | # Comment to post before locking. Set to `false` to disable 7 | lockComment: > 8 | This thread has been automatically locked because it has not had recent 9 | activity. Please open a new issue for related bugs and link to relevant 10 | comments in this thread. 11 | 12 | # Issues or pull requests with these labels will not be locked 13 | # exemptLabels: 14 | # - no-locking 15 | 16 | # Limit to only `issues` or `pulls` 17 | # only: issues 18 | 19 | # Add a label when locking. Set to `false` to disable 20 | lockLabel: false 21 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration for probot-no-response - https://github.com/probot/no-response 3 | # Number of days of inactivity before an Issue is closed for lack of response 4 | daysUntilClose: 14 5 | # Label requiring a response 6 | responseRequiredLabel: "Status: Awaiting response" 7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable 8 | closeComment: > 9 | This issue has been automatically closed because there has been no response 10 | to our request for more information from the original author. With only the 11 | information that is currently in the issue, we don't have enough information 12 | to take action. Please reach out if you have or find the answers we need so 13 | that we can investigate further. 14 | -------------------------------------------------------------------------------- /src/setup-template.h: -------------------------------------------------------------------------------- 1 | /* Add your keys & rename this file to setup.h */ 2 | using namespace std; 3 | 4 | #define WIFI_SSID "SSID" 5 | #define WIFI_PASSWORD "PASSWORD" 6 | 7 | #define MQTT_SERVER "DOMAIN_OR_IP" 8 | #define MQTT_USER "USERNAME" 9 | #define MQTT_PASSWORD "PASSWORD" 10 | #define MQTT_PORT 1883 11 | char *MQTT_STATE_TOPIC_PREFIX = "light/"; // e.g. led/ and led//set 12 | 13 | #define OTApassword "PASSWORD" //the password you will need to enter to upload remotely via the ArduinoIDE 14 | #define OTAport 8266 15 | 16 | #define LED_PIN 14 // D5 on ESP8266 17 | #define LED_COUNT 12 18 | #define NEO_PIXEL_TYPE NEO_RGB + NEO_KHZ800 19 | #define DEFAULT_EFFECT FX_MODE_RAINBOW_CYCLE 20 | #define DEFAULT_POWER_ON_STATE true 21 | 22 | char *deviceName = "led"; 23 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: python:2 2 | 3 | stages: 4 | - build 5 | 6 | # Change pip's cache directory to be inside the project directory since we can 7 | # only cache local items. 8 | variables: 9 | PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache" 10 | 11 | # Pip's cache doesn't store the python packages 12 | # https://pip.pypa.io/en/stable/reference/pip_install/#caching 13 | # 14 | # If you want to also cache the installed packages, you have to install 15 | # them in a virtualenv and cache it as well. 16 | cache: 17 | paths: 18 | - .cache/pip 19 | - venv/ 20 | - ~/.platformio 21 | 22 | before_script: 23 | - python -V # Print out python version for debugging 24 | - pip install -U platformio 25 | - platformio update 26 | 27 | run: 28 | stage: build 29 | script: 30 | - mv src/setup-template.h src/setup.h 31 | - platformio run 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) Timmo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/readme.txt: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for the project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link to executable file. 4 | 5 | The source code of each library should be placed in separate directory, like 6 | "lib/private_lib/[here are source files]". 7 | 8 | For example, see how can be organized `Foo` and `Bar` libraries: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) http://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- readme.txt --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | Then in `src/main.c` you should use: 31 | 32 | #include 33 | #include 34 | 35 | // rest H/C/CPP code 36 | 37 | PlatformIO will find your libraries automatically, configure preprocessor's 38 | include paths and build them. 39 | 40 | More information about PlatformIO Library Dependency Finder 41 | - http://docs.platformio.org/page/librarymanager/ldf.html 42 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration for probot-stale - https://github.com/probot/stale 3 | 4 | # Number of days of inactivity before an Issue or Pull Request becomes stale 5 | daysUntilStale: 60 6 | 7 | # Number of days of inactivity before a stale Issue or Pull Request is closed. 8 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 9 | daysUntilClose: 7 10 | 11 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 12 | exemptLabels: 13 | - "Status: On hold" 14 | - "Status: In progress" 15 | - "Status: Awaiting response" 16 | - "Status: Blocked" 17 | - "Idea" 18 | - "Security" 19 | 20 | # Set to true to ignore issues in a project (defaults to false) 21 | exemptProjects: false 22 | 23 | # Set to true to ignore issues in a milestone (defaults to false) 24 | exemptMilestones: false 25 | 26 | # Label to use when marking as stale 27 | staleLabel: "Status: Stale" 28 | 29 | # Comment to post when marking as stale. Set to `false` to disable 30 | markComment: > 31 | This issue has been automatically marked as stale because it has not had 32 | recent activity. It will be closed if no further activity occurs. Thank you 33 | for your contributions. 34 | 35 | # Comment to post when removing the stale label. 36 | # unmarkComment: > 37 | # Your comment here. 38 | unmarkComment: false 39 | 40 | # Comment to post when closing a stale Issue or Pull Request. 41 | # closeComment: > 42 | # Your comment here. 43 | closeComment: false 44 | 45 | # Limit the number of actions per hour, from 1-30. Default is 30 46 | limitPerRun: 30 47 | 48 | # Limit to only `issues` or `pulls` 49 | only: issues 50 | 51 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': 52 | # pulls: 53 | # daysUntilStale: 30 54 | # markComment: > 55 | # This pull request has been automatically marked as stale because it has not had 56 | # recent activity. It will be closed if no further activity occurs. Thank you 57 | # for your contributions. 58 | 59 | # issues: 60 | # exemptLabels: 61 | # - confirmed 62 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Configuration for request-info - https://github.com/behaviorbot/request-info 3 | 4 | # *OPTIONAL* Comment to reply with 5 | # Can be either a string : 6 | requestInfoReplyComment: 7 | - "We would appreciate it if you could provide us with more info about this issue/pr!" 8 | - "Hmmm... That issue/PR is kinda low on text. Could you please provide some more content?" 9 | 10 | # *OPTIONAL* default titles to check against for lack of descriptiveness 11 | # MUST BE ALL LOWERCASE 12 | requestInfoDefaultTitles: [] 13 | 14 | # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given 15 | requestInfoLabelToAdd: "Incomplete" 16 | 17 | # *OPTIONAL* Require Pull Requests to contain more information than what is provided in the PR template 18 | # Will fail if the pull request's body is equal to the provided template 19 | checkPullRequestTemplate: true 20 | 21 | # *OPTIONAL* Only warn about insufficient information on these events type 22 | # Keys must be lowercase. Valid values are 'issue' and 'pullRequest' 23 | requestInfoOn: 24 | pullRequest: true 25 | issue: true 26 | 27 | # *OPTIONAL* Add a list of people whose Issues/PRs will not be commented on 28 | # keys must be GitHub usernames 29 | requestInfoUserstoExclude: [] 30 | 31 | # Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome 32 | 33 | # Comment to be posted to on first time issues 34 | newIssueWelcomeComment: > 35 | :wave: Thanks for opening your first issue here! 36 | If you're reporting a :bug: bug, please make sure you include steps to reproduce it. 37 | Also, any logs, error messages etc. are useful. 38 | 39 | # Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome 40 | 41 | # Comment to be posted to on PRs from first time contributors in your repository 42 | newPRWelcomeComment: > 43 | Thanks for opening this pull request! :+1: 44 | If your PR gets accepted and merged in, we will invite you to the project :tada: 45 | 46 | # Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge 47 | 48 | # Comment to be posted to on pull requests merged by a first time user 49 | firstPRMergeComment: > 50 | Congrats on merging your first pull request! :tada: :tada: :tada: 51 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266 MQTT JSON Lights [![Build Status](https://travis-ci.org/timmo001/ESP8266-MQTT-JSON-Lights.svg?branch=master)](https://travis-ci.org/timmo001/ESP8266-MQTT-JSON-Lights) 2 | ESP8266 MQTT JSON Lights. Supports brightness, effects, speed and OTA uploads. Based on https://github.com/bruhautomation/ESP-MQTT-JSON-Digital-LEDs 3 | 4 | ## Showcase Video 5 | [![Showcase Video](http://img.youtube.com/vi/gas0h9pCgSs/0.jpg)](https://youtu.be/gas0h9pCgSs) 6 | 7 | ## Known working devices 8 | - WS2812 5v LED Ring 9 | - WS2811 5v LED String (Required `NEO_GRB` to be changed to `NEO_RGB` on line 56 in `main.cpp` for my set of lights) 10 | 11 | > This is not a comprehensive list by any means. Just devices that I or others have tested are working. Feel free to try uploading to your own device and add a pull request if your device works also. 12 | 13 | ## Hardware Setup 14 | Hardware is your choice of course. My examples however only requires a 5v power supply (which could just be USB) with high enough amperage to drive the LEDs. 15 | 16 | ### USB Neopixel WS2812 Ring/Strip Version 17 | ![USB Neopixel WS2812 Ring Version](diagrams/neopixel_ring_ws2812_5v_usb.svg) 18 | > A 5V power supply may be required if your lights draw too much current. 19 | > If this happens or you are planning to use more than 30 leds or so, use the below method. 20 | 21 | ### 5v PSU Neopixel WS2811 String/Strip Version 22 | ![5v PSU Neopixel WS2811 String/Strip Version](diagrams/neopixel_strip_string_ws2811_5v_psu.svg) 23 | > The diode / zenner diode isn't required, but I added it to avoid any reverse current issues. 24 | 25 | > You can drive over 100 LEDs without issues on this method. You may however have to add a wire from the PSU +5v to sections of the wire if you experience dimming along the string/strip. 26 | 27 | ## Software Setup 28 | - Using Atom or VS Code, install [Platform IO](https://platformio.org/platformio-ide) 29 | - Once setup, install the `esp8266` embedded platform 30 | - Rename `src/setup-template.h` to `src/setup.h` and add your network, MQTT and lighting setup information. Take note of the `deviceName` you set. You will need this later to send MQTT messages. 31 | - Build the project (Ctrl+Alt+B) and check for any errors 32 | 33 | > If the build produces an error referencing dependencies, You will need to manually install these libraries: 34 | - Adafruit NeoPixel 35 | - ArduinoJson 36 | - PubSubClient 37 | - WS2812FX 38 | - Upload to your board of choice (Ctrl+Alt+U). This project was created specifically for the `NodeMCU` but can be configured to work with another WiFi board with some tinkering. 39 | 40 | ## Example Home Assistant Configuration 41 | ```yaml 42 | light: 43 | platform: mqtt_json 44 | name: 'LED Lights' 45 | state_topic: 'light/led' 46 | command_topic: 'light/led/set' 47 | availability_topic: 'light/led/LWT' 48 | payload_available: 'Online' 49 | payload_not_available: 'Offline' 50 | effect: true 51 | effect_list: 52 | - static 53 | - blink 54 | - breath 55 | - color wipe 56 | - color wipe inverted 57 | - color wipe reverse 58 | - color wipe reverse inverted 59 | - color wipe random 60 | - random color 61 | - single dynamic 62 | - multi dynamic 63 | - rainbow 64 | - rainbow cycle 65 | - scan 66 | - dual scan 67 | - fade 68 | - theater chase 69 | - theater chase rainbow 70 | - running lights 71 | - twinkle 72 | - twinkle random 73 | - twinkle fade 74 | - twinkle fade random 75 | - sparkle 76 | - flash sparkle 77 | - hyper sparkle 78 | - strobe 79 | - strobe rainbow 80 | - multi strobe 81 | - blink rainbow 82 | - chase white 83 | - chase color 84 | - chase random 85 | - chase rainbow 86 | - chase flash 87 | - chase random 88 | - chase rainbow white 89 | - chase blackout 90 | - chase blackout rainbow 91 | - color sweep random 92 | - running color 93 | - running red blue 94 | - running random 95 | - larson scanner 96 | - comet 97 | - fireworks 98 | - fireworks random 99 | - merry christmas 100 | - fire flicker 101 | - fire flicker soft 102 | - fire flicker intense 103 | - circus combustus 104 | - halloween 105 | - bicolor chase 106 | - tricolor chase 107 | - icu 108 | brightness: true 109 | rgb: true 110 | optimistic: false 111 | qos: 0 112 | 113 | input_number: 114 | led_effect_speed: 115 | name: 'LED Effect Speed' 116 | initial: 50 # This is the default speed 117 | mode: slider 118 | min: 10 # ###################################### 119 | max: 1000 # Feel Free to adjust these as you like 120 | step: 10 # ###################################### 121 | 122 | automation: 123 | - action: 124 | - alias: Set LED Lights Effect Speed 125 | service: mqtt.publish 126 | data_template: 127 | topic: light/led/set 128 | payload: '{"speed":{{ trigger.to_state.state | int }}}' 129 | alias: LED Light Effect Speed 130 | trigger: 131 | - platform: state 132 | entity_id: input_number.led_effect_speed 133 | ``` 134 | 135 | > The speed of the lights will be slower the higher the slider value and faster the lower the value. Treat this more as a delay slider than a speed slider. 136 | 137 | ## Sample MQTT Payload 138 | ```json 139 | { 140 | "brightness": 120, 141 | "color": { 142 | "r": 255, 143 | "g": 255, 144 | "b": 255 145 | }, 146 | "effect": "rainbow cycle", 147 | "speed": 60, 148 | "state": "ON" 149 | } 150 | ``` 151 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | --- 2 | repository: 3 | description: "ESP8266 MQTT JSON Lights. Supports brightness, effects, speed and OTA uploads. Works with MQTT JSON and Home Assistant" 4 | homepage: https://git.timmo.xyz/ 5 | topics: mqtt, home-assistant, WS2812, WS2811, WS2813, neopixel, fastled, led, lights, lighting, c-plus-plus, arduino, nodemcu 6 | private: false 7 | has_issues: true 8 | has_projects: false 9 | has_wiki: false 10 | has_downloads: true 11 | default_branch: master 12 | allow_squash_merge: true 13 | allow_merge_commit: true 14 | allow_rebase_merge: true 15 | labels: 16 | # Priority labels 17 | - name: "Priority: Critical" 18 | color: ee0701 19 | description: "This should be dealt with ASAP. This issue is critical." 20 | oldname: "Critical Priority" 21 | - name: "Priority: High" 22 | color: b60205 23 | description: "After critical issues are fixed, these should be dealt with before any further issues." 24 | oldname: "High Priority" 25 | - name: "Priority: Medium" 26 | color: 0e8a16 27 | description: "This issue may be useful, and needs some attention." 28 | oldname: "Medium Priority" 29 | - name: "Priority: Low" 30 | color: e4ea8a 31 | description: "Low priotity issue." 32 | oldname: "Low Priority" 33 | 34 | # Type labels 35 | - name: "Type: Bug" 36 | color: ee0701 37 | description: "Inconsistencies or issues which will cause a problem for users or implementors." 38 | oldname: "Bug" 39 | - name: "Type: Documentation" 40 | color: 0052cc 41 | description: "Solely about the documentation of the project." 42 | oldname: "Documentation" 43 | - name: "Type: Enhancement" 44 | color: 1d76db 45 | description: "Enhancement of the code, not introducing new features." 46 | oldname: "Enhancement" 47 | - name: "Type: Feature" 48 | color: 0e8a16 49 | description: "New features or options." 50 | oldname: "Feature" 51 | - name: "Type: Support" 52 | color: 5319e7 53 | description: "Marks an issue as an support ticket." 54 | oldname: "Question" 55 | - name: "Type: Discussion" 56 | color: d4c5f9 57 | description: "Marks an issue as an generic discussion ticket." 58 | oldname: "Discussion" 59 | - name: "Type: Maintenance" 60 | color: 2af79e 61 | description: "Generic maintenance tasks, e.g., package updates." 62 | 63 | # Additional markers 64 | - name: "Security" 65 | color: ee0701 66 | description: "Marks an security issues that needs to be resolved asap." 67 | - name: "Idea" 68 | color: ffff28 69 | description: "Marks an idea, which might be excepted and implemented." 70 | - name: "Incomplete" 71 | color: fef2c0 72 | description: "Marks an PR or issue that is missing information." 73 | - name: "Pull request" 74 | color: fbca04 75 | description: "There is an PR opened for this issue." 76 | - name: "Accepted" 77 | color: c2e0c6 78 | description: "This issue or PR has been accepted." 79 | - name: "Declined" 80 | color: f9d0c4 81 | description: "This issue or PR has been declined." 82 | - name: "Potential duplicate" 83 | color: e6e6e6 84 | description: "This issue has been automatically marked as a potential duplicate." 85 | 86 | # Ongoing Status labels 87 | - name: "Status: Triage" 88 | color: fbca04 89 | description: "This issue needs to be triaged." 90 | oldname: "triage" 91 | - name: "Status: On hold" 92 | color: cccccc 93 | description: "Issue or PR that has been placed on hold for now." 94 | oldname: "On hold" 95 | - name: "Status: In progress" 96 | color: fbca04 97 | description: "Issue is currently being resolved by a developer." 98 | - name: "Status: Stale" 99 | color: fef2c0 100 | description: "There has not been activity on this issue or PR for quite some time." 101 | oldname: "stale" 102 | - name: "Status: Awaiting response" 103 | color: fef2c0 104 | description: "Issue or PR awaits response from the creator." 105 | oldname: "Awaiting Response" 106 | - name: "Status: Blocked" 107 | color: fef2c0 108 | description: "Progress on this issue is currently not possible." 109 | oldname: "Blocked" 110 | 111 | # Closing status labels 112 | - name: "Closed: Known limitation" 113 | color: e6e6e6 114 | description: "Issue is closed, it is a known limitation." 115 | oldname: "Known Limitation" 116 | - name: "Closed: Expected behavior" 117 | color: e6e6e6 118 | description: "Issues is closed, it is expected behavior." 119 | oldname: "Expected behavior" 120 | - name: "Closed: Duplicate" 121 | color: e6e6e6 122 | description: "Issue is closed, duplicate of an existing issue." 123 | oldname: "Duplicate" 124 | - name: "Closed: Invalid" 125 | color: e6e6e6 126 | description: "Issue is closed, marked as not a valid issue (e.g., an user error)." 127 | oldname: "Invalid" 128 | - name: "Closed: Wrong repository" 129 | color: e6e6e6 130 | description: "Issue is closed, was created in the wrong repository." 131 | oldname: "Wrong repository" 132 | - name: "Closed: Won't Fix" 133 | color: e6e6e6 134 | description: "Issue is closed, it won't be fixed." 135 | oldname: "Won't fix" 136 | - name: "Closed: Done" 137 | color: c2e0c6 138 | description: "Issue closed, work on this issue has been marked complete." 139 | oldname: "Done" 140 | 141 | # Others 142 | - name: "Beginner Friendly" 143 | color: 0e8a16 144 | description: "Good first issue for people wanting to contribute to the project." 145 | oldname: "Good first issue" 146 | - name: "Help wanted" 147 | color: 0e8a16 148 | description: "We need some extra helping hands or expertise in order to resolve this." 149 | oldname: "Help Wanted" 150 | - name: "Hacktoberfest" 151 | description: "Issues/PRs are participating in the Hacktoberfest" 152 | color: fbca04 153 | - name: "Architecture" 154 | description: "Related to how the app works and/or is built" 155 | color: d1924f 156 | - name: "Code Climate" 157 | description: "Issues created by Code Climate" 158 | color: 42f477 159 | 160 | branches: 161 | - name: master 162 | protection: 163 | required_pull_request_reviews: 164 | dismiss_stale_reviews: true 165 | require_code_owner_reviews: true 166 | dismissal_restrictions: 167 | users: [] 168 | teams: 169 | - Admins 170 | - Masters 171 | required_status_checks: 172 | strict: false 173 | contexts: [] 174 | enforce_admins: false 175 | restrictions: 176 | users: [] 177 | teams: 178 | - Admins 179 | - Masters 180 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | using namespace std; 2 | 3 | #include "setup.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /****************************************FOR JSON***************************************/ 13 | const int BUFFER_SIZE = JSON_OBJECT_SIZE(10); 14 | #define MQTT_MAX_PACKET_SIZE 512 15 | 16 | /*********************************** Defaults ********************************/ 17 | byte red = 255; 18 | byte green = 255; 19 | byte blue = 255; 20 | byte brightness = 204; // 80% 21 | String effect = "rainbow cycle"; // default effect ("static", "rainbow cycle" etc.) 22 | int speed = 50; 23 | 24 | /******************************** OTHER GLOBALS *******************************/ 25 | const char *on_cmd = "ON"; 26 | const char *off_cmd = "OFF"; 27 | const char *will_msg = "Offline"; 28 | const char *online_msg = "Online"; 29 | const char *effectString = "rainbow cycle"; 30 | bool stateOn = DEFAULT_POWER_ON_STATE; 31 | 32 | WiFiClient espClient; 33 | PubSubClient client(espClient); 34 | WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_PIXEL_TYPE); 35 | 36 | unsigned long rgbToHex(int r, int g, int b) { 37 | return ((r & 0xff) << 16) + ((g & 0xff) << 8) + (b & 0xff); 38 | } 39 | 40 | void setEffect(String effect) { 41 | if (effect == "static") 42 | ws2812fx.setMode(FX_MODE_STATIC); 43 | if (effect == "blink") 44 | ws2812fx.setMode(FX_MODE_BLINK); 45 | if (effect == "breath") 46 | ws2812fx.setMode(FX_MODE_BREATH); 47 | if (effect == "color wipe") 48 | ws2812fx.setMode(FX_MODE_COLOR_WIPE); 49 | if (effect == "color wipe inverted") 50 | ws2812fx.setMode(FX_MODE_COLOR_WIPE_INV); 51 | if (effect == "color wipe reverse") 52 | ws2812fx.setMode(FX_MODE_COLOR_WIPE_REV); 53 | if (effect == "color wipe reverse inverted") 54 | ws2812fx.setMode(FX_MODE_COLOR_WIPE_REV_INV); 55 | if (effect == "color wipe random") 56 | ws2812fx.setMode(FX_MODE_COLOR_WIPE_RANDOM); 57 | if (effect == "random color") 58 | ws2812fx.setMode(FX_MODE_RANDOM_COLOR); 59 | if (effect == "single dynamic") 60 | ws2812fx.setMode(FX_MODE_SINGLE_DYNAMIC); 61 | if (effect == "multi dynamic") 62 | ws2812fx.setMode(FX_MODE_MULTI_DYNAMIC); 63 | if (effect == "rainbow") 64 | ws2812fx.setMode(FX_MODE_RAINBOW); 65 | if (effect == "rainbow cycle") 66 | ws2812fx.setMode(FX_MODE_RAINBOW_CYCLE); 67 | if (effect == "scan") 68 | ws2812fx.setMode(FX_MODE_SCAN); 69 | if (effect == "dual scan") 70 | ws2812fx.setMode(FX_MODE_DUAL_SCAN); 71 | if (effect == "fade") 72 | ws2812fx.setMode(FX_MODE_FADE); 73 | if (effect == "theater chase") 74 | ws2812fx.setMode(FX_MODE_THEATER_CHASE); 75 | if (effect == "theater chase rainbow") 76 | ws2812fx.setMode(FX_MODE_THEATER_CHASE_RAINBOW); 77 | if (effect == "running lights") 78 | ws2812fx.setMode(FX_MODE_RUNNING_LIGHTS); 79 | if (effect == "twinkle") 80 | ws2812fx.setMode(FX_MODE_TWINKLE); 81 | if (effect == "twinkle random") 82 | ws2812fx.setMode(FX_MODE_TWINKLE_RANDOM); 83 | if (effect == "twinkle fade") 84 | ws2812fx.setMode(FX_MODE_TWINKLE_FADE); 85 | if (effect == "twinkle fade random") 86 | ws2812fx.setMode(FX_MODE_TWINKLE_FADE_RANDOM); 87 | if (effect == "sparkle") 88 | ws2812fx.setMode(FX_MODE_SPARKLE); 89 | if (effect == "flash sparkle") 90 | ws2812fx.setMode(FX_MODE_FLASH_SPARKLE); 91 | if (effect == "hyper sparkle") 92 | ws2812fx.setMode(FX_MODE_HYPER_SPARKLE); 93 | if (effect == "strobe") 94 | ws2812fx.setMode(FX_MODE_STROBE); 95 | if (effect == "strobe rainbow") 96 | ws2812fx.setMode(FX_MODE_STROBE_RAINBOW); 97 | if (effect == "multi strobe") 98 | ws2812fx.setMode(FX_MODE_MULTI_STROBE); 99 | if (effect == "blink rainbow") 100 | ws2812fx.setMode(FX_MODE_BLINK_RAINBOW); 101 | if (effect == "chase white") 102 | ws2812fx.setMode(FX_MODE_CHASE_WHITE); 103 | if (effect == "chase color") 104 | ws2812fx.setMode(FX_MODE_CHASE_COLOR); 105 | if (effect == "chase random") 106 | ws2812fx.setMode(FX_MODE_CHASE_RANDOM); 107 | if (effect == "chase rainbow") 108 | ws2812fx.setMode(FX_MODE_CHASE_RAINBOW); 109 | if (effect == "chase flash") 110 | ws2812fx.setMode(FX_MODE_CHASE_FLASH); 111 | if (effect == "chase random") 112 | ws2812fx.setMode(FX_MODE_CHASE_FLASH_RANDOM); 113 | if (effect == "chase rainbow white") 114 | ws2812fx.setMode(FX_MODE_CHASE_RAINBOW_WHITE); 115 | if (effect == "chase blackout") 116 | ws2812fx.setMode(FX_MODE_CHASE_BLACKOUT); 117 | if (effect == "chase blackout rainbow") 118 | ws2812fx.setMode(FX_MODE_CHASE_BLACKOUT_RAINBOW); 119 | if (effect == "color sweep random") 120 | ws2812fx.setMode(FX_MODE_COLOR_SWEEP_RANDOM); 121 | if (effect == "running color") 122 | ws2812fx.setMode(FX_MODE_RUNNING_COLOR); 123 | if (effect == "running red blue") 124 | ws2812fx.setMode(FX_MODE_RUNNING_RED_BLUE); 125 | if (effect == "running random") 126 | ws2812fx.setMode(FX_MODE_RUNNING_RANDOM); 127 | if (effect == "larson scanner") 128 | ws2812fx.setMode(FX_MODE_LARSON_SCANNER); 129 | if (effect == "comet") 130 | ws2812fx.setMode(FX_MODE_COMET); 131 | if (effect == "fireworks") 132 | ws2812fx.setMode(FX_MODE_FIREWORKS); 133 | if (effect == "fireworks random") 134 | ws2812fx.setMode(FX_MODE_FIREWORKS_RANDOM); 135 | if (effect == "merry christmas") 136 | ws2812fx.setMode(FX_MODE_MERRY_CHRISTMAS); 137 | if (effect == "fire flicker") 138 | ws2812fx.setMode(FX_MODE_FIRE_FLICKER); 139 | if (effect == "fire flicker soft") 140 | ws2812fx.setMode(FX_MODE_FIRE_FLICKER_SOFT); 141 | if (effect == "fire flicker intense") 142 | ws2812fx.setMode(FX_MODE_FIRE_FLICKER_INTENSE); 143 | if (effect == "circus combustus") 144 | ws2812fx.setMode(FX_MODE_CIRCUS_COMBUSTUS); 145 | if (effect == "halloween") 146 | ws2812fx.setMode(FX_MODE_HALLOWEEN); 147 | if (effect == "bicolor chase") 148 | ws2812fx.setMode(FX_MODE_BICOLOR_CHASE); 149 | if (effect == "tricolor chase") 150 | ws2812fx.setMode(FX_MODE_TRICOLOR_CHASE); 151 | if (effect == "icu") 152 | ws2812fx.setMode(FX_MODE_ICU); 153 | } 154 | 155 | void setup_wifi() { 156 | delay(10); 157 | Serial.print("Connecting to SSID: "); 158 | Serial.println(WIFI_SSID); 159 | 160 | // We start by connecting to a WiFi network 161 | WiFi.mode(WIFI_STA); 162 | WiFi.hostname(deviceName); 163 | 164 | if (WiFi.status() != WL_CONNECTED) { // FIX FOR USING 2.3.0 CORE (only .begin if not connected) 165 | WiFi.begin(WIFI_SSID, WIFI_PASSWORD); 166 | } 167 | 168 | while (WiFi.status() != WL_CONNECTED) { 169 | delay(500); 170 | Serial.print("."); 171 | } 172 | 173 | Serial.println(""); 174 | Serial.println("WiFi connected"); 175 | Serial.print("IP address: "); 176 | Serial.println(WiFi.localIP()); 177 | } 178 | 179 | void sendState() { 180 | StaticJsonBuffer jsonBuffer; 181 | 182 | JsonObject &root = jsonBuffer.createObject(); 183 | 184 | root["state"] = (stateOn) ? on_cmd : off_cmd; 185 | JsonObject &color = root.createNestedObject("color"); 186 | color["r"] = red; 187 | color["g"] = green; 188 | color["b"] = blue; 189 | 190 | root["brightness"] = brightness; 191 | root["speed"] = speed; 192 | root["effect"] = effect.c_str(); 193 | 194 | char buffer[root.measureLength() + 1]; 195 | root.printTo(buffer, sizeof(buffer)); 196 | 197 | char combinedArray[sizeof(MQTT_STATE_TOPIC_PREFIX) + sizeof(deviceName)]; 198 | sprintf(combinedArray, "%s%s", MQTT_STATE_TOPIC_PREFIX, deviceName); // with word space 199 | client.publish(combinedArray, buffer, true); 200 | } 201 | 202 | bool processJson(char *message) { 203 | StaticJsonBuffer jsonBuffer; 204 | 205 | JsonObject &root = jsonBuffer.parseObject(message); 206 | 207 | if (!root.success()) { 208 | Serial.println("parseObject() failed"); 209 | return false; 210 | } 211 | 212 | if (root.containsKey("state")) { 213 | if (strcmp(root["state"], on_cmd) == 0) { 214 | stateOn = true; 215 | if (!ws2812fx.isRunning()) 216 | ws2812fx.start(); 217 | } else if (strcmp(root["state"], off_cmd) == 0) { 218 | stateOn = false; 219 | ws2812fx.stop(); 220 | } else { 221 | sendState(); 222 | return false; 223 | } 224 | } 225 | 226 | if (root.containsKey("color")) { 227 | red = root["color"]["r"]; 228 | green = root["color"]["g"]; 229 | blue = root["color"]["b"]; 230 | ws2812fx.setColor(rgbToHex(red, green, blue)); 231 | } 232 | 233 | if (root.containsKey("brightness")) { 234 | brightness = root["brightness"]; 235 | ws2812fx.setBrightness(brightness); 236 | } 237 | 238 | if (root.containsKey("effect")) { 239 | effectString = root["effect"]; 240 | effect = effectString; 241 | setEffect(effectString); 242 | } 243 | 244 | if (root.containsKey("speed")) { 245 | speed = root["speed"]; 246 | ws2812fx.setSpeed(speed * 100); 247 | } 248 | 249 | return true; 250 | } 251 | 252 | void callback(char *topic, byte *payload, unsigned int length) { 253 | Serial.println(""); 254 | Serial.print("Message arrived ["); 255 | Serial.print(topic); 256 | Serial.print("] "); 257 | 258 | char message[length + 1]; 259 | for (int i = 0; i < length; i++) { 260 | message[i] = (char)payload[i]; 261 | } 262 | message[length] = '\0'; 263 | Serial.println(message); 264 | 265 | if (!processJson(message)) 266 | return; 267 | 268 | sendState(); 269 | } 270 | 271 | void reconnect() { 272 | // Loop until we're reconnected 273 | while (!client.connected()) { 274 | Serial.print("Attempting MQTT connection..."); 275 | // Attempt to connect 276 | char combinedArray[sizeof(MQTT_STATE_TOPIC_PREFIX) + sizeof(deviceName) + 4]; 277 | sprintf(combinedArray, "%s%s/LWT", MQTT_STATE_TOPIC_PREFIX, deviceName); 278 | if (client.connect(deviceName, MQTT_USER, MQTT_PASSWORD, combinedArray, 2, 1, will_msg)) { 279 | Serial.println("connected"); 280 | 281 | client.publish(combinedArray, online_msg, 1); // Send last will message 282 | 283 | sprintf(combinedArray, "%s%s/set", MQTT_STATE_TOPIC_PREFIX, deviceName); 284 | client.subscribe(combinedArray); 285 | 286 | sendState(); 287 | } else { 288 | Serial.print("failed, rc="); 289 | Serial.print(client.state()); 290 | Serial.println(" try again in 5 seconds"); 291 | // Wait 5 seconds before retrying 292 | delay(5000); 293 | } 294 | } 295 | } 296 | 297 | void setup() { 298 | pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output (So it doesnt float as a LED is on this pin) 299 | digitalWrite(LED_BUILTIN, LOW); // Turn the status LED on 300 | 301 | Serial.begin(115200); 302 | 303 | delay(500); // Wait for Leds to init and Cap to charge 304 | 305 | // End of trinket special code 306 | ws2812fx.init(); 307 | ws2812fx.setBrightness(brightness); 308 | ws2812fx.setColor(rgbToHex(red, green, blue)); 309 | ws2812fx.setSpeed(speed * 100); 310 | #ifdef DEFAULT_EFFECT 311 | ws2812fx.setMode(DEFAULT_EFFECT); 312 | #endif 313 | #if DEFAULT_POWER_ON_STATE 314 | ws2812fx.start(); 315 | stateOn = true; 316 | #endif 317 | 318 | setup_wifi(); 319 | 320 | client.setServer(MQTT_SERVER, MQTT_PORT); 321 | client.setCallback(callback); 322 | 323 | //OTA SETUP 324 | ArduinoOTA.setPort(OTAport); 325 | ArduinoOTA.setHostname(deviceName); // Hostname defaults to esp8266-[ChipID] 326 | ArduinoOTA.setPassword((const char *)OTApassword); // No authentication by default 327 | 328 | ArduinoOTA.onStart([]() { Serial.println("Starting"); }); 329 | ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); 330 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 331 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 332 | }); 333 | ArduinoOTA.onError([](ota_error_t error) { 334 | Serial.print("Error[%u]: " + error); 335 | if (error == OTA_AUTH_ERROR) 336 | Serial.println("Auth Failed"); 337 | else if (error == OTA_BEGIN_ERROR) 338 | Serial.println("Begin Failed"); 339 | else if (error == OTA_CONNECT_ERROR) 340 | Serial.println("Connect Failed"); 341 | else if (error == OTA_RECEIVE_ERROR) 342 | Serial.println("Receive Failed"); 343 | else if (error == OTA_END_ERROR) 344 | Serial.println("End Failed"); 345 | }); 346 | ArduinoOTA.begin(); 347 | 348 | Serial.println("Ready"); 349 | 350 | // OK we are connected 351 | digitalWrite(LED_BUILTIN, HIGH); // Turn the status LED off 352 | } 353 | 354 | void loop() { 355 | if (!client.connected()) { 356 | reconnect(); 357 | } 358 | 359 | if (WiFi.status() != WL_CONNECTED) { 360 | delay(1); 361 | Serial.print("WIFI Disconnected. Attempting reconnection."); 362 | setup_wifi(); 363 | return; 364 | } 365 | 366 | client.loop(); // Check MQTT 367 | 368 | ArduinoOTA.handle(); // Check OTA Firmware Updates 369 | 370 | ws2812fx.service(); 371 | } 372 | -------------------------------------------------------------------------------- /diagrams/neopixel_strip_string_ws2811_5v_psu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | +5V 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | GND 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | GND 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | +5V 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | Din 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | Dout 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | +5V 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | GND 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | GND 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | +5V 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | Din 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | Dout 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | breadboard 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | D0 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | D1 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | D2 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | D3 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | D4 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 3V3 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | GND 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | D5 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | D6 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | D7 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | D8 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | RX 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | TX 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | GND 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 3V3 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | Vin 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | GND 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | RST 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | EN 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 3V3 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | GND 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | CLK 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | SD0 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | CMD 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | SD1 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | SD2 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | SD3 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | RSV 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | RSV 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | A0 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 1590 | 1591 | 1592 | 1593 | 1594 | FLASH 1595 | 1596 | 1597 | 1598 | 1599 | 1600 | 1601 | 1602 | 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1621 | RST 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1660 | 1661 | 1662 | 1663 | 1664 | 1665 | 1666 | 1667 | 1668 | NodeMCU 1669 | V1.0 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1687 | 1688 | 1689 | 1690 | 1691 | 1692 | 1693 | 1694 | 1695 | 1696 | 1697 | blog.squix.ch 1698 | 1699 | 1700 | 1701 | 1702 | 1703 | 1704 | 1705 | 1706 | 1707 | 1708 | 1709 | 1710 | 1711 | 1712 | --------------------------------------------------------------------------------