├── .gitignore ├── .readthedocs.yaml ├── AUTHORS.rst ├── CONTRIBUTING.rst ├── HISTORY.rst ├── LICENSE ├── Makefile ├── README.rst └── docs ├── .gitignore ├── Makefile ├── _static └── .keep ├── authors.rst ├── bt_api.rst ├── conf.py ├── contributing.rst ├── firmware.rst ├── hardware.rst ├── history.rst ├── index.rst ├── make.bat ├── mqtt_api.rst ├── protocol_details.rst ├── readme.rst ├── requirements.in ├── requirements.txt └── rest_api.rst /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | # pyenv python configuration file 62 | .python-version 63 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # .readthedocs.yaml 3 | # Read the Docs configuration file 4 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 5 | 6 | # Required 7 | version: 2 8 | 9 | # Set the version of Python and other tools you might need 10 | build: 11 | os: ubuntu-22.04 12 | tools: 13 | python: "3.11" 14 | 15 | # Build documentation in the docs/ directory with Sphinx 16 | sphinx: 17 | configuration: docs/conf.py 18 | 19 | python: 20 | install: 21 | - requirements: docs/requirements.txt 22 | -------------------------------------------------------------------------------- /AUTHORS.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Credits 3 | ======= 4 | 5 | Development Lead 6 | ---------------- 7 | 8 | * Pavol Babinčák 9 | 10 | Contributors 11 | ------------ 12 | 13 | * Paul Webster (@PaulWebster) 14 | * Artem Ignatyev (@timon) 15 | * Anders Holst (@Anders-Holst) 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: shell 2 | 3 | ============ 4 | Contributing 5 | ============ 6 | 7 | Contributions are welcome, and they are greatly appreciated! Every 8 | little bit helps, and credit will always be given. 9 | 10 | You can contribute in many ways: 11 | 12 | Types of Contributions 13 | ---------------------- 14 | 15 | Report Bugs 16 | ~~~~~~~~~~~ 17 | 18 | Report bugs at https://github.com/scrool/xled-docs/issues. 19 | 20 | If you are reporting a bug, please include: 21 | 22 | * Your operating system name and version. 23 | * Any details about your local setup that might be helpful in troubleshooting. 24 | * Detailed steps to reproduce the bug. 25 | 26 | Fix Bugs 27 | ~~~~~~~~ 28 | 29 | Look through the GitHub issues for bugs. Anything tagged with "bug" 30 | and "help wanted" is open to whoever wants to implement it. 31 | 32 | Implement Features 33 | ~~~~~~~~~~~~~~~~~~ 34 | 35 | Look through the GitHub issues for features. Anything tagged with "enhancement" 36 | and "help wanted" is open to whoever wants to implement it. 37 | 38 | Write Documentation 39 | ~~~~~~~~~~~~~~~~~~~ 40 | 41 | xled could always use more documentation, whether as part of the 42 | official xled docs or even on the web in blog posts, articles, and such. 43 | 44 | Submit Feedback 45 | ~~~~~~~~~~~~~~~ 46 | 47 | The best way to send feedback is to file an issue at https://github.com/scrool/xled-docs/issues. 48 | 49 | If you are proposing a feature: 50 | 51 | * Explain in detail how it would work. 52 | * Keep the scope as narrow as possible, to make it easier to implement. 53 | * Remember that this is a volunteer-driven project, and that contributions 54 | are welcome :) 55 | -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | History 3 | ======= 4 | 5 | 2.4.21.2 (2020-12-22) 6 | ----------------------- 7 | 8 | * Add new REST API endpoints Get and set LED config 9 | * Add new REST endpoints: get LED effects and current LED effects 10 | * Improve application response description and add 1205 11 | * More consistent info about first firmware supporting MQTT 12 | * Document response 404 Not found 13 | * Specify initial firmware versions for all REST API endpoints 14 | * Move Logout earlier in the list of rest APIs 15 | * Rename section Change LED operation mode -> Set LED operation mode 16 | * Fix typos 17 | * Shorten main headings 18 | * Restructure rest api 19 | 20 | 2.4.21.1 (2020-12-07) 21 | ----------------------- 22 | 23 | * Use tab for indentation consistently 24 | * Add corresponding GET calls and one more example 25 | * Rename firmware 2.0.22-mqtt to 2.0.22. 26 | 27 | 2.4.21.0 (2020-12-07) 28 | ----------------------- 29 | 30 | * Introduce generation II and improve introduction 31 | 32 | 2.3.5.0 (2020-12-03) 33 | ----------------------- 34 | 35 | * Brightness can be set and read through MQTT 36 | * Fix typo in filename: msqtt_api.rst -> mqtt_api.rst 37 | * Brightness is available since firmware 2.3.5 38 | * Remove Cookiecutter_credits - it wasn't used in this project 39 | * Brightness is most likely percent so improve its description 40 | * Improve LED brightness REST endpoint 41 | * Contribute myself to the list of authors 42 | * Describe led brightness REST endpoint 43 | 44 | 2.1.0.2 (2018-12-15) 45 | ----------------------- 46 | 47 | * gestalt returns rssi 48 | 49 | 2.1.0.1 (2018-12-09) 50 | ----------------------- 51 | 52 | * Updated MQTT status API in new firmware 53 | 54 | 2.0.22.1 (2018-12-05) 55 | ----------------------- 56 | 57 | * Initial description on MQTT API 58 | 59 | 1.99.24.11 (2018-11-27) 60 | ----------------------- 61 | 62 | * Fix links in README 63 | 64 | 1.99.24.10 (2018-11-27) 65 | ----------------------- 66 | 67 | * New return value - 1104 68 | 69 | 1.99.24.9 (2018-11-21) 70 | ---------------------- 71 | * Describe private API for uploading movies. 72 | 73 | 1.99.24.8 (2018-11-18) 74 | ---------------------- 75 | * Fix typos. 76 | * Fix formatting. 77 | * In private API repeat warning about private API. 78 | * Remove uncertainty about real time mode. 79 | 80 | 1.99.24.7 (2018-11-12) 81 | ---------------------- 82 | * Minor formatting improvements. 83 | 84 | 1.99.24.6 (2018-01-02) 85 | ---------------------- 86 | * Protocol details about realtime and full movie upload LED modes. 87 | 88 | 1.99.24.5 (2018-01-02) 89 | ---------------------- 90 | * Improve documentation for contributors. 91 | 92 | 1.99.24.4 (2017-12-17) 93 | ---------------------- 94 | * First public documentation for private API. 95 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2017, Pavol Babinčák 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 | 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: docs help 2 | .DEFAULT_GOAL := help 3 | help: 4 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 5 | 6 | docs: ## generate Sphinx HTML documentation, including API docs 7 | $(MAKE) -C docs clean 8 | $(MAKE) -C docs html 9 | @echo -e "\033[95m\n\nBuild successful! View the docs homepage at docs/_build/html/index.html.\n\033[0m" 10 | 11 | servedocs: docs ## compile the docs watching for changes 12 | watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . 13 | 14 | requirements: ## generate Sphinx HTML documentation, including API docs 15 | $(MAKE) -C docs requirements.txt 16 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ========================== 2 | Smart LED Christmas lights 3 | ========================== 4 | 5 | `Unofficial documentation`_ of :ref:`API reference `, protocol 6 | details and hardware of `Twinkly`_ - Smart Decoration LED lights for Christmas. 7 | 8 | Official materials says: 9 | 10 | Twinkly is a LED light device that you can control via smartphone. It 11 | allows you to play with colouful and animated effects, or create new ones. 12 | Decoration lights, not suitable for household illumination. 13 | 14 | Since its `Kickstarter project`_ in 2016 many products were introduced with 15 | varying properties and features. Most notably products released since September 16 | 2019 are identified as Generation II. Older products are since then referred as 17 | Generation I. Documentation has been created and tested only on some 18 | :ref:`hardware `. 19 | 20 | Products could be further groupped by families for which firmware is released. 21 | Firmware on devices can be upgraded and sometimes new features are introduced. 22 | Documentation has been created for some of these :ref:`firmwares `. 23 | 24 | Why? 25 | ---- 26 | 27 | My first Twinkly was 105 LEDs starter light set. That was the latest available 28 | model in 2017: TW105S-EU. As of December 2017 there are only two ways to 29 | control lights: mobile app on Android or iOS or hardware button on the cord. 30 | 31 | Android application didn't work as advertised on my Xiaomi Redmi 3S phone. On 32 | first start it connected and disconnected in very fast pace (like every 1-2 33 | seconds) to the hardware. I wasn't able to control anything at all. Later I 34 | wanted to connect it to my local WiFi network. But popup dialog that shouldn't 35 | have appear never did so. 36 | 37 | Public API was `promised around Christmas 2016`_ for next season. Later update 38 | from October 2016 it seems `API won't be available any time soon`_: 39 | 40 | API for external control are on our dev check list, we definitely need some 41 | feedback from the community to understand which could be a proper core set 42 | to start with. 43 | 44 | It turned out that application uses HTTP to control lights. I ended up with 45 | capturing network traffic and documented this private API. In the end I'm able 46 | to configure the device pretty easilly. 47 | 48 | As of 2020 Twinkly devices can be controlled by Amazon Alexa and Google 49 | Assistant as well. Mobile application now requires an account to operate lights 50 | even locally. No sign of public API for local devices though. Therefore with my 51 | second device - Twinkly 210 RGB+W Wall I keep updating this documentation to be 52 | able to operate my devices locally and not rely on availability of 53 | manufacturer's servers. 54 | 55 | License 56 | ------- 57 | 58 | Documentation is available under MIT license. 59 | 60 | Client implementations 61 | ---------------------- 62 | 63 | There are multiple clients, libraries or just small projects that can be used 64 | to control Twinkly devices: 65 | 66 | * `xled`_ - python library and command line interface 67 | * `xled_plus`_ - Addons to the XLED package, to create nice effects for Twinkly LED lights 68 | * `Twinkly integration in Home Assistant`_ 69 | * SmartThings: 70 | 71 | * `Twinkly integration in SmartThings by StevenJonSmith`_ 72 | * `Twinkly integration in SmartThings by Dameon87`_ 73 | 74 | * `TwinklyTree Binding`_ for openHAB 75 | * `Twinkly HomeKit Hub for Mongoose OS`_ using `Twinkly library for Mongoose OS`_ 76 | * `homebridge-twinkly` - unofficial Homebridge plugin 77 | * `TwinklyWPF`_ - .net 5 GUI and API library 78 | * `ioBroker.twinkly`_ - twinkly adapter for ioBroker to communicate with the Twinkly lights 79 | * `Twinkly Twinkly Little Star` - ttls helps you to make async requests to Twinkly LEDs. Includes CLI and some examples how to create both loadable movies and realtime sequences. 80 | * `Twinkly.vb for HomeSeer`_ 81 | * `bpx`_ - BiblioPixel driver for the xled library 82 | * `thingzi-logic-twinkly`_ - Twinkly lights integration for node red 83 | * `twinkly-animator`_ - Drawing and animation tools for Twinkly LED lights 84 | * Python class to interact with generation I device and IDA Pro loader of firmware binary in `Twinkly Twinkly Little Star by F-Secure LABS`_. 85 | * `Artnet 2 Twinkly`_ - interface XLights to Twinkly on a PC. Partially emulates and artnet controller, and even hooks into Twinkly's web api to allow manual layout editing. 86 | 87 | Communities 88 | ----------- 89 | 90 | There are multiple places where you can connect with others who are interested 91 | in Twinkly devices: 92 | 93 | * `Twinkly (unofficial users group) on Facebook`_ to share your installations, show your creations, ask questions, post some hacks. Anything Twinkly related goes. 94 | * `Discussions on GitHub in xled_plus project`_ with daily effects. 95 | * `Gitter chat xled-community`_ of `xled` project. Fairly small and quiet. 96 | 97 | .. _`Twinkly`: https://www.twinkly.com/ 98 | .. _`Unofficial documentation`: https://xled-docs.readthedocs.io/ 99 | .. _`Kickstarter project`: https://www.kickstarter.com/projects/twinkly/twinkly-smart-decoration-for-your-christmas 100 | .. _`promised around Christmas 2016`: https://www.kickstarter.com/projects/twinkly/twinkly-smart-decoration-for-your-christmas/comments?cursor=15497325#comment-15497324 101 | .. _`API won't be available any time soon`: https://www.kickstarter.com/projects/twinkly/twinkly-smart-decoration-for-your-christmas/comments?cursor=14619713#comment-14619712 102 | .. _`xled`: https://pypi.org/project/xled/ 103 | .. _`xled_plus`: https://pypi.org/project/xled-plus/ 104 | .. _`Twinkly integration in Home Assistant`: https://www.home-assistant.io/integrations/twinkly/ 105 | .. _`Twinkly integration in SmartThings by StevenJonSmith`: https://github.com/StevenJonSmith/SmartThings 106 | .. _`Twinkly integration in SmartThings by Dameon87`: https://github.com/Dameon87/SmartThings 107 | .. _`TwinklyTree Binding`: https://github.com/mvanhulsentop/openhab-addons/tree/twinklytree/bundles/org.openhab.binding.twinklytree 108 | .. _`Twinkly library for Mongoose OS`: https://github.com/d4rkmen/twinkly 109 | .. _`Twinkly HomeKit Hub for Mongoose OS`: https://github.com/d4rkmen/twinkly-homekit 110 | .. _`homebridge-twinkly`: https://github.com/nschum/homebridge-twinkly 111 | .. _`TwinklyWPF`: https://github.com/MarkAlanJones/TwinklyWPF 112 | .. _`ioBroker.twinkly`: https://www.npmjs.com/package/iobroker.twinkly 113 | .. _`Twinkly Twinkly Little Star`: https://github.com/jschlyter/ttls 114 | .. _`Twinkly.vb for HomeSeer`: https://forums.homeseer.com/forum/developer-support/scripts-plug-ins-development-and-libraries/script-plug-in-library/1348314-twinkly-vb-christmas-tree-lights-with-predefined-and-custom-animations 115 | .. _`bpx`: https://github.com/rec/bpx 116 | .. _`thingzi-logic-twinkly`: https://www.npmjs.com/package/thingzi-logic-twinkly 117 | .. _`twinkly-animator`: https://github.com/sluggoman/twinkly-animator 118 | .. _`Twinkly Twinkly Little Star by F-Secure LABS`: https://labs.f-secure.com/blog/twinkly-twinkly-little-star/ 119 | .. _`Gitter chat xled-community`: https://gitter.im/xled-community/chat 120 | .. _`Discussions on GitHub in xled_plus project`: https://github.com/Anders-Holst/xled_plus/discussions 121 | .. _`Twinkly (unofficial users group) on Facebook`: https://www.facebook.com/groups/twinklyusergroup 122 | .. _`Artnet 2 Twinkly`: http://www.artnet2twinkly.com/ 123 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xled/xled-docs/6e88f64e382245a2aef3b9468f81c6707b2035b9/docs/.gitignore -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/xled.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/xled.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/xled" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/xled" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | 179 | requirements.txt: requirements.in 180 | pip-compile -o "$@" "$<" 181 | -------------------------------------------------------------------------------- /docs/_static/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xled/xled-docs/6e88f64e382245a2aef3b9468f81c6707b2035b9/docs/_static/.keep -------------------------------------------------------------------------------- /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../AUTHORS.rst 2 | -------------------------------------------------------------------------------- /docs/bt_api.rst: -------------------------------------------------------------------------------- 1 | Bluetooth API reference 2 | ======================= 3 | 4 | Overview 5 | -------- 6 | 7 | Generation II devices have Bluetooth LE module that can be used to configure 8 | WiFi network. User documentation how to `configure Twinkly generation II for 9 | the first time`_ can be found on the manufacturer's site. 10 | 11 | Protocol is based on `Espressif BluFi`_ solution with couple of differences 12 | described here. 13 | 14 | Device doesn't require data encryption nor it use data checksum. 15 | 16 | Device broadcasts its Device ID (see Protocol Details). Bluetooth adapter has 17 | MAC address that differs in right most byte from WiFi MAC address. 18 | 19 | GATT information 20 | ---------------- 21 | 22 | The most interesting handles are: 23 | 24 | - 0x2a for writing (client -> device) 25 | - 0x2c for reading and notification (device -> client): 26 | 27 | +--------------+-------------------------------------------+--------------+----------------+ 28 | | Handles | Service > Characteristics | Properties | Data | 29 | +==============+====+======================================+==============+================+ 30 | | 0001 -> 0005 | Generic Attribute (1801) | | | 31 | +--------------+----+--------------------------------------+--------------+----------------+ 32 | | 0003 | | Service Changed (2a05) | INDICATE | | 33 | +--------------+----+--------------------------------------+--------------+----------------+ 34 | | 0014 -> 001c | Generic Access (1800) | | | 35 | +--------------+----+--------------------------------------+--------------+----------------+ 36 | | 0016 | | Device Name (2a00) | READ | Twinkly_1CC190 | 37 | +--------------+----+--------------------------------------+--------------+----------------+ 38 | | 0018 | | Appearance (2a01) | READ | Unknown | 39 | +--------------+----+--------------------------------------+--------------+----------------+ 40 | | 001a | | 2aa6 | READ | 00 | 41 | +--------------+----+--------------------------------------+--------------+----------------+ 42 | | 0028 -> ffff | 68cac066-1f6e-0f96-1146-da9d00fa7b1b | | | 43 | +--------------+----+--------------------------------------+--------------+----------------+ 44 | | 002a | | 68cac066-1f6e-0f96-1146-da9d01fa7b1b | WRITE | | 45 | +--------------+----+--------------------------------------+--------------+----------------+ 46 | | 002c | | 68cac066-1f6e-0f96-1146-da9d02fa7b1b | READ, NOTIFY | 00 | 47 | +--------------+----+--------------------------------------+--------------+----------------+ 48 | 49 | Control frames 50 | -------------- 51 | 52 | Connect the device to the AP 53 | ```````````````````````````` 54 | 55 | LSB - Type: `0x0c` 56 | 57 | WiFi mode and its status 58 | ```````````````````````` 59 | 60 | LSB - Type: `0x14` 61 | 62 | Example 63 | 64 | .. code-block:: text 65 | 66 | 14 00 00 00 67 | 68 | Set the opmode of WiFi 69 | ``````````````````````` 70 | 71 | LSB - Type: `0x1d` 72 | 73 | Example in AP workflow 74 | 75 | .. code-block:: text 76 | 77 | 1d 00 00 02 04 00 78 | 79 | Example in STA workflow 80 | 81 | .. code-block:: text 82 | 83 | 1d 00 00 01 00 84 | 85 | Disconnect the BLE GATT link 86 | ```````````````````````````` 87 | 88 | LSB - Type: `0x20` 89 | 90 | WiFi List 91 | `````````` 92 | 93 | LSB - Type: `0x24` 94 | 95 | Example 96 | 97 | .. code-block:: text 98 | 99 | 24 00 00 00 100 | 101 | Data frames 102 | ----------- 103 | 104 | Unknown use 105 | ``````````` 106 | 107 | LSB - Type: `0x08` 108 | 109 | Example 110 | 111 | .. code-block:: text 112 | 113 | 08 08 00 02 01 00 114 | 115 | Send the SSID for STA mode 116 | `````````````````````````` 117 | 118 | LSB - Type: `0x09` 119 | 120 | Send the password for STA mode 121 | `````````````````````````````` 122 | 123 | LSB - Type: `0x0d` 124 | 125 | .. _`Espressif BluFi`: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/blufi.html 126 | .. _`configure Twinkly generation II for the first time`: https://web.archive.org/web/2/https://www.twinkly.com/knowledge/configure-twinkly-generation-ii-for-the-first-time/ 127 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # xled documentation build configuration file, created by 5 | # sphinx-quickstart on Tue Jul 9 22:26:36 2013. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import sys 17 | import os 18 | 19 | # If extensions (or modules to document with autodoc) are in another 20 | # directory, add these directories to sys.path here. If the directory is 21 | # relative to the documentation root, use os.path.abspath to make it 22 | # absolute, like shown here. 23 | #sys.path.insert(0, os.path.abspath('.')) 24 | 25 | # Get the project root dir, which is the parent dir of this 26 | cwd = os.getcwd() 27 | project_root = os.path.dirname(cwd) 28 | 29 | # Insert the project root dir as the first element in the PYTHONPATH. 30 | # This lets us ensure that the source package is imported, and that its 31 | # version is used. 32 | sys.path.insert(0, project_root) 33 | 34 | # -- General configuration --------------------------------------------- 35 | 36 | # If your documentation needs a minimal Sphinx version, state it here. 37 | #needs_sphinx = '1.0' 38 | 39 | # Add any Sphinx extension module names here, as strings. They can be 40 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 41 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx_rtd_theme'] 42 | 43 | # Add any paths that contain templates here, relative to this directory. 44 | templates_path = ['_templates'] 45 | 46 | # The suffix of source filenames. 47 | source_suffix = '.rst' 48 | 49 | # The encoding of source files. 50 | #source_encoding = 'utf-8-sig' 51 | 52 | # The master toctree document. 53 | master_doc = 'index' 54 | 55 | # General information about the project. 56 | project = u'Smart LED Christmas lights' 57 | copyright = u"2017, Pavol Babinčák" 58 | 59 | # The version info for the project you're documenting, acts as replacement 60 | # for |version| and |release|, also used in various other places throughout 61 | # the built documents. 62 | # 63 | # The short X.Y version. 64 | version = '2.4.21.2' 65 | # The full version, including alpha/beta/rc tags. 66 | release = version 67 | 68 | # The language for content autogenerated by Sphinx. Refer to documentation 69 | # for a list of supported languages. 70 | #language = None 71 | 72 | # There are two options for replacing |today|: either, you set today to 73 | # some non-false value, then it is used: 74 | #today = '' 75 | # Else, today_fmt is used as the format for a strftime call. 76 | #today_fmt = '%B %d, %Y' 77 | 78 | # List of patterns, relative to source directory, that match files and 79 | # directories to ignore when looking for source files. 80 | exclude_patterns = ['_build'] 81 | 82 | # The reST default role (used for this markup: `text`) to use for all 83 | # documents. 84 | #default_role = None 85 | 86 | # If true, '()' will be appended to :func: etc. cross-reference text. 87 | #add_function_parentheses = True 88 | 89 | # If true, the current module name will be prepended to all description 90 | # unit titles (such as .. function::). 91 | #add_module_names = True 92 | 93 | # If true, sectionauthor and moduleauthor directives will be shown in the 94 | # output. They are ignored by default. 95 | #show_authors = False 96 | 97 | # The name of the Pygments (syntax highlighting) style to use. 98 | pygments_style = 'sphinx' 99 | 100 | # A list of ignored prefixes for module index sorting. 101 | #modindex_common_prefix = [] 102 | 103 | # If true, keep warnings as "system message" paragraphs in the built 104 | # documents. 105 | #keep_warnings = False 106 | 107 | 108 | # -- Options for HTML output ------------------------------------------- 109 | 110 | # The theme to use for HTML and HTML Help pages. See the documentation for 111 | # a list of builtin themes. 112 | html_theme = 'sphinx_rtd_theme' 113 | 114 | # Theme options are theme-specific and customize the look and feel of a 115 | # theme further. For a list of options available for each theme, see the 116 | # documentation. 117 | #html_theme_options = {} 118 | 119 | # Add any paths that contain custom themes here, relative to this directory. 120 | #html_theme_path = [] 121 | 122 | # The name for this set of Sphinx documents. If None, it defaults to 123 | # " v documentation". 124 | #html_title = None 125 | 126 | # A shorter title for the navigation bar. Default is the same as 127 | # html_title. 128 | #html_short_title = None 129 | 130 | # The name of an image file (relative to this directory) to place at the 131 | # top of the sidebar. 132 | #html_logo = None 133 | 134 | # The name of an image file (within the static path) to use as favicon 135 | # of the docs. This file should be a Windows icon file (.ico) being 136 | # 16x16 or 32x32 pixels large. 137 | #html_favicon = None 138 | 139 | # Add any paths that contain custom static files (such as style sheets) 140 | # here, relative to this directory. They are copied after the builtin 141 | # static files, so a file named "default.css" will overwrite the builtin 142 | # "default.css". 143 | html_static_path = ['_static'] 144 | 145 | # If not '', a 'Last updated on:' timestamp is inserted at every page 146 | # bottom, using the given strftime format. 147 | #html_last_updated_fmt = '%b %d, %Y' 148 | 149 | # If true, SmartyPants will be used to convert quotes and dashes to 150 | # typographically correct entities. 151 | #html_use_smartypants = True 152 | 153 | # Custom sidebar templates, maps document names to template names. 154 | #html_sidebars = {} 155 | 156 | # Additional templates that should be rendered to pages, maps page names 157 | # to template names. 158 | #html_additional_pages = {} 159 | 160 | # If false, no module index is generated. 161 | #html_domain_indices = True 162 | 163 | # If false, no index is generated. 164 | #html_use_index = True 165 | 166 | # If true, the index is split into individual pages for each letter. 167 | #html_split_index = False 168 | 169 | # If true, links to the reST sources are added to the pages. 170 | #html_show_sourcelink = True 171 | 172 | # If true, "Created using Sphinx" is shown in the HTML footer. 173 | # Default is True. 174 | #html_show_sphinx = True 175 | 176 | # If true, "(C) Copyright ..." is shown in the HTML footer. 177 | # Default is True. 178 | #html_show_copyright = True 179 | 180 | # If true, an OpenSearch description file will be output, and all pages 181 | # will contain a tag referring to it. The value of this option 182 | # must be the base URL from which the finished HTML is served. 183 | #html_use_opensearch = '' 184 | 185 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 186 | #html_file_suffix = None 187 | 188 | # Output file base name for HTML help builder. 189 | htmlhelp_basename = 'xleddoc' 190 | 191 | 192 | # -- Options for LaTeX output ------------------------------------------ 193 | 194 | latex_elements = { 195 | # The paper size ('letterpaper' or 'a4paper'). 196 | #'papersize': 'letterpaper', 197 | 198 | # The font size ('10pt', '11pt' or '12pt'). 199 | #'pointsize': '10pt', 200 | 201 | # Additional stuff for the LaTeX preamble. 202 | #'preamble': '', 203 | } 204 | 205 | # Grouping the document tree into LaTeX files. List of tuples 206 | # (source start file, target name, title, author, documentclass 207 | # [howto/manual]). 208 | latex_documents = [ 209 | ('index', 'xled.tex', 210 | u'Smart LED Christmas lights Documentation', 211 | u'Pavol Babinčák', 'manual'), 212 | ] 213 | 214 | # The name of an image file (relative to this directory) to place at 215 | # the top of the title page. 216 | #latex_logo = None 217 | 218 | # For "manual" documents, if this is true, then toplevel headings 219 | # are parts, not chapters. 220 | #latex_use_parts = False 221 | 222 | # If true, show page references after internal links. 223 | #latex_show_pagerefs = False 224 | 225 | # If true, show URL addresses after external links. 226 | #latex_show_urls = False 227 | 228 | # Documents to append as an appendix to all manuals. 229 | #latex_appendices = [] 230 | 231 | # If false, no module index is generated. 232 | #latex_domain_indices = True 233 | 234 | 235 | # -- Options for manual page output ------------------------------------ 236 | 237 | # One entry per manual page. List of tuples 238 | # (source start file, name, description, authors, manual section). 239 | man_pages = [ 240 | ('index', 'xled', 241 | u'Smart LED Christmas lights Documentation', 242 | [u'Pavol Babinčák'], 1) 243 | ] 244 | 245 | # If true, show URL addresses after external links. 246 | #man_show_urls = False 247 | 248 | 249 | # -- Options for Texinfo output ---------------------------------------- 250 | 251 | # Grouping the document tree into Texinfo files. List of tuples 252 | # (source start file, target name, title, author, 253 | # dir menu entry, description, category) 254 | texinfo_documents = [ 255 | ('index', 'xled', 256 | u'Smart LED Christmas lights Documentation', 257 | u'Pavol Babinčák', 258 | 'xled', 259 | 'One line description of project.', 260 | 'Miscellaneous'), 261 | ] 262 | 263 | # Documents to append as an appendix to all manuals. 264 | #texinfo_appendices = [] 265 | 266 | # If false, no module index is generated. 267 | #texinfo_domain_indices = True 268 | 269 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 270 | #texinfo_show_urls = 'footnote' 271 | 272 | # If true, do not generate a @detailmenu in the "Top" node's menu. 273 | #texinfo_no_detailmenu = False 274 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /docs/firmware.rst: -------------------------------------------------------------------------------- 1 | .. _firmware: 2 | 3 | Firmware 4 | ======== 5 | 6 | This page desribes firmware that this documentation has been tested with. 7 | Firmware can be upgraded over the network. 8 | 9 | Generation I 10 | ------------ 11 | 12 | Firmware family "D" 13 | ``````````````````` 14 | 15 | Firmware consists of two files. I have seen following versions: 16 | 17 | +-------------+-----------------------------------------------------------------------------------------+ 18 | | Version | Notes | 19 | +=============+=========================================================================================+ 20 | | 1.99.18 | Probably first public version | 21 | +-------------+-----------------------------------------------------------------------------------------+ 22 | | 1.99.20 | | 23 | +-------------+-----------------------------------------------------------------------------------------+ 24 | | 1.99.24 | | 25 | +-------------+-----------------------------------------------------------------------------------------+ 26 | | 1.99.30 | | 27 | +-------------+-----------------------------------------------------------------------------------------+ 28 | | 2.0.0 | | 29 | +-------------+-----------------------------------------------------------------------------------------+ 30 | | 2.0.8 | | 31 | +-------------+-----------------------------------------------------------------------------------------+ 32 | | 2.0.12 | | 33 | +-------------+-----------------------------------------------------------------------------------------+ 34 | | 2.0.13 | | 35 | +-------------+-----------------------------------------------------------------------------------------+ 36 | | 2.0.19 | | 37 | +-------------+-----------------------------------------------------------------------------------------+ 38 | | 2.0.22-mqtt | Adds MQTT support | 39 | +-------------+-----------------------------------------------------------------------------------------+ 40 | | 2.1.0 | | 41 | +-------------+-----------------------------------------------------------------------------------------+ 42 | | 2.1.1-net | | 43 | +-------------+-----------------------------------------------------------------------------------------+ 44 | | 2.1.2-net | | 45 | +-------------+-----------------------------------------------------------------------------------------+ 46 | | 2.3.5 | Last version offered by application for upgrade | 47 | +-------------+-----------------------------------------------------------------------------------------+ 48 | | 2.3.8 | | 49 | +-------------+-----------------------------------------------------------------------------------------+ 50 | 51 | Generation II 52 | ------------- 53 | 54 | Firmware file is `encrypted using host generated key`_. 55 | 56 | I have seen following versions: 57 | 58 | +---------+------------+------------+---------------------------------------------------------------------+ 59 | | Version | Available for Family | Notes | 60 | | +------------+------------+ | 61 | | | "F" | "G" | | 62 | +=========+============+============+=====================================================================+ 63 | | 2.2.1 | Yes | | Shipped with family "F" device in 2020, maybe first public version? | 64 | +---------+------------+------------+---------------------------------------------------------------------+ 65 | | 2.2.2 | Yes | | | 66 | +---------+------------+------------+---------------------------------------------------------------------+ 67 | | 2.4.2 | Yes | | Adds MQTT and brightness support | 68 | +---------+------------+------------+---------------------------------------------------------------------+ 69 | | 2.4.6 | Yes | | Seems to incorrectly report `frame_rate: 1` in `gestalt` API call | 70 | +---------+------------+------------+---------------------------------------------------------------------+ 71 | | 2.4.14 | Yes | | | 72 | +---------+------------+------------+---------------------------------------------------------------------+ 73 | | 2.4.16 | Yes | | | 74 | +---------+------------+------------+---------------------------------------------------------------------+ 75 | | 2.4.21 | Yes | Yes | Shipped with family "G" device | 76 | +---------+------------+------------+---------------------------------------------------------------------+ 77 | | 2.4.22 | Yes | | | 78 | +---------+------------+------------+---------------------------------------------------------------------+ 79 | | 2.4.25 | Yes | Yes | | 80 | +---------+------------+------------+---------------------------------------------------------------------+ 81 | | 2.4.30 | Yes | Yes | Introduced SSID encryption for client setup | 82 | +---------+------------+------------+---------------------------------------------------------------------+ 83 | | 2.5.6 | Yes | Yes | Adds UUIDs to effects | 84 | +---------+------------+------------+---------------------------------------------------------------------+ 85 | | 2.5.9 | Yes | Yes | | 86 | +---------+------------+------------+---------------------------------------------------------------------+ 87 | | 2.6.0 | Yes | Yes | | 88 | +---------+------------+------------+---------------------------------------------------------------------+ 89 | | 2.6.2 | Yes | Yes | Shipped with family "F" device in 2021 | 90 | +---------+------------+------------+---------------------------------------------------------------------+ 91 | | 2.7.1 | Yes | Yes | | 92 | +---------+------------+------------+---------------------------------------------------------------------+ 93 | | 2.8.3 | Yes | Yes | | 94 | +---------+------------+------------+---------------------------------------------------------------------+ 95 | 96 | .. _`encrypted using host generated key`: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html#using-host-generated-key 97 | -------------------------------------------------------------------------------- /docs/hardware.rst: -------------------------------------------------------------------------------- 1 | .. _hardware: 2 | 3 | Hardware 4 | ======== 5 | 6 | There are wide variety of Twinkly products on the market with various 7 | functionality and properties. This page desribes hardware that this 8 | documentation has been tested with. 9 | 10 | Generation I 11 | ------------ 12 | 13 | Hardware consists of two circuit boards: 14 | 15 | - Module ESP-01 with microcontroller ESP8266 by Espressif Systems 16 | - Custom-made LED driver module 17 | 18 | Esptool v2.8 identification of MCU: 19 | 20 | - Chip is ESP8266EX 21 | - Features: WiFi 22 | - Crystal is 26MHz 23 | 24 | and flash: 25 | 26 | - Manufacturer: 5e 27 | - Device: 4015 28 | - Detected flash size: 2MB 29 | 30 | Model TW105S-EU 31 | ``````````````` 32 | 33 | It is a string of 105 RGB LED from 2017. 34 | 35 | API exposes these details: 36 | 37 | - Product code: TW105SEUP06 38 | - Product version: 2 39 | - Hardware version: 6 40 | - Flash size: 16 41 | - LED Type: 6 42 | - LED Version: 1 43 | - Max Supported LEDs: 255 44 | - Movie Capacity: 719 45 | - Frame Rate: 25 46 | 47 | Standard physical configuration is a string of 105 LEDs. 48 | 49 | Firmware belongs to family "D". In this documentation the device is referred 50 | as: 51 | 52 | - Hardware ID: 0033aaff 53 | - MAC address 5c:cf:7f:33:aa:ff 54 | 55 | Generation II 56 | ------------- 57 | 58 | Hardware consists of a circuit board with ESP32 microcontroller by Espressif 59 | Systems. Esptool v2.8 identification of MCU: 60 | 61 | - Chip is ESP32D0WDQ5 (revision 1) 62 | - Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None 63 | - Crystal is 40MHz 64 | 65 | and flash: 66 | 67 | - Manufacturer: c8 68 | - Device: 4017 69 | - Detected flash size: 8MB 70 | 71 | On the top of that device has Bluetooth for out of the band configuration of 72 | WiFi. 73 | 74 | Model TWW210SPP-TEU 75 | ``````````````````` 76 | 77 | It is branded as `Twinkly Wall and consists of 210 RGB+W LEDs`_. It is a matrix 78 | of 10 strings each consisting of 21 red, green, blue and white LEDs. 79 | 80 | API exposes these details: 81 | 82 | - Product code: TWW210SPP 83 | - Hardware version: 100 84 | - Flash size: 64 85 | - LED Type: 12 86 | - Firmware family: G 87 | - Bytes per LED: 4 88 | - Max Supported LEDs: 1200 89 | - Frame Rate: 11 90 | - Movie Capacity: 992 91 | - Wire type: 1 92 | 93 | Physical configuration is a string of 210 LEDs. 94 | 95 | In this documentation the device is referred as: 96 | 97 | - Hardware ID: 1bb210 98 | - MAC address 98:f4:ab:1b:b2:10 99 | 100 | Model TWI190SPP-TEU 101 | ``````````````````` 102 | 103 | It is branded as `Twinkly Icicle and consists of 190 RGB+W LEDs`_. It is a 104 | repeated pattern of strings with length 2, 4, 6, 2, 5 where each has red, 105 | green, blue and white LEDs. 106 | 107 | API exposes these details: 108 | 109 | - Product code: TWI190SPP 110 | - Hardware version: 100 111 | - Flash size: 64 112 | - LED Type: 12 113 | - Firmware family: G 114 | - Bytes per LED: 4 115 | - Max Supported LEDs: 1200 116 | - Frame Rate: 28.57 117 | - Movie Capacity: 992 118 | - Wire type: 4 119 | 120 | Physical configuration: 121 | 122 | - string of 95 LEDs on first cable 123 | - string of 95 LEDs on second cable 124 | 125 | In this documentation the device is referred as: 126 | 127 | - Hardware ID: 1cc190 128 | - MAC address 98:f4:ab:1c:c1:90 129 | 130 | Model TWF020STP-BEU 131 | ``````````````````` 132 | 133 | It is branded as `Twinkly Festoon and consists of 20 RGB Lamps`_. It is a 134 | string where each lamp is red, green and blue LEDs. 135 | 136 | API exposes these details: 137 | 138 | - Product code: TWF020STP-BT 139 | - Hardware version: 100 140 | - Flash size: 64 141 | - LED Type: 14 142 | - Firmware family: F 143 | - Bytes per LED: 3 144 | - Max Supported LEDs: 510 145 | - Frame Rate: 200 146 | - Movie Capacity: 1984 147 | 148 | Standard physical configuration is a string of 20 LEDs. 149 | 150 | In this documentation the device is referred as: 151 | 152 | - Hardware ID: 1fe520 153 | - MAC address 98:f4:ab:1f:e5:20 154 | 155 | Model TWS250STP-BEU 156 | ``````````````````` 157 | 158 | It is branded as `Twinkly Strings 250 LEDs Multicolor`_ with 250 red, green and 159 | blue LEDs. 160 | 161 | API exposes these details: 162 | 163 | - Product code: TWS250STP 164 | - Hardware version: 100 165 | - Flash size: 64 166 | - LED Type: 14 167 | - Firmware family: F 168 | - Bytes per LED: 3 169 | - Max Supported LEDs: 510 170 | - Frame Rate: 30.3 171 | - Movie Capacity: 1984 172 | 173 | Physical configuration: 174 | 175 | - string of 125 LEDs on first cable 176 | - string of 125 LEDs on second cable 177 | 178 | In this documentation the device is referred as: 179 | 180 | - Hardware ID: 2bb250 181 | - MAC address 98:f4:ab:2b:b2:50 182 | 183 | .. _`Twinkly Wall and consists of 210 RGB+W LEDs`: https://web.archive.org/web/2/https://www.twinkly.com/products/curtain-special-edition-210-leds/ 184 | .. _`Twinkly Icicle and consists of 190 RGB+W LEDs`: https://web.archive.org/web/2/https://www.twinkly.com/products/icicle-190-leds-special-edition/ 185 | .. _`Twinkly Festoon and consists of 20 RGB Lamps`: https://web.archive.org/web/2/https://www.twinkly.com/products/festoon-lights-starter-pack/ 186 | .. _`Twinkly Strings 250 LEDs Multicolor`: https://web.archive.org/web/2/https://www.twinkly.com/products/strings-multicolor-250-leds/ 187 | -------------------------------------------------------------------------------- /docs/history.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../HISTORY.rst 2 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Smart LED Christmas lights 2 | ========================== 3 | 4 | Contents: 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | 9 | readme 10 | 11 | Guides 12 | ------ 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | 17 | hardware 18 | firmware 19 | protocol_details 20 | 21 | .. _api-reference: 22 | 23 | API reference 24 | ------------- 25 | 26 | .. toctree:: 27 | :maxdepth: 2 28 | 29 | mqtt_api 30 | rest_api 31 | bt_api 32 | 33 | 34 | The Contributor Guide 35 | --------------------- 36 | 37 | .. toctree:: 38 | :maxdepth: 2 39 | 40 | contributing 41 | authors 42 | history 43 | 44 | Indices and tables 45 | ================== 46 | 47 | * :ref:`genindex` 48 | * :ref:`modindex` 49 | * :ref:`search` 50 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. xml to make Docutils-native XML files 37 | echo. pseudoxml to make pseudoxml-XML files for display purposes 38 | echo. linkcheck to check all external links for integrity 39 | echo. doctest to run all doctests embedded in the documentation if enabled 40 | goto end 41 | ) 42 | 43 | if "%1" == "clean" ( 44 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 45 | del /q /s %BUILDDIR%\* 46 | goto end 47 | ) 48 | 49 | 50 | %SPHINXBUILD% 2> nul 51 | if errorlevel 9009 ( 52 | echo. 53 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 54 | echo.installed, then set the SPHINXBUILD environment variable to point 55 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 56 | echo.may add the Sphinx directory to PATH. 57 | echo. 58 | echo.If you don't have Sphinx installed, grab it from 59 | echo.http://sphinx-doc.org/ 60 | exit /b 1 61 | ) 62 | 63 | if "%1" == "html" ( 64 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 68 | goto end 69 | ) 70 | 71 | if "%1" == "dirhtml" ( 72 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 76 | goto end 77 | ) 78 | 79 | if "%1" == "singlehtml" ( 80 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 84 | goto end 85 | ) 86 | 87 | if "%1" == "pickle" ( 88 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can process the pickle files. 92 | goto end 93 | ) 94 | 95 | if "%1" == "json" ( 96 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 97 | if errorlevel 1 exit /b 1 98 | echo. 99 | echo.Build finished; now you can process the JSON files. 100 | goto end 101 | ) 102 | 103 | if "%1" == "htmlhelp" ( 104 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 105 | if errorlevel 1 exit /b 1 106 | echo. 107 | echo.Build finished; now you can run HTML Help Workshop with the ^ 108 | .hhp project file in %BUILDDIR%/htmlhelp. 109 | goto end 110 | ) 111 | 112 | if "%1" == "qthelp" ( 113 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 114 | if errorlevel 1 exit /b 1 115 | echo. 116 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 117 | .qhcp project file in %BUILDDIR%/qthelp, like this: 118 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\xled.qhcp 119 | echo.To view the help file: 120 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\xled.ghc 121 | goto end 122 | ) 123 | 124 | if "%1" == "devhelp" ( 125 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished. 129 | goto end 130 | ) 131 | 132 | if "%1" == "epub" ( 133 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 137 | goto end 138 | ) 139 | 140 | if "%1" == "latex" ( 141 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 145 | goto end 146 | ) 147 | 148 | if "%1" == "latexpdf" ( 149 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 150 | cd %BUILDDIR%/latex 151 | make all-pdf 152 | cd %BUILDDIR%/.. 153 | echo. 154 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 155 | goto end 156 | ) 157 | 158 | if "%1" == "latexpdfja" ( 159 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 160 | cd %BUILDDIR%/latex 161 | make all-pdf-ja 162 | cd %BUILDDIR%/.. 163 | echo. 164 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 165 | goto end 166 | ) 167 | 168 | if "%1" == "text" ( 169 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 170 | if errorlevel 1 exit /b 1 171 | echo. 172 | echo.Build finished. The text files are in %BUILDDIR%/text. 173 | goto end 174 | ) 175 | 176 | if "%1" == "man" ( 177 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 178 | if errorlevel 1 exit /b 1 179 | echo. 180 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 181 | goto end 182 | ) 183 | 184 | if "%1" == "texinfo" ( 185 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 186 | if errorlevel 1 exit /b 1 187 | echo. 188 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 189 | goto end 190 | ) 191 | 192 | if "%1" == "gettext" ( 193 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 194 | if errorlevel 1 exit /b 1 195 | echo. 196 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 197 | goto end 198 | ) 199 | 200 | if "%1" == "changes" ( 201 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 202 | if errorlevel 1 exit /b 1 203 | echo. 204 | echo.The overview file is in %BUILDDIR%/changes. 205 | goto end 206 | ) 207 | 208 | if "%1" == "linkcheck" ( 209 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 210 | if errorlevel 1 exit /b 1 211 | echo. 212 | echo.Link check complete; look for any errors in the above output ^ 213 | or in %BUILDDIR%/linkcheck/output.txt. 214 | goto end 215 | ) 216 | 217 | if "%1" == "doctest" ( 218 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 219 | if errorlevel 1 exit /b 1 220 | echo. 221 | echo.Testing of doctests in the sources finished, look at the ^ 222 | results in %BUILDDIR%/doctest/output.txt. 223 | goto end 224 | ) 225 | 226 | if "%1" == "xml" ( 227 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 228 | if errorlevel 1 exit /b 1 229 | echo. 230 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 231 | goto end 232 | ) 233 | 234 | if "%1" == "pseudoxml" ( 235 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 236 | if errorlevel 1 exit /b 1 237 | echo. 238 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 239 | goto end 240 | ) 241 | 242 | :end 243 | -------------------------------------------------------------------------------- /docs/mqtt_api.rst: -------------------------------------------------------------------------------- 1 | Messaging API reference 2 | ======================= 3 | 4 | New in firmware version 2.0.22. 5 | 6 | Overview 7 | -------- 8 | 9 | Device sends messages with its states to a broker with MQTT. By default broker is set to mqtt.twinkly.com. 10 | 11 | Firmware family "D" use HTTP and "G" use TLS. 12 | 13 | Last topic levels are always client ID which are by default derived from MAC address of the device as uppercased hexadecimal digits. 14 | 15 | Status from device 16 | ------------------ 17 | 18 | Device publishes these messages to a broker. 19 | 20 | Topic `xled/status/` followed by client ID 21 | 22 | Messages 23 | ```````` 24 | 25 | * `online` 26 | 27 | * `ip` - IP address. Added in firmware 2.1.0. 28 | * `ssid` - SSID to which device is connected. Added in firmware 2.1.0. 29 | 30 | * `offline` 31 | 32 | Example 33 | ``````` 34 | 35 | Online (firmware 2.0.22):: 36 | 37 | {"status": "online"} 38 | 39 | Online (since firmware 2.1.0):: 40 | 41 | {"status": "online", "ip": "192.168.4.1", "ssid": "home"} 42 | 43 | Offline:: 44 | 45 | {"status": "offline"} 46 | 47 | Application status from device 48 | ------------------------------ 49 | Device publishes these messages to a broker. 50 | 51 | Topic 52 | ````` 53 | 54 | `xled/appstatus/` followed by client ID 55 | 56 | Messages 57 | ```````` 58 | 59 | * `off` 60 | * `movie` 61 | * `collision` 62 | * `rainbow` 63 | * `twinkle` 64 | * `snake` 65 | 66 | Example 67 | ``````` 68 | 69 | Rainbow:: 70 | 71 | {"appstatus": "rainbow"} 72 | 73 | Parameters 74 | ---------- 75 | 76 | Parameters published by a device to broker. 77 | 78 | Topic 79 | ````` 80 | 81 | `xled/params/` followed by client ID 82 | 83 | Messages 84 | ```````` 85 | 86 | `brightness` 87 | (number), brightness value in percent 88 | `filters` 89 | (list), contains a string "brightness" if brightness is set. 90 | 91 | Example 92 | ``````` 93 | 94 | :: 95 | 96 | {"brightness": 50, "filters": ["brightness"]} 97 | 98 | Command messages to device 99 | -------------------------- 100 | 101 | Device listens to these messages. 102 | 103 | Topic 104 | ````` 105 | 106 | `xled/command/` followed by client ID 107 | 108 | Messages 109 | ```````` 110 | 111 | `changeeffect` 112 | each message switches to next of default effects or movie. Same as pressing the button on the device. 113 | 114 | `setmovie` 115 | sets to uploaded movie effect 116 | 117 | `setcollision` 118 | sets default effect "collision" 119 | 120 | `setrainbow` 121 | sets default effect "rainbow" 122 | 123 | `setsnake` 124 | sets default effect "snake" 125 | 126 | `settwinkle` 127 | sets default effect "twinkle" 128 | 129 | `setwaves` 130 | sets default effect "waves" 131 | 132 | `switchoff` 133 | switches off the device 134 | 135 | `switchon` 136 | switches on the device 137 | 138 | `setbrightnessdelta` 139 | changes brightness by amount set by `value`. Parameter `value` is signed number. 140 | 141 | `setbrightness` 142 | changes brightness to `value`. Parameter `value` is a number between 0..255 but only up to 100 has a dimming effect. 143 | 144 | Example 145 | ``````` 146 | 147 | Switch on:: 148 | 149 | {"command": "switchon"} 150 | 151 | Lower brightness value by 20 percents:: 152 | 153 | {"command": "setbrightnessdelta", "value", -20} 154 | -------------------------------------------------------------------------------- /docs/protocol_details.rst: -------------------------------------------------------------------------------- 1 | Protocol details 2 | ================ 3 | 4 | This page describes hardware, modes of operation and some private protocols or algorithms used by Twinkly application. 5 | 6 | Hardware ID 7 | ----------- 8 | 9 | Each device has unique hardware ID that consists of 6 bytes written as lowercase hex value. It can be read through API call. 10 | 11 | * In generation I devices it is rightmost part of device's MAC address. 12 | 13 | * In generation II devices it is rightmost part of the device's MAC address in station (STA) mode. 14 | 15 | Device ID 16 | --------- 17 | 18 | Each device has unique ID that consists of a prefix **Twinkly_** and 6 bytes written as uppercase hex value: 19 | 20 | * In generation I devices it is rightmost part of device's MAC address. 21 | 22 | * In generation II devices it is rightmost part of the device's MAC address in access point (AP) mode. 23 | 24 | Value can not be directly read by API but it is used in various places - e.g. in discovery datagrams. 25 | 26 | Device name 27 | ----------- 28 | 29 | Device has a name that can be used for identification - e.g. in the application. Its default value is the same as `device id`_. It can be read or changed by API. It's length is from 0 to 32 bytes. 30 | 31 | Access point SSID 32 | ----------------- 33 | 34 | Device in Access Point mode broadcasts SSID. Its default value is the same as `device id`_. It can be read or changed with API. It's length is from 1 to 31 bytes. 35 | 36 | MQTT Client ID 37 | -------------- 38 | 39 | When device uses MQTT protocol it sends client identification. Its default value is written as uppercase 12 byte long hex value: 40 | 41 | * In generation I devices from their MAC address. 42 | 43 | * In generation II devices from their MAC address in access point (AP) mode. 44 | 45 | It can be read or changed by API. It's length is from 0 to 32 bytes. 46 | 47 | Modes of network operation 48 | -------------------------- 49 | 50 | Hardware works in two network modes: 51 | 52 | - Access Point (AP) 53 | - Station (STA) 54 | 55 | AP mode is default - after factory reset. See `Access point SSID` for details. Generation I devices provide open AP - without any encryption. Generation II devices use WPA2 with password `Twinkly2019`. Server uses static IP address 192.168.4.1 and operates in network 192.168.4.0/24. Provides DHCP server for any device it joins the network. It's hostname is `_gateway`. 56 | 57 | In STA mode a device connects to an access points with configured SSID and password. If DHCP is enabled it sends `device id`_ hostname. 58 | 59 | Network mode can be changed with an API calls. 60 | 61 | http://41j.com/blog/2015/01/esp8266-access-mode-notes/ 62 | 63 | WiFi setup encryption 64 | --------------------- 65 | 66 | Some WiFi configuration is encrypted before it is sent over REST API to the device. 67 | 68 | Up until firmware version 2.4.22 only WiFi password was encrypted using key string `supersecretkey!!`, which is 16 bytes long, in hex:: 69 | 70 | 73 75 70 65 72 73 71 | 65 63 72 65 74 6B 72 | 65 79 21 21 73 | 74 | Since firmware version 2.4.25 not only WiFi password but also SSID is encrypted with new key of length 48 bytes, in hex:: 75 | 76 | 26 80 F5 87 9F EE 77 | 2C 75 11 AA 08 15 78 | 47 44 8E 04 99 CD 79 | 68 07 6E 09 32 62 80 | 5D C4 DE 7C 38 98 81 | 9E 88 80 EE 2A B7 82 | 33 67 8F A2 0D CC 83 | 85 D8 94 CD 94 4F 84 | 85 | 1. Generate encryption key 86 | 87 | 1. Get MAC address of a device in AP mode or `mac` value from `gestalt` REST API call and repeat it to length of the secret key. 88 | 2. XOR these two values. 89 | 90 | 2. Right pad desired configuration (password or SSID) with zero bytes to length 64 bytes. 91 | 92 | 3. Use RC4 to encrypt padded data with the encryption key. 93 | 94 | 4. Base64 encode encrypted string. 95 | 96 | Discovery protocol 97 | ------------------ 98 | 99 | Discovery protocol uses IPv4 datagrams to broadcast addresses over UDP to port 5555 listens for replies. 100 | 101 | Discovery request message to find all Twinkly devices on the network: 102 | 103 | * 1 byte `0x01` probably version 104 | * 8 bytes as a string `discover` 105 | 106 | Twinkly devices respond with message: 107 | 108 | * first four bytes are octets of IP address of the device in reverse order - first byte is last octet of the IP adress, second one is the second to last, ... 109 | 110 | * fifth and sixth byte are `0x79 0x75` - string `OK` 111 | 112 | * rest is a string representing `device id`_ 113 | 114 | * last one is a zero byte 115 | 116 | Where are you protocol 117 | ---------------------- 118 | 119 | Where are you protocol uses unicast IPv4 datagrams over UDP to port 5556. 120 | 121 | Request message so far with unknown purpose: 122 | 123 | * 1 byte `0x01` probably version 124 | * 8 bytes as a string `WHEREAREYOU` 125 | 126 | Get and verify authentication token 127 | ----------------------------------- 128 | 129 | Application uses TCP port 80 to get and verify authentication token. It is later used for some calls that require it. 130 | 131 | 1. Application generates challenge and sends it as part of login request. 132 | 2. Among other data server responds with authentication token 133 | 3. Application uses authentication_token in header of request to verify. 134 | 135 | Only after this handshake authentication token can be used in other calls. Most of them require it. Previous authentication token, if existed, is invalided. 136 | 137 | Verification of challenge-response 138 | ---------------------------------- 139 | 140 | As part of login process server sends not only authentication token but also challenge-response. Application may verify if it shares secret with server - maybe if it is genuine Twinkly device. 141 | 142 | The key for this algorithm is a string `evenmoresecret!!` which is 16 long, in hex:: 143 | 144 | 65 76 65 6E 6D 6F 145 | 72 65 73 65 63 72 146 | 65 74 21 21 147 | 148 | 1. Generate encryption key 149 | 150 | 1. Get MAC address of a device in AP mode or `mac` value from `gestalt` REST API call and repeat it to length of the secret key. 151 | 2. XOR these two values 152 | 153 | 2. Encrypt - use RC4 to encrypt challenge with the key. 154 | 155 | 3. Generate hash digest - encrypted data with SHA1. 156 | 157 | 4. Compare - hash digest must be same as challenge-response from server. 158 | 159 | Firmware update 160 | --------------- 161 | 162 | Update sequence for generation I device follows: 163 | 164 | 1. application sends first file to endpoint 0 over HTTP 165 | 2. server returns sha1sum of received file 166 | 3. application sends second file to endpoint 1 over HTTP 167 | 4. server returns sha1sum of received file 168 | 5. application calls update API with sha1sum of each stages. 169 | 170 | Update sequence for generation II device follows: 171 | 172 | 1. application sends first file to endpoint 0 over HTTP 173 | 2. server returns sha1sum of received file 174 | 3. application calls update API with sha1sum of uploaded stage. 175 | 176 | LED operating modes 177 | ------------------- 178 | 179 | Hardware can operate in one of following modes: 180 | 181 | * `off` - turns off lights 182 | * `color` - shows a static color 183 | * `demo` - starts predefined sequence of effects that are changed after few seconds 184 | * `movie` - plays predefined or uploaded effect. If movie hasn't been set (yet) code 1104 is returned. 185 | * `rt` - receive effect in real time 186 | * `effect` - plays effect with `effect_id` 187 | * `playlist` - plays a movie from a playlist. Since firmware version 2.5.6. 188 | 189 | Upload full movie LED effect 190 | ---------------------------- 191 | 192 | 1. Application calls API to switch mode to movie 193 | 2. Application calls API movie/full with file sent as part of the request 194 | 3. Application calls config movie call with additional parameters of the movie 195 | 196 | Frame format 197 | ------------ 198 | 199 | A frame is the lowest level that a device accepts to light any LED. Firstly let's start with single LED definition. 200 | 201 | Single LED 202 | `````````` 203 | 204 | Intensity of each color in a LED is defined by one unsigned byte. Order of bytes is based on a LED profile: 205 | 206 | - RGB: 207 | 208 | 1. *red* 209 | 2. *green* 210 | 3. *blue* 211 | 212 | - RGBW: 213 | 214 | 1. *white* 215 | 2. *red* 216 | 3. *green* 217 | 4. *blue* 218 | 219 | Frame 220 | ````` 221 | 222 | The frame is a sequence of bytes that define color of each LED in a device. First LED is the closest to a LED driver/adapter (potentially on one of the cables if a device has two). 223 | 224 | Examples of frame lengths: 225 | 226 | +----------------+-------------+-----------------------+ 227 | | Number of LEDs | LED profile | Frame length in bytes | 228 | +================+=============+=======================+ 229 | | 105 | RGB | 315 | 230 | +----------------+-------------+-----------------------+ 231 | | 210 | RGBW | 840 | 232 | +----------------+-------------+-----------------------+ 233 | 234 | Movie format 235 | ------------ 236 | 237 | A movie is a sequence of frames. A frame rate is defined separately from a movie. 238 | 239 | Example movie lengths: 240 | 241 | +-----------------------+------------------+-----------------------+ 242 | | Frame length in bytes | Number of frames | Movie length in bytes | 243 | +=======================+==================+=======================+ 244 | | 315 | 12 | 3780 | 245 | +-----------------------+------------------+-----------------------+ 246 | | 840 | 6 | 5040 | 247 | +-----------------------+------------------+-----------------------+ 248 | 249 | Real time LED operating mode 250 | ---------------------------- 251 | 252 | 1. Application calls HTTP API to switch mode to rt 253 | 2. Then UDP datagrams are sent to a port 7777 of device. Each datagram contains a frame or its segment that is immediately displayed. See bellow for format of the datagrams. 254 | 3. After some time without any UDP datagrams device switches back to movie mode. 255 | 256 | Real time LED UDP datagram format 257 | --------------------------------- 258 | 259 | Before datagrams are sent to a device application needs to login and verify authentication token. See above. 260 | 261 | UDP datagram format depends on firmware version which implies device generation. 262 | 263 | Version 1 264 | ````````` 265 | 266 | This format is used in generation I devices. An UDP datagram starts with a header: 267 | 268 | * 1 byte: version *\\x01* (byte with hex representation 0x01) 269 | * 8 bytes: byte representation of the authentication token - not encoded in base 64 270 | * 1 byte: number of LED definitions in the frame 271 | 272 | Then follows a body in the frame format. 273 | 274 | Version 2 275 | ````````` 276 | 277 | This format is used in generation II devices until firmware version 2.4.6 (including). An UDP datagram starts with a header: 278 | 279 | * 1 byte: version *\\x02* (byte with hex representation 0x02) 280 | * 8 bytes: byte representation of the authentication token - not encoded in base 64 281 | * 1 byte: *\\x00* of unknown meaning 282 | 283 | Then follows a body in the movie format. 284 | 285 | Version 3 286 | ````````` 287 | 288 | This format is used in generation II devices from firmware version 2.4.14. 289 | 290 | Frames are split into fragments with size up to 900 bytes. Each fragment is sent in an UDP datagram that starts with a header: 291 | 292 | * 1 byte: version *\\x03* (byte with hex representation 0x03) 293 | * 8 bytes: byte representation of the authentication token - not encoded in base 64 294 | * 2 bytes: *\\x00\\x00* of unknown meaning - maybe a fragment could be 3 bytes long? 295 | * 1 byte: frame fragment number - first one is 0 296 | 297 | Then follows a body with the frame fragment. 298 | 299 | Example of a frame with size 2250 bytes for a device with 750 LEDs with RGB LED profile: 300 | 301 | +-----------------------+---------------------+ 302 | | Frame fragment number | Frame fragment size | 303 | +=======================+=====================+ 304 | | 0 | 900 | 305 | +-----------------------+---------------------+ 306 | | 1 | 900 | 307 | +-----------------------+---------------------+ 308 | | 2 | 450 | 309 | +-----------------------+---------------------+ 310 | 311 | Scan for WiFi networks 312 | ---------------------- 313 | 314 | Hardware can be used to scan for available WiFi networks and return some information about them. I haven't seen this call done by the application so I guess it can be used to find available channels or so. 315 | 316 | 1. Call network scan API 317 | 2. Wait a little bit 318 | 3. Call network results API 319 | 320 | Group devices 321 | ------------- 322 | 323 | Devices can be grouped together to control them at once. Only compatible devices can be grouped. Compatibility seems to be based on LED profile (RGB vs. RGB+W). 324 | 325 | One device is master and other are slaves. 326 | 327 | Group name acts as a single device in the application. 328 | 329 | Master since firmware version 2.5.6 grouped with one slave in compat mode sends every 5 seconds broadcast datagrams from UDP port 7777 to UDP port 7777 with total length 50 bytes. Every time 3 datagrams of the same contents are sent. 330 | 331 | Header: 332 | 333 | * 1 byte *\\x03* (byte with hex representation 0x03) 334 | * 8 bytes *\\x0000000000000000* 335 | 336 | Followed by one of: 337 | 338 | a) First triplet: 339 | 340 | * 2 bytes *\\x0101* 341 | * 4 bytes that seem to be based on group name 342 | * 3 bytes of unknown meaning 343 | * 4 bytes that seem to be constant for a device also used in the next datagram 344 | 345 | b) Second triplet: 346 | 347 | * 2 bytes *\\x0104* 348 | * 4 bytes that seem to be based on group name 349 | * 2 bytes of unknown meaning 350 | * 4 bytes that seem to be constant for a device also same as in previous datagram 351 | 352 | c) Third or later: 353 | 354 | * 2 bytes *\\x0102* 355 | * 4 bytes that seem to be based on group name 356 | * 2 bytes that change every 10 seconds 357 | 358 | Rest is padded with *\\x00* 359 | -------------------------------------------------------------------------------- /docs/readme.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | -------------------------------------------------------------------------------- /docs/requirements.in: -------------------------------------------------------------------------------- 1 | sphinx==7.2.6 2 | sphinx_rtd_theme 3 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file is autogenerated by pip-compile with Python 3.11 3 | # by the following command: 4 | # 5 | # pip-compile --output-file=requirements.txt requirements.in 6 | # 7 | alabaster==0.7.13 8 | # via sphinx 9 | babel==2.14.0 10 | # via sphinx 11 | certifi==2023.11.17 12 | # via requests 13 | charset-normalizer==3.3.2 14 | # via requests 15 | docutils==0.20.1 16 | # via 17 | # sphinx 18 | # sphinx-rtd-theme 19 | idna==3.6 20 | # via requests 21 | imagesize==1.4.1 22 | # via sphinx 23 | jinja2==3.1.2 24 | # via sphinx 25 | markupsafe==2.1.3 26 | # via jinja2 27 | packaging==23.2 28 | # via sphinx 29 | pygments==2.17.2 30 | # via sphinx 31 | requests==2.31.0 32 | # via sphinx 33 | snowballstemmer==2.2.0 34 | # via sphinx 35 | sphinx==7.2.6 36 | # via 37 | # -r requirements.in 38 | # sphinx-rtd-theme 39 | # sphinxcontrib-applehelp 40 | # sphinxcontrib-devhelp 41 | # sphinxcontrib-htmlhelp 42 | # sphinxcontrib-jquery 43 | # sphinxcontrib-qthelp 44 | # sphinxcontrib-serializinghtml 45 | sphinx-rtd-theme==2.0.0 46 | # via -r requirements.in 47 | sphinxcontrib-applehelp==1.0.7 48 | # via sphinx 49 | sphinxcontrib-devhelp==1.0.5 50 | # via sphinx 51 | sphinxcontrib-htmlhelp==2.0.4 52 | # via sphinx 53 | sphinxcontrib-jquery==4.1 54 | # via sphinx-rtd-theme 55 | sphinxcontrib-jsmath==1.0.1 56 | # via sphinx 57 | sphinxcontrib-qthelp==1.0.6 58 | # via sphinx 59 | sphinxcontrib-serializinghtml==1.1.9 60 | # via sphinx 61 | urllib3==2.1.0 62 | # via requests 63 | -------------------------------------------------------------------------------- /docs/rest_api.rst: -------------------------------------------------------------------------------- 1 | RESTful API reference 2 | ===================== 3 | 4 | Overview 5 | -------- 6 | 7 | Twinkly rest API is primary way to get information about the device, configure network and modes of the device. It is a HTTP 1.1 based API sent over TCP port 80. 8 | 9 | This API is used by mobile applications. It haven't been made public yet so it may change at any time. 10 | 11 | Request Authentication 12 | `````````````````````` 13 | 14 | Most API requests require valid authentication token. Except of: 15 | 16 | * login 17 | * gestalt 18 | * fw version 19 | * status 20 | 21 | If API requires authentication but valid token wasn't passed server returns HTTP status code 401 Unauthenticated and string `Invalid Token.` in the response body. 22 | 23 | HTTP Responses 24 | `````````````` 25 | 26 | The HTTP response can be used to determine if the request was successful, and if not, whether the request should be retried. 27 | 28 | 200 Success 29 | The request was successful. 30 | 31 | 401 Unauthenticated 32 | Request requires authentication but authorization failed. Application didn't handle the request. 33 | 34 | 404 Not Found 35 | If a string `Resource not found.` is found in the response body check if API endpoint is implemented in the current firmware version. 36 | 37 | Application hierarchy 38 | ````````````````````` 39 | 40 | Endpoints seem to be organized into hierarchy by applications. Overview of the hierarchy: 41 | 42 | * `login` 43 | * `verify` 44 | * `logout` 45 | * `gestalt` 46 | * `status` 47 | * `device_name` 48 | * `echo` 49 | * `timer` 50 | * `led` 51 | 52 | * `layout` 53 | 54 | * `full` 55 | 56 | * `mode` 57 | * `color` 58 | * `effects` 59 | 60 | * `current` 61 | 62 | * `config` 63 | * `movie` 64 | 65 | * `full` 66 | * `config` 67 | 68 | * `out` 69 | 70 | * `brightness` 71 | * `saturation` 72 | 73 | * `driver_params` 74 | * `reset` 75 | * `reset2` 76 | * `rt` 77 | 78 | * `fw` 79 | 80 | * `version` 81 | * `update` 82 | * `0` 83 | 84 | * `update` 85 | 86 | * `1` 87 | 88 | * `update` 89 | 90 | * `movies` 91 | 92 | * `new` 93 | * `full` 94 | * `current` 95 | 96 | * `network` 97 | 98 | * `scan` 99 | * `scan_results` 100 | * `status` 101 | 102 | * `playlist` 103 | 104 | * `current` 105 | 106 | * `mqtt` 107 | 108 | * `config` 109 | 110 | * `mic` 111 | 112 | * `config` 113 | * `sample` 114 | 115 | * `music` 116 | 117 | * `drivers` 118 | 119 | * `sets` 120 | 121 | * `current` 122 | 123 | * `summary` 124 | 125 | Application responses 126 | ````````````````````` 127 | 128 | The API may return application status as `code` value of JSON. Returned will not necessarily "correspond" with the HTTP status code. For example, a HTTP status code 200 OK returned with an error application code indicates that the request successfully reached the server, but application cannot process the request. 129 | 130 | 1000 131 | Ok 132 | 133 | 1001 134 | Error 135 | 136 | 1101 137 | Invalid argument value 138 | 139 | 1102 140 | Error 141 | 142 | 1103 143 | Error - value too long? Or missing required object key? 144 | 145 | 1104 146 | Error - malformed JSON on input? 147 | 148 | 1105 149 | Invalid argument key 150 | 151 | 1107 152 | Ok? 153 | 154 | 1108 155 | Ok? 156 | 157 | 1205 158 | Error with firmware upgrade - SHA1SUM does not match 159 | 160 | Login 161 | ----- 162 | 163 | Request access token. 164 | 165 | Since firmware version 1.99.18. 166 | 167 | HTTP request 168 | ```````````` 169 | 170 | `POST /xled/v1/login` 171 | 172 | Parameters 173 | `````````` 174 | 175 | Parameters as JSON object. 176 | 177 | `challenge` 178 | Random 32 byte string encoded with base64. 179 | 180 | Response 181 | ```````` 182 | 183 | The response will be an object. 184 | 185 | `authentication_token` 186 | Access token in format: 8 byte string base64 encoded. First authenticated API with this token must be Verify. 187 | 188 | `challenge-response` 189 | 41 byte string ([0-9a-h]) 190 | 191 | `code` 192 | (integer), application return code. 193 | 194 | `authentication_token_expires_in`: integer. All the time 14400? 195 | 196 | Example 197 | ``````` 198 | 199 | Request:: 200 | 201 | POST /xled/v1/login HTTP/1.1 202 | Host: 192.168.4.1 203 | Content-Type: application/json 204 | Content-Length: 61 205 | 206 | {"challenge": "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8="} 207 | 208 | Response:: 209 | 210 | HTTP/1.1 200 Ok 211 | Connection: close 212 | Content-Length: 155 213 | Content-Type: application/json 214 | 215 | {"authentication_token":"5jPe+ONhwUY=","authentication_token_expires_in":14400,"challenge-response":"8d87f080947e343180da3f411df3997e3e9ae0cc","code":1000} 216 | 217 | Verify 218 | ------ 219 | 220 | Verify the token retrieved by Login. Successful call invalidates previous token, if it existed. 221 | 222 | Since firmware version 1.99.18. 223 | 224 | HTTP request 225 | ```````````` 226 | 227 | `POST /xled/v1/verify` 228 | 229 | `X-Auth-Token` 230 | Authentication token 231 | 232 | Parameters 233 | `````````` 234 | 235 | Parameters as JSON object. 236 | 237 | `challenge-response` 238 | (optional) value returned by login request. 239 | 240 | Response 241 | ```````` 242 | 243 | The response will be an object. 244 | 245 | `code` 246 | (integer), application return code. 247 | 248 | Example 249 | ``````` 250 | 251 | Request:: 252 | 253 | POST /xled/v1/verify HTTP/1.1 254 | Host: 192.168.4.1 255 | Content-Type: application/json 256 | X-Auth-Token: 5jPe+ONhwUY= 257 | Content-Length: 66 258 | 259 | {"challenge-response": "8d87f080947e343180da3f411df3997e3e9ae0cc"} 260 | 261 | Response:: 262 | 263 | HTTP/1.1 200 Ok 264 | Connection: close 265 | Content-Length: 13 266 | Content-Type: application/json 267 | 268 | {"code":1000} 269 | 270 | Logout 271 | ------ 272 | 273 | Probably invalidate access token. Doesn't work. 274 | 275 | Since firmware version 1.99.18. 276 | 277 | HTTP request 278 | ```````````` 279 | 280 | `POST /xled/v1/logout` 281 | 282 | `X-Auth-Token` 283 | Authentication token 284 | 285 | Response 286 | ```````` 287 | 288 | The response will be an object. 289 | 290 | `code` 291 | (integer), application return code. 292 | 293 | Example 294 | ``````` 295 | 296 | Request:: 297 | 298 | POST /xled/v1/logout HTTP/1.1 299 | Host: 192.168.4.1 300 | Content-Type: application/json 301 | X-Auth-Token: 5jPe+ONhwUY= 302 | Content-Length: 2 303 | 304 | {} 305 | 306 | Response:: 307 | 308 | HTTP/1.1 200 Ok 309 | Connection: close 310 | Content-Length: 13 311 | Content-Type: application/json 312 | 313 | {"code":1000} 314 | 315 | Device details 316 | -------------- 317 | 318 | Gets information detailed information about the device. 319 | 320 | Since firmware version 1.99.18. 321 | 322 | HTTP request 323 | ```````````` 324 | 325 | `GET /xled/v1/gestalt` 326 | 327 | Response 328 | ```````` 329 | 330 | The response will be an object. 331 | 332 | For firmware family "D": 333 | 334 | `product_name` 335 | (string) `Twinkly` 336 | 337 | `product_version` 338 | (numeric string), e.g. "2" 339 | 340 | `hardware_version` 341 | (numeric string), e.g. "6" 342 | 343 | `bytes_per_led` 344 | (number), 4 345 | 346 | `flash_size` 347 | (number), e.g. 16 348 | 349 | `led_type` 350 | (number), e.g. 6 351 | 352 | `led_version` 353 | (string) "1" 354 | 355 | `product_code` 356 | (string), e.g. "TW105SEUP06" 357 | 358 | `device_name` 359 | (string), name of the device - see section Device Name in Protocol details. 360 | 361 | `rssi` 362 | (number), Received signal strength indication. Since firmware version: 2.1.0. 363 | 364 | `uptime` 365 | (string) number as a string. Seconds since start. E.g. "60" 366 | 367 | `hw_id` 368 | (string), see section Hardware ID in Protocol details. 369 | 370 | `mac` 371 | (string) MAC address as six groups of two hexadecimal digits separated by colons (:). 372 | 373 | `uuid` 374 | (string) UUID of the device. Since firmware version: 2.0.8. Device in family "D" has value 00000000-0000-0000-0000-000000000000. 375 | 376 | `max_supported_led` 377 | (number), e.g. firmware family "D": 180 in firmware version 1.99.20, 224 in 1.99.24, 228 in 1.99.30, 255 in 2.0.0 and newer. 378 | 379 | `base_leds_number` 380 | (number), e.g. 105 381 | 382 | `number_of_led` 383 | (number), e.g. 105 384 | 385 | `led_profile` 386 | (string) "RGB" 387 | 388 | `frame_rate` 389 | (number), 25 390 | 391 | `movie_capacity` 392 | (number), e.g. 719 393 | 394 | `copyright` 395 | (string) "LEDWORKS 2017" 396 | 397 | `code` 398 | (integer), application return code. 399 | 400 | For firmware family "F" since firmware version 2.2.1: 401 | 402 | `fw_family` 403 | (string) "F", 404 | 405 | `product_name` 406 | (string) `Twinkly` 407 | 408 | `hardware_version` 409 | (numeric string), "100" 410 | 411 | `bytes_per_led` 412 | (number), 3 413 | 414 | `flash_size` 415 | (number), 64 416 | 417 | `led_type` 418 | (number), 14 419 | 420 | `product_code` 421 | (string), e.g. "TWS250STP" 422 | 423 | `device_name` 424 | (string), name of the device - see section Device Name in Protocol details. 425 | 426 | `uptime` 427 | (string) number as a string. Miliseconds since start. E.g. "60000" 428 | 429 | `hw_id` 430 | (string), see section Hardware ID in Protocol details. 431 | 432 | `mac` 433 | (string) MAC address as six groups of two hexadecimal digits separated by colons (:). Address of a device in access point mode. 434 | 435 | `uuid` 436 | (string) UUID of the device 437 | 438 | `max_supported_led` 439 | (number), e.g. 510, since firmware version 2.4.14: 1020, since 2.4.22: 1200 440 | 441 | `number_of_led` 442 | (number), e.g. 250 443 | 444 | `led_profile` 445 | (string) "RGB" 446 | 447 | `frame_rate` 448 | (number), e.g. 30.3, since firmware version 2.4.14: 17.86, since 2.4.16: 23.81, since 2.4.22: 25, since 2.4.30: 25.64, since 2.5.6: 24. 449 | 450 | `measured_frame_rate` 451 | (number), e.g. 23.26. Since firmware version 2.5.6. 452 | 453 | `movie_capacity` 454 | (number), e.g. 1984, since firmware version 2.4.14: 992 455 | 456 | `copyright` 457 | (string) "LEDWORKS 2018" 458 | 459 | `code` 460 | (integer), application return code. 461 | 462 | For firmware family "G" since firmware version 2.4.21: 463 | 464 | `fw_family` 465 | (string) "G", 466 | 467 | `product_name` 468 | (string) `Twinkly` 469 | 470 | `hardware_version` 471 | (numeric string), "100" 472 | 473 | `flash_size` 474 | (number), 64 475 | 476 | `led_type` 477 | (number), 12 478 | 479 | `product_code` 480 | (string), e.g. "TWW210SPP" or "TWI190SPP" 481 | 482 | `device_name` 483 | (string), name of the device - see section Device Name in Protocol details. 484 | 485 | `uptime` 486 | (string) number as a string. Miliseconds since start. E.g. "60000" 487 | 488 | `hw_id` 489 | (string), see section Hardware ID in Protocol details. 490 | 491 | `mac` 492 | (string) MAC address as six groups of two hexadecimal digits separated by colons (:). Address of a device in access point mode. 493 | 494 | `uuid` 495 | (string) UUID of the device 496 | 497 | `max_supported_led` 498 | (number), e.g. 1200 499 | 500 | `number_of_led` 501 | (number), e.g. 190 or 210 502 | 503 | `led_profile` 504 | (string) "RGBW" 505 | 506 | `frame_rate` 507 | (number), e.g. 28.57. Since firmware version 2.5.6: 24 508 | 509 | `measured_frame_rate` 510 | (number), e.g. 27.78. Since firmware version 2.5.6. 511 | 512 | `movie_capacity` 513 | (number), e.g. 992 514 | 515 | `copyright` 516 | (string) "LEDWORKS 2018" 517 | 518 | `wire_type` 519 | (integer), e.g. 1 or 4 520 | 521 | `code` 522 | (integer), application return code. 523 | 524 | Example 525 | ``````` 526 | 527 | Request:: 528 | 529 | GET /xled/v1/gestalt HTTP/1.1 530 | Host: 192.168.4.1 531 | 532 | Response from firmware family "D":: 533 | 534 | HTTP/1.1 200 Ok 535 | Connection: close 536 | Content-Length: 406 537 | Content-Type: application/json 538 | 539 | {"product_name":"Twinkly","product_version":"2","hardware_version":"6","flash_size":16,"led_type":6,"led_version":"1","product_code":"TW105SEUP06","device_name":"Twinkly_33AAFF","uptime":"60","hw_id":"0033aaff","mac":"5c:cf:7f:33:aa:ff","max_supported_led":224,"base_leds_number":105,"number_of_led":105,"led_profile":"RGB","frame_rate":25,"movie_capacity":719,"copyright":"LEDWORKS 2017","code":1000} 540 | 541 | Response from firmware family "G":: 542 | 543 | HTTP/1.1 200 OK 544 | Server: esp-httpd/0.5 545 | Transfer-Encoding: chunked 546 | Content-Type: application/json 547 | 548 | {"product_name":"Twinkly","hardware_version":"100","bytes_per_led":4,"hw_id":"1cc190","flash_size":64,"led_type":12,"product_code":"TWI190SPP","fw_family":"G","device_name":"Twinkly_1CC190","uptime":"8107194","mac":"98:f4:ab:1c:c1:90","uuid":"E103C5A3-3398-4B77-AE1A-9D8998A5EB62","max_supported_led":1200,"number_of_led":190,"led_profile":"RGBW","frame_rate":28.57,"movie_capacity":992,"wire_type":4,"copyright":"LEDWORKS 2018","code":1000} 549 | 550 | Get device name 551 | --------------- 552 | 553 | Gets device name 554 | 555 | Since firmware version 1.99.18. 556 | 557 | HTTP request 558 | ```````````` 559 | 560 | `GET /xled/v1/device_name` 561 | 562 | `X-Auth-Token` 563 | Authentication token 564 | 565 | Response 566 | ```````` 567 | 568 | The response will be an object. 569 | 570 | `name` 571 | (string) Device name. 572 | 573 | `code` 574 | (integer), application return code. 575 | 576 | Example 577 | ``````` 578 | 579 | Request:: 580 | 581 | GET /xled/v1/device_name HTTP/1.1 582 | Host: 192.168.4.1 583 | X-Auth-Token: 5jPe+ONhwUY= 584 | 585 | Response:: 586 | 587 | HTTP/1.1 200 Ok 588 | Connection: close 589 | Content-Length: 37 590 | Content-Type: application/json 591 | 592 | {"name":"Twinkly_33AAFF","code":1000} 593 | 594 | Set device name 595 | --------------- 596 | 597 | Sets device name 598 | 599 | Since firmware version 1.99.18. 600 | 601 | HTTP request 602 | ```````````` 603 | 604 | `POST /xled/v1/device_name` 605 | 606 | `X-Auth-Token` 607 | Authentication token 608 | 609 | Parameters 610 | `````````` 611 | 612 | Parameters as JSON object. 613 | 614 | `name` 615 | (string) Desired device name. At most 32 characters. 616 | 617 | Response 618 | ```````` 619 | 620 | The response will be an object. 621 | 622 | `code` 623 | (integer), application return code. `1103` if too long. 624 | 625 | Example 626 | ``````` 627 | 628 | Request:: 629 | 630 | POST /xled/v1/device_name HTTP/1.1 631 | Host: 192.168.4.1 632 | Content-Type: application/json 633 | X-Auth-Token: 5jPe+ONhwUY= 634 | Content-Length: 26 635 | 636 | {"name": "Twinkly_33AAFF"} 637 | 638 | Response:: 639 | 640 | HTTP/1.1 200 Ok 641 | Connection: close 642 | Content-Length: 37 643 | Content-Type: application/json 644 | 645 | {"name":"Twinkly_33AAFF","code":1000} 646 | 647 | Echo 648 | ---- 649 | 650 | Responds with requested message. 651 | 652 | Since firmware version 1.99.18. 653 | 654 | HTTP request 655 | ```````````` 656 | 657 | `POST /xled/v1/echo` 658 | 659 | `X-Auth-Token` 660 | Authentication token 661 | 662 | Parameters 663 | `````````` 664 | 665 | Parameters must be an JSON object. There doesn't seem to be any requirement on a structure. 666 | 667 | Response 668 | ```````` 669 | 670 | The response will be an object. 671 | 672 | `code` 673 | (integer), application return code. Returns 1001 on error. 674 | 675 | `json` 676 | (object), contents is the same as the request. 677 | 678 | Example 679 | ``````` 680 | 681 | Request:: 682 | 683 | POST /xled/v1/echo HTTP/1.1 684 | Host: 192.168.4.1 685 | Content-Type: application/json 686 | X-Auth-Token: 5jPe+ONhwUY= 687 | Content-Length: 23 688 | 689 | {"message": "Hello!"}} 690 | 691 | Response:: 692 | 693 | HTTP/1.1 200 Ok 694 | Connection: close 695 | Content-Length: 44 696 | Content-Type: application/json 697 | 698 | {"json":{"message":"Hello!"},"code":1000} 699 | 700 | Get timer 701 | --------- 702 | 703 | Gets time when lights should be turned on and time to turn them off. 704 | 705 | Since firmware version 1.99.18. 706 | 707 | HTTP request 708 | ```````````` 709 | 710 | `GET /xled/v1/timer` 711 | 712 | `X-Auth-Token` 713 | Authentication token 714 | 715 | Response 716 | ```````` 717 | 718 | The response will be an object. 719 | 720 | `time_now` 721 | (integer) current time in seconds after midnight 722 | 723 | `time_on` 724 | (number) time when to turn lights on in seconds after midnight. -1 if not set 725 | 726 | `time_off` 727 | (number) time when to turn lights off in seconds after midnight. -1 if not set 728 | 729 | `code` 730 | (integer), application return code. Since firmware family "D" version: 2.3.8 and family "F" version: 2.5.6. 731 | 732 | Example 733 | ``````` 734 | 735 | Request:: 736 | 737 | GET /xled/v1/timer HTTP/1.1 738 | Host: 192.168.4.1 739 | X-Auth-Token: 5jPe+ONhwUY= 740 | 741 | Response:: 742 | 743 | HTTP/1.1 200 Ok 744 | Connection: close 745 | Content-Length: 45 746 | Content-Type: application/json 747 | 748 | {"time_now":17083,"time_on":-1,"time_off":-1} 749 | 750 | Set timer 751 | --------- 752 | 753 | Sets time when lights should be turned on and time to turn them off. 754 | 755 | Since firmware version 1.99.18. 756 | 757 | HTTP request 758 | ```````````` 759 | 760 | `POST /xled/v1/timer` 761 | 762 | `X-Auth-Token` 763 | Authentication token 764 | 765 | Parameters 766 | `````````` 767 | 768 | Parameters as JSON object. 769 | 770 | `time_now` 771 | (integer) current time in seconds after midnight 772 | 773 | `time_on` 774 | (number) time when to turn lights on in seconds after midnight. -1 if not set 775 | 776 | `time_off` 777 | (number) time when to turn lights off in seconds after midnight. -1 if not set 778 | 779 | Example 780 | ``````` 781 | 782 | Request to set current time to 2:00 AM, turn on lights at 1:00 AM and turn off at 4:00 AM:: 783 | 784 | POST /xled/v1/timer HTTP/1.1 785 | Host: 192.168.4.1 786 | Content-Type: application/json 787 | X-Auth-Token: 5jPe+ONhwUY= 788 | Content-Length: 51 789 | 790 | {"time_now": 120, "time_on": 60, "time_off": 240} 791 | 792 | Response:: 793 | 794 | HTTP/1.1 200 Ok 795 | Connection: close 796 | Content-Length: 13 797 | Content-Type: application/json 798 | 799 | {"code":1000} 800 | 801 | Get layout 802 | ---------- 803 | 804 | Since firmware version 1.99.18. 805 | 806 | HTTP request 807 | ```````````` 808 | 809 | `GET /xled/v1/led/layout/full` 810 | 811 | `X-Auth-Token` 812 | Authentication token 813 | 814 | Response 815 | ```````` 816 | 817 | Parameters as JSON object. 818 | 819 | `aspectXY` 820 | (integer), e.g. 0 821 | 822 | `aspectXZ` 823 | (integer), e.g. 0 824 | 825 | `coordinates` 826 | (array) 827 | 828 | `source` 829 | (string enum) 830 | 831 | `synthesized` 832 | (bool), e.g. false 833 | 834 | `uuid` 835 | (string), e.g. "00000000-0000-0000-0000-000000000000" 836 | 837 | Where each item of `coordinates` is an object: 838 | 839 | `x` 840 | (number) 841 | 842 | `y` 843 | (number) 844 | 845 | `z` 846 | (number) 847 | 848 | `source` is one of: 849 | 850 | * "linear" 851 | * "2d" 852 | * "3d" 853 | 854 | Upload layout 855 | ------------- 856 | 857 | Since firmware version 1.99.18. 858 | 859 | HTTP request 860 | ```````````` 861 | 862 | `POST /xled/v1/led/layout/full` 863 | 864 | `X-Auth-Token` 865 | Authentication token 866 | 867 | Parameters 868 | `````````` 869 | 870 | Parameters as JSON object. 871 | 872 | `aspectXY` 873 | (integer), e.g. 0 874 | 875 | `aspectXZ` 876 | (integer), e.g. 0 877 | 878 | `coordinates` 879 | (array) 880 | 881 | `source` 882 | (string enum) 883 | 884 | `synthesized` 885 | (bool), e.g. false 886 | 887 | Where each item of `coordinates` is an object: 888 | 889 | `x` 890 | (number) 891 | 892 | `y` 893 | (number) 894 | 895 | `z` 896 | (number) 897 | 898 | `source` is one of: 899 | 900 | * "linear" 901 | * "2d" 902 | * "3d" 903 | 904 | Response 905 | ```````` 906 | 907 | The response will be an object. 908 | 909 | `code` 910 | (integer), application return code. 911 | 912 | `parsed_coordinates` 913 | (integer) 914 | 915 | Delete layout 916 | ------------- 917 | 918 | HTTP request 919 | ```````````` 920 | 921 | `DELETE /xled/v1/led/layout/full` 922 | 923 | `X-Auth-Token` 924 | Authentication token 925 | 926 | Response 927 | ```````` 928 | 929 | The response will be an object. 930 | 931 | `code` 932 | (integer), application return code. 933 | 934 | Get LED operation mode 935 | ------------------------- 936 | 937 | Gets current LED operation mode. 938 | 939 | Since firmware version 1.99.18. 940 | 941 | HTTP request 942 | ```````````` 943 | 944 | `GET /xled/v1/led/mode` 945 | 946 | `X-Auth-Token` 947 | Authentication token 948 | 949 | Response 950 | ```````` 951 | 952 | The response will be an object. 953 | 954 | `code` 955 | (integer), application return code. 956 | 957 | `mode` 958 | (string) mode of operation. 959 | 960 | `shop_mode` 961 | (integer), by default 0. Since firmware version 2.4.21. 962 | 963 | Mode can be one of: 964 | 965 | * `off` - lights are turned off 966 | * `color` - lights show a static color 967 | * `demo` - demo mode, cycles through pre-defined effects 968 | * `effect` - plays a predefined effect 969 | * `movie` - plays an uploaded movie 970 | * `playlist` - cycles through playlist of uploaded movies 971 | * `rt` - receive effect in real time 972 | 973 | Example 974 | ``````` 975 | 976 | Request:: 977 | 978 | GET /xled/v1/led/mode HTTP/1.1 979 | Host: 192.168.4.1 980 | X-Auth-Token: 5jPe+ONhwUY= 981 | 982 | Response:: 983 | 984 | HTTP/1.1 200 OK 985 | Connection: close 986 | Content-Length: 28 987 | Content-Type: application/json 988 | 989 | {"mode":"movie","code":1000} 990 | 991 | Set LED operation mode 992 | ---------------------- 993 | 994 | Changes LED operation mode. 995 | 996 | Since firmware version 1.99.18. 997 | 998 | HTTP request 999 | ```````````` 1000 | 1001 | `POST /xled/v1/led/mode` 1002 | 1003 | `X-Auth-Token` 1004 | Authentication token 1005 | 1006 | Parameters 1007 | `````````` 1008 | 1009 | Parameters as JSON object. 1010 | 1011 | `mode` 1012 | (string) mode of operation. See LED operating modes in Protocol details. 1013 | 1014 | `effect_id` 1015 | (int), id of effect, e.g. 0. Set together with `mode: effect`. 1016 | 1017 | Response 1018 | ```````` 1019 | 1020 | The response will be an object. 1021 | 1022 | `code` 1023 | (integer), application return code. 1024 | 1025 | Example 1026 | ``````` 1027 | 1028 | Request:: 1029 | 1030 | POST /xled/v1/led/mode HTTP/1.1 1031 | Host: 192.168.4.1 1032 | Content-Type: application/json 1033 | X-Auth-Token: 5jPe+ONhwUY= 1034 | Content-Length: 15 1035 | 1036 | {"mode":"demo"} 1037 | 1038 | Response:: 1039 | 1040 | HTTP/1.1 200 Ok 1041 | Connection: close 1042 | Content-Length: 13 1043 | Content-Type: application/json 1044 | 1045 | {"code":1000} 1046 | 1047 | Get LED color 1048 | ------------- 1049 | 1050 | Gets the color shown when in color mode. 1051 | 1052 | Since firmware version 2.7.1 1053 | 1054 | HTTP request 1055 | ```````````` 1056 | 1057 | `GET /xled/v1/led/color` 1058 | 1059 | `X-Auth-Token` 1060 | Authentication token 1061 | 1062 | Response 1063 | ```````` 1064 | 1065 | The response will be an object. 1066 | 1067 | `hue` 1068 | (integer), hue component of HSV, in range 0..359 1069 | 1070 | `saturation` 1071 | (integer), saturation component of HSV, in range 0..255 1072 | 1073 | `value` 1074 | (integer), value component of HSV, in range 0..255 1075 | 1076 | `red` 1077 | (integer), red component of RGB, in range 0..255 1078 | 1079 | `green` 1080 | (integer), green component of RGB, in range 0..255 1081 | 1082 | `blue` 1083 | (integer), blue component of RGB, in range 0..255 1084 | 1085 | `code` 1086 | (integer), application return code. 1087 | 1088 | Example 1089 | ``````` 1090 | Request:: 1091 | 1092 | GET /xled/v1/led/color HTTP/1.1 1093 | Host: 192.168.4.1 1094 | Content-Type: application/json 1095 | X-Auth-Token: 5jPe+ONhwUY= 1096 | 1097 | Response:: 1098 | 1099 | HTTP/1.1 200 Ok 1100 | Connection: close 1101 | Content-Length: 84 1102 | Content-Type: application/json 1103 | 1104 | {"hue":56,"saturation":105,"value":255,"red":255,"green":248,"blue":150,"code":1000} 1105 | 1106 | Set LED color 1107 | ------------- 1108 | 1109 | Sets the color shown when in color mode. 1110 | 1111 | Since firmware version 2.7.1 1112 | 1113 | HTTP request 1114 | ```````````` 1115 | 1116 | `POST /xled/v1/led/color` 1117 | 1118 | `X-Auth-Token` 1119 | Authentication token 1120 | 1121 | Parameters 1122 | `````````` 1123 | 1124 | Parameters as JSON object. 1125 | 1126 | Either the three HSV components: 1127 | 1128 | `hue` 1129 | (integer), hue component of HSV, in range 0..359 1130 | 1131 | `saturation` 1132 | (integer), saturation component of HSV, in range 0..255 1133 | 1134 | `value` 1135 | (integer), value component of HSV, in range 0..255 1136 | 1137 | Or the three RGB components: 1138 | 1139 | `red` 1140 | (integer), red component of RGB, in range 0..255 1141 | 1142 | `green` 1143 | (integer), green component of RGB, in range 0..255 1144 | 1145 | `blue` 1146 | (integer), blue component of RGB, in range 0..255 1147 | 1148 | Response 1149 | ```````` 1150 | 1151 | The response will be an object. 1152 | 1153 | `code` 1154 | (integer), application return code. 1155 | 1156 | Example 1157 | ``````` 1158 | 1159 | Request:: 1160 | 1161 | POST /xled/v1/led/color HTTP/1.1 1162 | Host: 192.168.4.1 1163 | Content-Type: application/json 1164 | X-Auth-Token: 5jPe+ONhwUY= 1165 | Content-Length: 40 1166 | 1167 | {"hue":300,"saturation":255,"value":255} 1168 | 1169 | Response:: 1170 | 1171 | HTTP/1.1 200 Ok 1172 | Connection: close 1173 | Content-Length: 13 1174 | Content-Type: application/json 1175 | 1176 | {"code":1000} 1177 | 1178 | Get LED effects 1179 | --------------- 1180 | 1181 | Retrieve the identities of all available predefined effects. 1182 | 1183 | Since firmware version 1.99.18. 1184 | 1185 | HTTP request 1186 | ```````````` 1187 | 1188 | `GET /xled/v1/led/effects` 1189 | 1190 | `X-Auth-Token` 1191 | Authentication token 1192 | 1193 | Response 1194 | ```````` 1195 | 1196 | The response will be an object. 1197 | 1198 | `code` 1199 | (integer), application return code. 1200 | 1201 | `effects_number` 1202 | (integer), e.g. 5 until firmware version 2.4.30 and 15 since firmware version 2.5.6. 1203 | 1204 | `unique_ids` 1205 | (array), since firmware version 2.5.6. 1206 | 1207 | Item of `unique_ids` array is a UUID string. Default values are "00000000-0000-0000-0000-000000000001" up until "00000000-0000-0000-0000-00000000000F". 1208 | 1209 | Example 1210 | ``````` 1211 | Request:: 1212 | 1213 | GET /xled/v1/led/effects HTTP/1.1 1214 | Host: 192.168.4.1 1215 | Content-Type: application/json 1216 | X-Auth-Token: 5jPe+ONhwUY= 1217 | 1218 | Response:: 1219 | 1220 | HTTP/1.1 200 Ok 1221 | Connection: close 1222 | Content-Length: 32 1223 | Content-Type: application/json 1224 | 1225 | {"effects_number":5,"code":1000} 1226 | 1227 | Get current LED effect 1228 | ---------------------- 1229 | 1230 | Gets the id of the effect shown when in effect mode. 1231 | 1232 | Since firmware version 1.99.18. 1233 | 1234 | HTTP request 1235 | ```````````` 1236 | 1237 | `GET /xled/v1/led/effects/current` 1238 | 1239 | `X-Auth-Token` 1240 | Authentication token 1241 | 1242 | Response 1243 | ```````` 1244 | 1245 | The response will be an object. 1246 | 1247 | `code` 1248 | (integer), application return code. 1249 | 1250 | `unique_id` 1251 | (string), UUID. Since firmware version 2.5.6. 1252 | 1253 | `effect_id` 1254 | (integer), e.g. 0 1255 | 1256 | Example 1257 | ``````` 1258 | Request:: 1259 | 1260 | GET /xled/v1/led/effects/current HTTP/1.1 1261 | Host: 192.168.4.1 1262 | Content-Type: application/json 1263 | X-Auth-Token: 5jPe+ONhwUY= 1264 | 1265 | Response:: 1266 | 1267 | HTTP/1.1 200 Ok 1268 | Connection: close 1269 | Content-Length: 27 1270 | Content-Type: application/json 1271 | 1272 | {"effect_id":0,"code":1000} 1273 | 1274 | Set current LED effect 1275 | ---------------------- 1276 | 1277 | Sets which effect to show when in effect mode. 1278 | 1279 | Since firmware version 1.99.18. 1280 | 1281 | HTTP request 1282 | ```````````` 1283 | 1284 | `POST /xled/v1/led/effects/current` 1285 | 1286 | `X-Auth-Token` 1287 | Authentication token 1288 | 1289 | Parameters 1290 | `````````` 1291 | 1292 | Parameters as JSON object. 1293 | 1294 | `effect_id` 1295 | (int), id of effect, e.g. 0. 1296 | 1297 | Response 1298 | ```````` 1299 | 1300 | The response will be an object. 1301 | 1302 | `code` 1303 | (integer), application return code. 1304 | 1305 | Example 1306 | ``````` 1307 | 1308 | Request:: 1309 | 1310 | POST /xled/v1/led/effects/current HTTP/1.1 1311 | Host: 192.168.4.1 1312 | Content-Type: application/json 1313 | X-Auth-Token: 5jPe+ONhwUY= 1314 | Content-Length: 15 1315 | 1316 | {"effect_id":0} 1317 | 1318 | Response:: 1319 | 1320 | HTTP/1.1 200 Ok 1321 | Connection: close 1322 | Content-Length: 13 1323 | Content-Type: application/json 1324 | 1325 | {"code":1000} 1326 | 1327 | Get LED config 1328 | -------------- 1329 | 1330 | Since firmware version 1.99.18. 1331 | 1332 | HTTP request 1333 | ```````````` 1334 | 1335 | `GET /xled/v1/led/config` 1336 | 1337 | `X-Auth-Token` 1338 | Authentication token 1339 | 1340 | Response 1341 | ```````` 1342 | 1343 | The response will be an object. 1344 | 1345 | `strings` 1346 | Array of objects 1347 | 1348 | `code` 1349 | (integer), application return code. Since firmware version: 1.99.20. 1350 | 1351 | Item of strings array is object: 1352 | 1353 | `first_led_id` 1354 | (integer), e.g. 0 1355 | 1356 | `length` 1357 | (integer), e.g. 105 1358 | 1359 | Example 1360 | ``````` 1361 | 1362 | Request:: 1363 | 1364 | GET /xled/v1/led/config HTTP/1.1 1365 | Host: 192.168.4.1 1366 | X-Auth-Token: 5jPe+ONhwUY= 1367 | 1368 | Response from firmware family "D":: 1369 | 1370 | HTTP/1.1 200 Ok 1371 | Connection: close 1372 | Content-Length: 57 1373 | Content-Type: application/json 1374 | 1375 | {"strings":[{"first_led_id":0,"length":105}],"code":1000} 1376 | 1377 | Response from Icicle firmware family "G":: 1378 | 1379 | HTTP/1.1 200 OK 1380 | Server: esp-httpd/0.5 1381 | Transfer-Encoding: chunked 1382 | Content-Type: application/json 1383 | 1384 | {"strings":[{"first_led_id":0,"length":95},{"first_led_id":95,"length":95}],"code":1000} 1385 | 1386 | Set LED config 1387 | -------------- 1388 | 1389 | Since firmware version 1.99.18. 1390 | 1391 | HTTP request 1392 | ```````````` 1393 | 1394 | `POST /xled/v1/led/config` 1395 | 1396 | `X-Auth-Token` 1397 | Authentication token 1398 | 1399 | Parameters 1400 | `````````` 1401 | 1402 | Parameters as JSON object. 1403 | 1404 | `strings` 1405 | Array of objects 1406 | 1407 | Item of strings array is object: 1408 | 1409 | `first_led_id` 1410 | (integer), e.g. 0 1411 | 1412 | `length` 1413 | (integer), e.g. 105 1414 | 1415 | Response 1416 | ```````` 1417 | 1418 | The response will be an object. 1419 | 1420 | `code` 1421 | (integer), application return code. 1422 | 1423 | Example 1424 | ``````` 1425 | 1426 | Request:: 1427 | 1428 | POST /xled/v1/led/config HTTP/1.1 1429 | Host: 192.168.4.1 1430 | X-Auth-Token: 5jPe+ONhwUY= 1431 | Content-Type: application/json 1432 | Content-Length: 45 1433 | 1434 | {"strings":[{"first_led_id":0,"length":100}]} 1435 | 1436 | Response:: 1437 | 1438 | HTTP/1.1 200 Ok 1439 | Connection: close 1440 | Content-Length: 13 1441 | Content-Type: application/json 1442 | 1443 | {"code":1000} 1444 | 1445 | Upload full movie 1446 | ----------------- 1447 | 1448 | Effect is sent in body of the request. If mode is `movie` it starts playing this effect. 1449 | 1450 | Since firmware version 1.99.18. 1451 | 1452 | HTTP request 1453 | ```````````` 1454 | 1455 | `POST /xled/v1/led/movie/full` 1456 | 1457 | `X-Auth-Token` 1458 | Authentication token 1459 | 1460 | `Content-Type` 1461 | "application/octet-stream" 1462 | 1463 | Response 1464 | ```````` 1465 | 1466 | The response will be an object. 1467 | 1468 | `code` 1469 | (integer), application return code. 1470 | 1471 | `frames_number` 1472 | (integer) number of received frames 1473 | 1474 | Get LED movie config 1475 | -------------------- 1476 | 1477 | Since firmware version 1.99.18. 1478 | 1479 | HTTP request 1480 | ```````````` 1481 | 1482 | `GET /xled/v1/led/movie/config` 1483 | 1484 | `X-Auth-Token` 1485 | Authentication token 1486 | 1487 | Response 1488 | ```````` 1489 | 1490 | The response will be an object. 1491 | 1492 | `frame_delay` 1493 | (integer) 1494 | 1495 | `leds_number` 1496 | (integer) seems to be total number of LEDs to use 1497 | 1498 | `loop_type` 1499 | (integer), e.g. 0 1500 | 1501 | `frames_number` 1502 | (integer) 1503 | 1504 | `sync` 1505 | (object) 1506 | 1507 | `mic` 1508 | (object), since firmware family "G" version 2.4.21 until 2.4.30 and firmware family "F" version 2.4.14 until 2.4.30. 1509 | 1510 | `code` 1511 | (integer), application return code. 1512 | 1513 | Contents of object `sync`: 1514 | 1515 | `mode` 1516 | (string) 1517 | 1518 | `slave_id` 1519 | (string), e.g. "". Defined if mode is "slave". Since firmware version 2.5.6 not present if empty 1520 | 1521 | `master_id` 1522 | (string), e.g. "". Defined if mode is "slave" or "master". Since firmware version 2.5.6 not present if empty 1523 | 1524 | `compat_mode` 1525 | (number), default 0. Since firmware version 2.5.6. 1526 | 1527 | Contents of object `mic`: 1528 | 1529 | `filters` 1530 | array of objects 1531 | 1532 | `brightness_depth` 1533 | (integer) 1534 | 1535 | `hue_depth` 1536 | (integer) 1537 | 1538 | `value_depth` 1539 | (integer) 1540 | 1541 | `saturation_depth` 1542 | (integer) 1543 | 1544 | Contents of `mode` is one of: 1545 | 1546 | * "none" 1547 | * "master" 1548 | * "slave" 1549 | 1550 | Contents of `compat_mode` is one of: 1551 | 1552 | * 0 1553 | * 1 - maybe if joined with older version, e.g. gen I device? 1554 | 1555 | Example 1556 | ``````` 1557 | 1558 | Request:: 1559 | 1560 | GET /xled/v1/led/movie/config HTTP/1.1 1561 | Host: 192.168.4.1 1562 | X-Auth-Token: 5jPe+ONhwUY= 1563 | 1564 | Response from firmware family "D":: 1565 | 1566 | HTTP/1.1 200 Ok 1567 | Connection: close 1568 | Content-Length: 134 1569 | Content-Type: application/json 1570 | 1571 | {"frame_delay":40,"leds_number":105,"loop_type":0,"frames_number":325,"sync":{"mode":"none","slave_id":"","master_id":""},"code":1000} 1572 | 1573 | Response from firmware family "G":: 1574 | 1575 | HTTP/1.1 200 OK 1576 | Server: esp-httpd/0.5 1577 | Transfer-Encoding: chunked 1578 | Content-Type: application/json 1579 | 1580 | {"frame_delay":0,"leds_number":0,"loop_type":0,"frames_number":0,"sync":{"mode":"none","slave_id":"","master_id":""},"mic":{"filters":[],"brightness_depth":0,"hue_depth":0,"value_depth":0,"saturation_depth":0},"code":1000} 1581 | 1582 | Set LED movie config 1583 | -------------------- 1584 | 1585 | Since firmware version 1.99.18. 1586 | 1587 | HTTP request 1588 | ```````````` 1589 | 1590 | `POST /xled/v1/led/movie/config` 1591 | 1592 | `X-Auth-Token` 1593 | Authentication token 1594 | 1595 | Parameters 1596 | `````````` 1597 | 1598 | Parameters as JSON object. 1599 | 1600 | `frame_delay` 1601 | (integer) the delay in milliseconds between two consecutive frames. For *n* fps, this is *1000 / n*. 1602 | 1603 | `leds_number` 1604 | (integer) seems to be total number of LEDs to use 1605 | 1606 | `frames_number` 1607 | (integer) 1608 | 1609 | Response 1610 | ```````` 1611 | 1612 | The response will be an object. 1613 | 1614 | `code` 1615 | (integer), application return code. 1616 | 1617 | Get brightness 1618 | -------------- 1619 | 1620 | Gets the current brightness level. 1621 | 1622 | * For devices with firmware family "D" since version 2.3.5. 1623 | * For devices with firmware family "F" since 2.4.2. 1624 | * For devices with firmware family "G" since version 2.4.21. 1625 | 1626 | HTTP request 1627 | ```````````` 1628 | 1629 | `GET /xled/v1/led/out/brightness` 1630 | 1631 | `X-Auth-Token` 1632 | Authentication token 1633 | 1634 | Response 1635 | ```````` 1636 | 1637 | The response will be an object. 1638 | 1639 | `code` 1640 | (integer), application return code. 1641 | 1642 | `mode` 1643 | (string) one of "enabled" or "disabled". 1644 | 1645 | `value` 1646 | (integer) brightness level in range of 0..100 1647 | 1648 | Mode string displays if the dimming is applied. The led shines at full 1649 | brightness regardless of what value is set if the `mode` is `disabled`. 1650 | Brightness level value represents percent so 0 is dark and 100 is maximum 1651 | brightness. 1652 | 1653 | Example 1654 | ``````` 1655 | 1656 | Request:: 1657 | 1658 | GET /xled/v1/led/out/brightness HTTP/1.1 1659 | Host: 192.168.4.1 1660 | X-Auth-Token: 5jPe+ONhwUY= 1661 | 1662 | Response:: 1663 | 1664 | HTTP/1.1 200 Ok 1665 | Connection: close 1666 | Content-Length: 42 1667 | Content-Type: application/json 1668 | 1669 | {"value":100,"mode":"enabled","code":1000} 1670 | 1671 | Set brightness 1672 | -------------- 1673 | 1674 | Sets the brightness level. 1675 | 1676 | * For devices with firmware family "D" since version 2.3.5. 1677 | * For devices with firmware family "F" since 2.4.2. 1678 | * For devices with firmware family "G" since version 2.4.21. 1679 | 1680 | HTTP request 1681 | ```````````` 1682 | 1683 | `POST /xled/v1/led/out/brightness` 1684 | 1685 | `X-Auth-Token` 1686 | Authentication token 1687 | 1688 | Parameters 1689 | `````````` 1690 | 1691 | Parameters as JSON object. 1692 | 1693 | `mode` 1694 | (string) one of "enabled", "disabled" 1695 | 1696 | `type` 1697 | (string) either "A" for Absolute value or "R" for Relative value 1698 | 1699 | `value` 1700 | (signed integer) brightness level in range of 0..100 if type is "A", or change of level in range -100..100 if type is "R" 1701 | 1702 | When `mode` is "disabled" no dimming is applied and the led works at full 1703 | brightness. It is not necessary to submit all the parameters, basically it 1704 | would work if only `value` or `mode` is supplied. `type` parameter can be 1705 | omitted ("A" is the default). The brightness level value is in percent 1706 | so 0 is dark and maximum meaningful value is 100. Greater values are possible 1707 | but don't seem to have any effect. 1708 | 1709 | Response 1710 | ```````` 1711 | 1712 | The response will be an object. 1713 | 1714 | `code` 1715 | (integer), application return code. 1716 | 1717 | Example 1718 | ``````` 1719 | 1720 | Set the brightness level to 10%: 1721 | 1722 | Request:: 1723 | 1724 | POST /xled/v1/led/out/brightness HTTP/1.1 1725 | Host: 192.168.4.1 1726 | X-Auth-Token: 5jPe+ONhwUY= 1727 | Content-Type: application/json 1728 | Content-Length: 41 1729 | 1730 | {"mode":"enabled","type":"A","value":100} 1731 | 1732 | Response:: 1733 | 1734 | HTTP/1.1 200 Ok 1735 | Connection: close 1736 | Content-Length: 13 1737 | 1738 | {"code":1000} 1739 | 1740 | Get saturation 1741 | -------------- 1742 | 1743 | Gets the current saturation level. 1744 | 1745 | * For devices with firmware family "D" since version 2.3.5. 1746 | * For devices with firmware family "F" since 2.4.2. 1747 | * For devices with firmware family "G" since version 2.4.21. 1748 | 1749 | HTTP request 1750 | ```````````` 1751 | 1752 | `GET /xled/v1/led/out/saturation` 1753 | 1754 | `X-Auth-Token` 1755 | Authentication token 1756 | 1757 | Response 1758 | ```````` 1759 | 1760 | The response will be an object. 1761 | 1762 | `code` 1763 | (integer), application return code. 1764 | 1765 | `mode` 1766 | (string) one of "enabled" or "disabled". 1767 | 1768 | `value` 1769 | (integer) saturation level in range of 0..100 1770 | 1771 | Mode string displays if desaturation is applied. The led shines with full 1772 | color regardless of what value is set if the `mode` is `disabled`. 1773 | Saturation level value represents percent so 0 is completely black-and-white 1774 | and 100 is full color. 1775 | 1776 | Example 1777 | ``````` 1778 | 1779 | Request:: 1780 | 1781 | GET /xled/v1/led/out/saturation HTTP/1.1 1782 | Host: 192.168.4.1 1783 | X-Auth-Token: 5jPe+ONhwUY= 1784 | 1785 | Response:: 1786 | 1787 | HTTP/1.1 200 Ok 1788 | Connection: close 1789 | Content-Length: 37 1790 | Content-Type: application/json 1791 | 1792 | {"value":"100,"mode":"enabled","code":1000} 1793 | 1794 | Set saturation 1795 | -------------- 1796 | 1797 | Sets the saturation level. 1798 | 1799 | * For devices with firmware family "D" since version 2.3.5. 1800 | * For devices with firmware family "F" since 2.4.2. 1801 | * For devices with firmware family "G" since version 2.4.21. 1802 | 1803 | HTTP request 1804 | ```````````` 1805 | 1806 | `POST /xled/v1/led/out/saturation` 1807 | 1808 | `X-Auth-Token` 1809 | Authentication token 1810 | 1811 | Parameters 1812 | `````````` 1813 | 1814 | Parameters as JSON object. 1815 | 1816 | `mode` 1817 | (string) one of "enabled", "disabled" 1818 | 1819 | `type` 1820 | (string) either "A" for Absolute value or "R" for Relative value 1821 | 1822 | `value` 1823 | (signed integer) saturation level in range of 0..100 if type is "A", or change of level in range -100..100 if type is "R" 1824 | 1825 | When `mode` is "disabled" no desaturation is applied and the led works at full 1826 | color. It is not necessary to submit all the parameters, basically it 1827 | would work if only `value` or `mode` is supplied. `type` parameter can be 1828 | omitted ("A" is the default). The saturation level value is in percent 1829 | so 0 is completely black-and-white and maximum meaningful value is 100. Greater 1830 | values are possible but don't seem to have any effect. 1831 | 1832 | Response 1833 | ```````` 1834 | 1835 | The response will be an object. 1836 | 1837 | `code` 1838 | (integer), application return code. 1839 | 1840 | Example 1841 | ``````` 1842 | 1843 | Decrease the saturation level with 20%: 1844 | 1845 | Request:: 1846 | 1847 | POST /xled/v1/led/out/saturation HTTP/1.1 1848 | Host: 192.168.4.1 1849 | X-Auth-Token: 5jPe+ONhwUY= 1850 | Content-Type: application/json 1851 | Content-Length: 43 1852 | 1853 | {"mode":"enabled","type":"R","value":-20} 1854 | 1855 | Response:: 1856 | 1857 | HTTP/1.1 200 Ok 1858 | Connection: close 1859 | Content-Length: 13 1860 | 1861 | {"code":1000} 1862 | 1863 | Set LED driver parameters 1864 | ------------------------- 1865 | 1866 | Since firmware version 1.99.18. 1867 | 1868 | HTTP request 1869 | ```````````` 1870 | 1871 | `POST /xled/v1/led/driver_params` 1872 | 1873 | `X-Auth-Token` 1874 | Authentication token 1875 | 1876 | Parameters 1877 | `````````` 1878 | 1879 | Parameters as JSON object. 1880 | 1881 | `t0h` 1882 | (integer) 1883 | 1884 | `t0l` 1885 | (integer) 1886 | 1887 | `t1h` 1888 | (integer) 1889 | 1890 | `t1l` 1891 | (integer) 1892 | 1893 | `tendh` 1894 | (integer) 1895 | 1896 | `tendl` 1897 | (integer) 1898 | 1899 | Response 1900 | ```````` 1901 | 1902 | The response will be an object. 1903 | 1904 | `code` 1905 | (integer), application return code 1906 | 1907 | Reset LED 1908 | --------- 1909 | 1910 | HTTP request 1911 | ```````````` 1912 | 1913 | `GET /xled/v1/led/reset` 1914 | 1915 | `X-Auth-Token` 1916 | Authentication token 1917 | 1918 | Response 1919 | ```````` 1920 | 1921 | The response will be an object. 1922 | 1923 | `code` 1924 | (integer), application return code. 1925 | 1926 | Reset2 LED 1927 | ---------- 1928 | 1929 | Maybe reboot? 1930 | 1931 | HTTP request 1932 | ```````````` 1933 | 1934 | `GET /xled/v1/led/reset2` 1935 | 1936 | `X-Auth-Token` 1937 | Authentication token 1938 | 1939 | Response 1940 | ```````` 1941 | 1942 | The response will be an object. 1943 | 1944 | `code` 1945 | (integer), application return code. 1946 | 1947 | Send Realtime Frame 1948 | ------------------- 1949 | 1950 | Used by application during lights mapping. 1951 | 1952 | Frame without any header is sent in the request body. 1953 | 1954 | HTTP request 1955 | ```````````` 1956 | 1957 | `POST /xled/v1/led/rt/frame` 1958 | 1959 | `X-Auth-Token` 1960 | Authentication token 1961 | 1962 | `Content-Type` 1963 | "application/octet-stream" 1964 | 1965 | Response 1966 | ```````` 1967 | 1968 | The response will be an object. 1969 | 1970 | `code` 1971 | (integer), application return code. 1972 | 1973 | Get firmware version 1974 | -------------------- 1975 | 1976 | Note: no authentication needed. 1977 | 1978 | Since firmware version 1.99.18. 1979 | 1980 | HTTP request 1981 | ```````````` 1982 | 1983 | `GET /xled/v1/fw/version` 1984 | 1985 | Response 1986 | ```````` 1987 | 1988 | The response will be an object. 1989 | 1990 | `code` 1991 | (integer), application return code. 1992 | 1993 | `version` 1994 | (string) 1995 | 1996 | Example 1997 | ``````` 1998 | 1999 | Request:: 2000 | 2001 | GET /xled/v1/fw/version HTTP/1.1 2002 | Host: 192.168.4.1 2003 | Accept: */* 2004 | 2005 | Response:: 2006 | 2007 | HTTP/1.1 200 Ok 2008 | Connection: close 2009 | Content-Length: 33 2010 | Content-Type: application/json 2011 | 2012 | {"version":"1.99.24","code":1000} 2013 | 2014 | Get Status 2015 | ---------- 2016 | 2017 | Since firmware version 1.99.18. 2018 | 2019 | HTTP request 2020 | ```````````` 2021 | 2022 | `GET /xled/v1/status` 2023 | 2024 | Response 2025 | ```````` 2026 | 2027 | The response will be an object. 2028 | 2029 | `code` 2030 | (integer), application return code. 2031 | 2032 | Example 2033 | ``````` 2034 | 2035 | Request:: 2036 | 2037 | GET /xled/v1/status HTTP/1.1 2038 | Host: 192.168.4.1 2039 | Content-Type: application/json 2040 | 2041 | Response:: 2042 | 2043 | HTTP/1.1 200 Ok 2044 | Connection: close 2045 | Content-Length: 13 2046 | Content-Type: application/json 2047 | 2048 | {"code":1000} 2049 | 2050 | Update firmware 2051 | --------------- 2052 | 2053 | Initiates firmware update. 2054 | 2055 | Since firmware version 1.99.18. 2056 | 2057 | HTTP request 2058 | ```````````` 2059 | 2060 | `POST /xled/v1/fw/update` 2061 | 2062 | `X-Auth-Token` 2063 | Authentication token 2064 | 2065 | Parameters 2066 | `````````` 2067 | 2068 | Parameters as JSON object. 2069 | 2070 | `checksum` 2071 | (object) 2072 | 2073 | Checksum object parameters for generation I devices: 2074 | 2075 | `stage0_sha1sum` 2076 | (string) SHA1 digest of first stage 2077 | 2078 | `stage1_sha1sum` 2079 | (string) SHA1 digest of second stage 2080 | 2081 | Checksum object parameters for generation II devices: 2082 | 2083 | `stage0_sha1sum` 2084 | (string) SHA1 digest of first stage 2085 | 2086 | Response 2087 | ```````` 2088 | 2089 | The response will be an object. 2090 | 2091 | `code` 2092 | (integer), application return code. 2093 | 2094 | Example 2095 | ``````` 2096 | 2097 | Request for generation I device:: 2098 | 2099 | POST /xled/v1/fw/update HTTP/1.1 2100 | X-Auth-Token: 5jPe+ONhwUY= 2101 | Content-Type: application/json 2102 | Content-Length: 134 2103 | Host: 192.168.4.1 2104 | 2105 | {"checksum":{"stage0_sha1sum":"1c705292285a1a5b8558f7b39abd22c5550606b5","stage1_sha1sum":"ac691b8d4563dcdbb3f837bf3db2ebf56fe77fbe"}} 2106 | 2107 | Response:: 2108 | 2109 | HTTP/1.1 200 Ok 2110 | Connection: close 2111 | Content-Length: 13 2112 | Content-Type: application/json 2113 | 2114 | {"code":1000} 2115 | 2116 | Upload first stage of firmware 2117 | ------------------------------ 2118 | 2119 | First stage of firmware is uploaded in body of the request. 2120 | 2121 | Since firmware version 1.99.18. 2122 | 2123 | HTTP request 2124 | ```````````` 2125 | 2126 | `POST /xled/v1/fw/0/update` 2127 | 2128 | `X-Auth-Token` 2129 | Authentication token 2130 | 2131 | `Content-Type` 2132 | "application/octet-stream" 2133 | 2134 | Response 2135 | ```````` 2136 | 2137 | The response will be an object. 2138 | 2139 | `code` 2140 | (integer), application return code. 2141 | 2142 | `sha1sum` 2143 | SHA1 digest of uploaded firmware. 2144 | 2145 | Upload second stage of firmware 2146 | ------------------------------- 2147 | 2148 | Second stage of firmware is uploaded in body of the request. 2149 | 2150 | Since firmware version 1.99.18. 2151 | 2152 | Used only for generation I devices. 2153 | 2154 | HTTP request 2155 | ```````````` 2156 | 2157 | `POST /xled/v1/fw/1/update` 2158 | 2159 | `X-Auth-Token` 2160 | Authentication token 2161 | 2162 | `Content-Type` 2163 | "application/octet-stream" 2164 | 2165 | Response 2166 | ```````` 2167 | 2168 | The response will be an object. 2169 | 2170 | `code` 2171 | (integer), application return code. 2172 | 2173 | `sha1sum` 2174 | SHA1 digest of uploaded firmware. 2175 | 2176 | Get list of movies 2177 | ------------------ 2178 | 2179 | Retrieve the identities and parameters of all uploaded movies. 2180 | 2181 | Available since firmware version 2.5.6. 2182 | 2183 | HTTP request 2184 | ```````````` 2185 | 2186 | `GET /xled/v1/movies` 2187 | 2188 | `X-Auth-Token` 2189 | Authentication token 2190 | 2191 | Response 2192 | ```````` 2193 | 2194 | The response will be an object. 2195 | 2196 | `code` 2197 | (integer), application return code. 2198 | 2199 | `movies` 2200 | Array of objects 2201 | 2202 | `available_frames` 2203 | (integer), e.g. 992 2204 | 2205 | `max_capacity` 2206 | (integer), e.g. 992 2207 | 2208 | Where each item of `movies` is an object. 2209 | 2210 | `id` 2211 | (integer), e.g. 0 2212 | 2213 | `name` 2214 | (string) 2215 | 2216 | `unique_id` 2217 | (string), UUID 2218 | 2219 | `descriptor_type` 2220 | (string), e.g "rgbw_raw" for firmware family "G" or "rgb_raw" for firmware family "F" 2221 | 2222 | `leds_per_frame` 2223 | (integer), e.g. 210 2224 | 2225 | `frames_number` 2226 | (integer), e.g. 4 2227 | 2228 | `fps` 2229 | (integer), e.g. 0 2230 | 2231 | Example 2232 | ``````` 2233 | 2234 | Request:: 2235 | 2236 | GET /xled/v1/movies HTTP/1.1 2237 | Host: 192.168.1.2 2238 | X-Auth-Token: 5jPe+ONhwUY= 2239 | 2240 | Response with empty list of movies:: 2241 | 2242 | HTTP/1.1 200 OK 2243 | Server: esp-httpd/0.5 2244 | Transfer-Encoding: chunked 2245 | Content-Type: application/json 2246 | 2247 | {"movies":[],"available_frames":992,"max_capacity":992,"code":1000} 2248 | 2249 | Delete movies 2250 | ------------- 2251 | 2252 | Remove all uploaded movies. 2253 | 2254 | Any existing playlist will be removed as well. This call only works if 2255 | the device is not in movie or playlist mode. 2256 | 2257 | Available since firmware version 2.5.6. 2258 | 2259 | HTTP request 2260 | ```````````` 2261 | 2262 | `DELETE /xled/v1/movies` 2263 | 2264 | `X-Auth-Token` 2265 | Authentication token 2266 | 2267 | Response 2268 | ```````` 2269 | 2270 | The response will be an object. 2271 | 2272 | `code` 2273 | (integer), application return code. 2274 | 2275 | Create new movie entry 2276 | ---------------------- 2277 | 2278 | Available since firmware version 2.5.6. 2279 | 2280 | HTTP request 2281 | ```````````` 2282 | 2283 | `POST /xled/v1/movies/new` 2284 | 2285 | `X-Auth-Token` 2286 | Authentication token 2287 | 2288 | Parameters 2289 | `````````` 2290 | 2291 | Parameters as JSON object. 2292 | 2293 | `name` 2294 | (string) 2295 | 2296 | `unique_id` 2297 | (string), UUID 2298 | 2299 | `descriptor_type` 2300 | (string), e.g "rgbw_raw", 2301 | 2302 | `leds_per_frame` 2303 | (integer), e.g. 210 2304 | 2305 | `frames_number` 2306 | (integer), e.g. 4 2307 | 2308 | `fps` 2309 | (integer), e.g. 0 2310 | 2311 | Response 2312 | ```````` 2313 | 2314 | The response will be an object. 2315 | 2316 | `code` 2317 | (integer), application return code. 2318 | 2319 | Upload new movie to list of movies 2320 | ---------------------------------- 2321 | 2322 | Available since firmware version 2.5.6. 2323 | 2324 | Effect is received in body of the request. This call must be preceeded by a call to `movies/new`. 2325 | 2326 | HTTP request 2327 | ```````````` 2328 | 2329 | `POST /xled/v1/movies/full` 2330 | 2331 | `X-Auth-Token` 2332 | Authentication token 2333 | 2334 | `Content-Type` 2335 | "application/octet-stream" 2336 | 2337 | Response 2338 | ```````` 2339 | 2340 | The response will be an object. 2341 | 2342 | `code` 2343 | (integer), application return code. 2344 | 2345 | 2346 | Get current movie 2347 | ----------------- 2348 | 2349 | Gets the id of the movie shown when in movie mode. 2350 | 2351 | Since firmware version 2.5.6. 2352 | 2353 | HTTP request 2354 | ```````````` 2355 | 2356 | `GET /xled/v1/led/movies/current` 2357 | 2358 | `X-Auth-Token` 2359 | Authentication token 2360 | 2361 | Response 2362 | ```````` 2363 | 2364 | The response will be an object. 2365 | 2366 | `code` 2367 | (integer), application return code. 2368 | 2369 | `id` 2370 | (integer), numeric id of movie, in range 0 .. 15 2371 | 2372 | `unique_id` 2373 | (string), UUID of movie. 2374 | 2375 | `name` 2376 | (string), name of movie. 2377 | 2378 | Example 2379 | ``````` 2380 | Request:: 2381 | 2382 | GET /xled/v1/led/movies/current HTTP/1.1 2383 | Host: 192.168.4.1 2384 | Content-Type: application/json 2385 | X-Auth-Token: 5jPe+ONhwUY= 2386 | 2387 | Response:: 2388 | 2389 | HTTP/1.1 200 Ok 2390 | Connection: close 2391 | Content-Length: 81 2392 | Content-Type: application/json 2393 | 2394 | {"id":0,"unique_id":"00000000-0000-0000-0000-800000000000","name":"","code":1000} 2395 | 2396 | Set current movie 2397 | ----------------- 2398 | 2399 | Sets which movie to show when in movie mode. 2400 | 2401 | Since firmware version 2.5.6. 2402 | 2403 | HTTP request 2404 | ```````````` 2405 | 2406 | `POST /xled/v1/led/movies/current` 2407 | 2408 | `X-Auth-Token` 2409 | Authentication token 2410 | 2411 | Parameters 2412 | `````````` 2413 | 2414 | Parameters as JSON object. 2415 | 2416 | `id` 2417 | (int), id of movie, in range 0 .. 15. 2418 | 2419 | Response 2420 | ```````` 2421 | 2422 | The response will be an object. 2423 | 2424 | `code` 2425 | (integer), application return code. 2426 | 2427 | Example 2428 | ``````` 2429 | 2430 | Request:: 2431 | 2432 | POST /xled/v1/led/movies/current HTTP/1.1 2433 | Host: 192.168.4.1 2434 | Content-Type: application/json 2435 | X-Auth-Token: 5jPe+ONhwUY= 2436 | Content-Length: 8 2437 | 2438 | {"id":0} 2439 | 2440 | Response:: 2441 | 2442 | HTTP/1.1 200 Ok 2443 | Connection: close 2444 | Content-Length: 13 2445 | Content-Type: application/json 2446 | 2447 | {"code":1000} 2448 | 2449 | Initiate WiFi network scan 2450 | -------------------------- 2451 | 2452 | Since firmware version 1.99.18. 2453 | 2454 | HTTP request 2455 | ```````````` 2456 | 2457 | `GET /xled/v1/network/scan` 2458 | 2459 | `X-Auth-Token` 2460 | Authentication token 2461 | 2462 | Response 2463 | ```````` 2464 | 2465 | The response will be an object. 2466 | 2467 | `code` 2468 | (integer), application return code. 2469 | 2470 | Get results of WiFi network scan 2471 | -------------------------------- 2472 | 2473 | Since firmware version 1.99.18. 2474 | 2475 | HTTP request 2476 | ```````````` 2477 | 2478 | `GET /xled/v1/network/scan_results` 2479 | 2480 | `X-Auth-Token` 2481 | Authentication token 2482 | 2483 | Response 2484 | ```````` 2485 | 2486 | The response will be an object. 2487 | 2488 | `code` 2489 | (integer), application return code. 2490 | 2491 | `networks` 2492 | Array of objects 2493 | 2494 | Item of networks array is object: 2495 | 2496 | `ssid` 2497 | (string) 2498 | 2499 | `mac` 2500 | (string) 2501 | 2502 | `rssi` 2503 | (number) negative number 2504 | 2505 | `channel` 2506 | (integer) 2507 | 2508 | `enc` 2509 | One of numbers 0 (Open), 1 (WEP), 2 (WPA-PSK), 3 (WPA2-PSK), 4 (WPA-PSK + WPA2-PSK), 5 (WPA2-EAP). 2510 | 2511 | Response seems to correspond with `AT command CWLAP `_. 2512 | 2513 | Get network status 2514 | ------------------ 2515 | 2516 | Gets network mode operation. 2517 | 2518 | Since firmware version 1.99.18. 2519 | 2520 | HTTP request 2521 | ```````````` 2522 | 2523 | `GET /xled/v1/network/status` 2524 | 2525 | `X-Auth-Token` 2526 | Authentication token 2527 | 2528 | Response 2529 | ```````` 2530 | The response will be an object. 2531 | 2532 | `mode` 2533 | (enum) 1 or 2 2534 | 2535 | `station` 2536 | (object) 2537 | 2538 | `ap` 2539 | (object) 2540 | 2541 | `code` 2542 | (integer), application return code. 2543 | 2544 | Contents of object `station` for firmware family "D": 2545 | 2546 | `ssid` 2547 | (string), SSID of a WiFi network to connect to 2548 | 2549 | `ip` 2550 | (string), IP address of the device 2551 | 2552 | `gw` 2553 | (string), IP address of the gateway 2554 | 2555 | `mask` 2556 | (string), subnet mask 2557 | 2558 | `status` 2559 | (integer), status of the network connection: 5 = connected, 255 = AP is used 2560 | 2561 | Contents of object `station` for firmware family "G" since firmware version 2.4.21 and "F" since 2.2.1: 2562 | 2563 | `ssid` 2564 | (string), SSID of a WiFi network to connect to. If empty string is passed it defaults to prefix `ESP_` instead of `Twinkly_`. 2565 | 2566 | `ip` 2567 | (string), IP address of the device 2568 | 2569 | `gw` 2570 | (string), IP address of the gateway 2571 | 2572 | `mask` 2573 | (string), subnet mask 2574 | 2575 | Contents of object `ap`: 2576 | 2577 | `ssid` 2578 | (string), SSID of the device 2579 | 2580 | `channel` 2581 | (integer), channel number 2582 | 2583 | `ip` 2584 | (string), IP address 2585 | 2586 | `enc` 2587 | (enum), 0 for no encryption, 2 for WPA1, 3 for WPA2, 4 for WPA1+WPA2 2588 | 2589 | `ssid_hidden` 2590 | (integer), default 0. Since firmware version 2.4.25. 2591 | 2592 | `max_connection` 2593 | (integer), default 4. Since firmware version 2.4.25. 2594 | 2595 | `password_changed` 2596 | (integer), either hidden or set to 1 if default password for AP was changed. 2597 | 2598 | Example 2599 | ``````` 2600 | 2601 | Request:: 2602 | 2603 | GET /xled/v1/network/status HTTP/1.1 2604 | Host: 192.168.1.2 2605 | X-Auth-Token: 5jPe+ONhwUY= 2606 | 2607 | Response:: 2608 | 2609 | HTTP/1.1 200 Ok 2610 | Connection: close 2611 | Content-Length: 187 2612 | Content-Type: application/json 2613 | 2614 | {"mode":1,"station":{"ssid":"home","ip":"192.168.1.2","gw":"192.168.1.1","mask":"255.255.255.0","status":5},"ap":{"ssid":"Twinkly_33AAFF","channel":11,"ip":"0.0.0.0","enc":0},"code":1000} 2615 | 2616 | Set network status 2617 | ------------------ 2618 | 2619 | Sets network mode operation. 2620 | 2621 | Since firmware version 1.99.18. 2622 | 2623 | HTTP request 2624 | ```````````` 2625 | 2626 | `POST /xled/v1/network/status` 2627 | 2628 | `X-Auth-Token` 2629 | Authentication token 2630 | 2631 | Parameters 2632 | `````````` 2633 | 2634 | Parameters as JSON object. 2635 | 2636 | `mode` 2637 | (enum), required: 1 or 2 2638 | 2639 | `station` 2640 | (object) optional, if mode set to 1 this parameter could provide additional details. 2641 | 2642 | `ap` 2643 | (object) optional, if mode set to 2 this parameter could provide additional details. 2644 | 2645 | `station` object parameters: 2646 | 2647 | `dhcp` 2648 | (integer) 1 2649 | 2650 | `ssid` 2651 | (string) SSID of a WiFi network until firmare version 2.4.25 2652 | 2653 | `encssid` 2654 | (string) encrypted SSID of a WiFi network since firmare version 2.4.30. 2655 | 2656 | `encpassword` 2657 | (string) encrypted password. 2658 | 2659 | `ap` object parameters: 2660 | 2661 | `ssid` 2662 | (string), required SSID of a WiFi network 2663 | 2664 | `encpassword` 2665 | (string), optional encrypted password. 2666 | 2667 | `password` 2668 | (string), optional plaintext password. Since firmware version 2.4.25 (?). 2669 | 2670 | `enc` 2671 | (enum), optional type of encryption. See above in Get network status. Defaults to 0 if not part of the request. If a request has `enc` value 1, get will return 0 as well. 2672 | 2673 | `channel` 2674 | (integer), optional 2675 | 2676 | `ssid_hidden` 2677 | (integer), optional, 0 to broadcast SSID, 1 to hide. Since firmware version 2.4.25. 2678 | 2679 | `max_connection` 2680 | (integer), optional, value from 1 to 4. Since firmware version 2.4.25. 2681 | 2682 | Response 2683 | ```````` 2684 | 2685 | The response will be an object. 2686 | 2687 | `code` 2688 | (integer), application return code. 2689 | 2690 | Example 2691 | ``````` 2692 | 2693 | Request to change network mode to client and connect to SSID "home" with password "Twinkly". Encoded with MAC address '5C:CF:7F:33:AA:FF':: 2694 | 2695 | POST /xled/v1/network/status HTTP/1.1 2696 | Host: 192.168.4.1 2697 | Content-Type: application/json 2698 | X-Auth-Token: 5jPe+ONhwUY= 2699 | Content-Length: 150 2700 | 2701 | {"mode":1,"station":{"ssid":"home","encpassword":"e4XXiiUhg4J1FnJEfUQ0BhIji2HGVk1NHU5vGCHfyclFdX6R8Nd9BSXVKS5nj2FXGU6SWv9CIzztfAvGgTGLUw==","dhcp":1}} 2702 | 2703 | Request to change network mode to AP:: 2704 | 2705 | POST /xled/v1/network/status HTTP/1.1 2706 | Host: 192.168.1.100 2707 | Content-Type: application/json 2708 | X-Auth-Token: 5jPe+ONhwUY= 2709 | Content-Length: 10 2710 | 2711 | {"mode":2} 2712 | 2713 | Get MQTT configuration 2714 | ---------------------- 2715 | 2716 | * For devices with firmware family "D" since version 2.0.22. 2717 | * For devices with firmware family "F" since version 2.4.2. 2718 | * For devices with firmware family "G" since version 2.4.21. 2719 | 2720 | HTTP request 2721 | ```````````` 2722 | 2723 | `GET /xled/v1/mqtt/config` 2724 | 2725 | `X-Auth-Token` 2726 | Authentication token 2727 | 2728 | Response 2729 | ```````` 2730 | 2731 | The response will be an object. 2732 | 2733 | For firmware family "D": 2734 | 2735 | `code` 2736 | (integer), application return code. 2737 | 2738 | `broker_host` 2739 | (string), hostname of broker. By default `mqtt.twinkly.com`. 2740 | 2741 | `broker_port` 2742 | (integer), destination port of broker. By default "1883". 2743 | 2744 | `client_id` 2745 | (string), see section MQTT Client ID in Protocol details. 2746 | 2747 | `encryption_key_set` 2748 | (bool), by default "False" 2749 | 2750 | `keep_alive_interval` 2751 | (integer), by default "180". 2752 | 2753 | `user` 2754 | (string), by default "twinkly_noauth" 2755 | 2756 | For firmware family "G" since firmware version 2.4.21 and "F" since 2.4.2: 2757 | 2758 | `code` 2759 | (integer), application return code. 2760 | 2761 | `broker_host` 2762 | (string), hostname of broker. By default `mqtt.twinkly.com`. 2763 | 2764 | `broker_port` 2765 | (integer), destination port of broker. By default "8883". 2766 | 2767 | `client_id` 2768 | (string), see section MQTT Client ID in Protocol details. 2769 | 2770 | `keep_alive_interval` 2771 | (integer), by default "60". 2772 | 2773 | `user` 2774 | (string), by default "twinkly32" 2775 | 2776 | `password` 2777 | (string), only in firmware family "F" since 2.4.2 until 2.4.14. 2778 | 2779 | Example 2780 | ``````` 2781 | 2782 | Request:: 2783 | 2784 | GET /xled/v1/mqtt/config HTTP/1.1 2785 | Host: 192.168.4.1 2786 | Content-Type: application/json 2787 | X-Auth-Token: mfqEJHHKJR8= 2788 | 2789 | Response from firmware family "D":: 2790 | 2791 | HTTP/1.1 200 Ok 2792 | Connection: close 2793 | Content-Length: 169 2794 | Content-Type: application/json 2795 | 2796 | {"broker_host":"mqtt.twinkly.com","broker_port":1883,"client_id":"5CCF7F33AAFF","user":"twinkly_noauth","keep_alive_interval":180,"encryption_key_set":false,"code":1000} 2797 | 2798 | Response from firmware family "G":: 2799 | 2800 | HTTP/1.1 200 OK 2801 | Server: esp-httpd/0.5 2802 | Transfer-Encoding: chunked 2803 | Content-Type: application/json 2804 | 2805 | {"broker_host":"mqtt.twinkly.com","broker_port":8883,"client_id":"98F4AB1CC190","user":"twinkly32","keep_alive_interval":60,"code":1000} 2806 | 2807 | Set MQTT configuration 2808 | ---------------------- 2809 | 2810 | Since firmware version: 2.0.22 2811 | 2812 | HTTP request 2813 | ```````````` 2814 | 2815 | `POST /xled/v1/mqtt/config` 2816 | 2817 | `X-Auth-Token` 2818 | Authentication token 2819 | 2820 | Parameters 2821 | `````````` 2822 | 2823 | Parameters as JSON object. 2824 | 2825 | For firmware family "D" since firmware version 2.0.22 and firmware family "G" since firmware version 2.4.21 and firmware family "F" since version 2.4.2: 2826 | 2827 | `broker_host` 2828 | (string), optional hostname of a broker 2829 | 2830 | `client_id` 2831 | (string), optional 2832 | 2833 | `keep_alive_interval` 2834 | (integer), optional 2835 | 2836 | `user` 2837 | (string), optional 2838 | 2839 | Response 2840 | ```````` 2841 | 2842 | The response will be an object. 2843 | 2844 | `code` 2845 | (integer), application return code. 2846 | 2847 | Get playlist 2848 | ------------ 2849 | 2850 | Available since firmware version 2.5.6. 2851 | 2852 | HTTP request 2853 | ```````````` 2854 | 2855 | `GET /xled/v1/playlist` 2856 | 2857 | `X-Auth-Token` 2858 | Authentication token 2859 | 2860 | Response 2861 | ```````` 2862 | 2863 | The response will be an object. 2864 | 2865 | `code` 2866 | (integer), application return code. 2867 | 2868 | `entries` 2869 | Array of objects 2870 | 2871 | Where each item of `entries` is an object. 2872 | 2873 | `duration` 2874 | (integer), in seconds, e.g. 10 2875 | 2876 | `unique_id` 2877 | (string), UUID 2878 | 2879 | Example 2880 | ``````` 2881 | 2882 | Request:: 2883 | 2884 | GET /xled/v1/movies HTTP/1.1 2885 | Host: 192.168.1.2 2886 | X-Auth-Token: 5jPe+ONhwUY= 2887 | 2888 | Response:: 2889 | 2890 | HTTP/1.1 200 OK 2891 | Server: esp-httpd/0.5 2892 | Transfer-Encoding: chunked 2893 | Content-Type: application/json 2894 | 2895 | {"entries":[],"code":1000} 2896 | 2897 | Create playlist 2898 | --------------- 2899 | 2900 | Available since firmware version 2.5.6. 2901 | 2902 | HTTP request 2903 | ```````````` 2904 | 2905 | `POST /xled/v1/playlist` 2906 | 2907 | `X-Auth-Token` 2908 | Authentication token 2909 | 2910 | Parameters 2911 | `````````` 2912 | 2913 | Parameters as JSON object. 2914 | 2915 | `entries` 2916 | Array of objects 2917 | 2918 | Where each item of `entries` is an object. 2919 | 2920 | `duration` 2921 | (integer), in seconds, e.g. 10 2922 | 2923 | `unique_id` 2924 | (string), UUID 2925 | 2926 | Response 2927 | ```````` 2928 | 2929 | The response will be an object. 2930 | 2931 | `code` 2932 | (integer), application return code. 2933 | 2934 | Delete playlist 2935 | --------------- 2936 | 2937 | Available since firmware version 2.5.6. 2938 | 2939 | HTTP request 2940 | ```````````` 2941 | 2942 | `DELETE /xled/v1/playlist` 2943 | 2944 | `X-Auth-Token` 2945 | Authentication token 2946 | 2947 | Response 2948 | ```````` 2949 | 2950 | The response will be an object. 2951 | 2952 | `code` 2953 | (integer), application return code. 2954 | 2955 | Get current playlist entry 2956 | -------------------------- 2957 | 2958 | Gets which movie is currently played in playlist mode. 2959 | 2960 | Available since firmware version 2.5.6. 2961 | 2962 | HTTP request 2963 | ```````````` 2964 | 2965 | `GET /xled/v1/playlist/current` 2966 | 2967 | `X-Auth-Token` 2968 | Authentication token 2969 | 2970 | Response 2971 | ```````` 2972 | 2973 | The response will be an object. 2974 | 2975 | `id` 2976 | (integer), 0 2977 | `unique_id` 2978 | (string), UUID 2979 | `name` 2980 | (string) 2981 | `code` 2982 | (integer), application return code. 2983 | 2984 | Set current playlist entry 2985 | -------------------------- 2986 | 2987 | Sets which movie to jump to when in playlist mode. 2988 | 2989 | When entering playlist mode, it always starts from the first entry in 2990 | the playlist, so this call is only useful when already in playlist mode. 2991 | 2992 | Available since firmware version 2.5.6. 2993 | 2994 | HTTP request 2995 | ```````````` 2996 | 2997 | `POST /xled/v1/led/playlist/current` 2998 | 2999 | `X-Auth-Token` 3000 | Authentication token 3001 | 3002 | Parameters 3003 | `````````` 3004 | 3005 | Parameters as JSON object. 3006 | 3007 | `id` 3008 | (int), id of movie to jump to, e.g. 0. 3009 | 3010 | Response 3011 | ```````` 3012 | 3013 | The response will be an object. 3014 | 3015 | `code` 3016 | (integer), application return code. 3017 | 3018 | Get mic config 3019 | -------------- 3020 | 3021 | Since firmware version 2.4.2 until 2.4.30. 3022 | 3023 | HTTP request 3024 | ```````````` 3025 | 3026 | `GET /xled/v1/mic/config` 3027 | 3028 | `X-Auth-Token` 3029 | Authentication token 3030 | 3031 | Response 3032 | ```````` 3033 | 3034 | The response will be an object. 3035 | 3036 | `filters` 3037 | array of objects 3038 | 3039 | `silence_threshold` 3040 | (integer), default 0 3041 | 3042 | `active_range` 3043 | (integer), default 0 3044 | 3045 | `brightness_depth` 3046 | (integer), default 255 3047 | 3048 | `hue_depth` 3049 | (integer), default 255 3050 | 3051 | `value_depth` 3052 | (integer), default 255 3053 | 3054 | `saturation_depth` 3055 | (integer), default 255 3056 | 3057 | `code` 3058 | (integer), application return code. 3059 | 3060 | Example 3061 | ``````` 3062 | 3063 | Request:: 3064 | 3065 | GET /xled/v1/mic/config HTTP/1.1 3066 | Host: 192.168.4.1 3067 | X-Auth-Token: 5jPe+ONhwUY= 3068 | 3069 | Response:: 3070 | 3071 | HTTP/1.1 200 OK 3072 | Server: esp-httpd/0.5 3073 | Transfer-Encoding: chunked 3074 | Content-Type: application/json 3075 | 3076 | {"filters":[],"silence_threshold":0,"active_range":0,"brightness_depth":255,"hue_depth":255,"value_depth":255,"saturation_depth":255,"code":1000} 3077 | 3078 | Get mic sample 3079 | -------------- 3080 | 3081 | Since firmware version 2.4.2 until 2.4.30. 3082 | 3083 | HTTP request 3084 | ```````````` 3085 | 3086 | `GET /xled/v1/mic/sample` 3087 | 3088 | `X-Auth-Token` 3089 | Authentication token 3090 | 3091 | Response 3092 | ```````` 3093 | 3094 | The response will be an object. 3095 | 3096 | `sampled_value` 3097 | (integer), e.g. 0 3098 | 3099 | `code` 3100 | (integer), application return code. 3101 | 3102 | Example 3103 | ``````` 3104 | 3105 | Request:: 3106 | 3107 | GET /xled/v1/mic/sample HTTP/1.1 3108 | Host: 192.168.4.1 3109 | X-Auth-Token: 5jPe+ONhwUY= 3110 | 3111 | Response:: 3112 | 3113 | HTTP/1.1 200 OK 3114 | Server: esp-httpd/0.5 3115 | Transfer-Encoding: chunked 3116 | Content-Type: application/json 3117 | 3118 | {"sampled_value":0,"code":1000} 3119 | 3120 | Get summary 3121 | ----------- 3122 | 3123 | Since firmware version 2.5.6. 3124 | 3125 | HTTP request 3126 | ```````````` 3127 | 3128 | `GET /xled/v1/summary` 3129 | 3130 | `X-Auth-Token` 3131 | Authentication token 3132 | 3133 | Response 3134 | ```````` 3135 | 3136 | The response will be an object. 3137 | 3138 | `led_mode` 3139 | (object) corresponds to response of Get LED operation mode without `code`. 3140 | 3141 | `timer` 3142 | (object) corresponds to response of Get Timer without `code`. 3143 | 3144 | `music` 3145 | (object) 3146 | 3147 | `filters` 3148 | Array of objects 3149 | 3150 | `group` 3151 | (object) corresponds to `sync` object from response of Get LED movie config without `code`. 3152 | 3153 | `layout` 3154 | (object) 3155 | 3156 | `color` 3157 | (object) corresponds to response of Get LED color without `code`. Since firmware version 2.7.1 3158 | 3159 | `code` 3160 | (integer), application return code. 3161 | 3162 | Where `music` contains: 3163 | 3164 | `enabled` 3165 | (integer), e.g. 1 3166 | 3167 | `active` 3168 | (integer), e.g. 0 3169 | 3170 | `current_driverset` 3171 | (integer), e.g. 1 3172 | 3173 | Where each item of `filters` is an object: 3174 | 3175 | `filter` 3176 | (string), one of "brightness", "hue", "saturation" 3177 | 3178 | `config` 3179 | (object) 3180 | 3181 | Where `config` consists of: 3182 | 3183 | `value` 3184 | (integer), e.g. 0 3185 | 3186 | `mode` 3187 | (string), e.g. "disabled" 3188 | 3189 | Object `layout` consists of: 3190 | 3191 | `uuid` 3192 | (string) UUID 3193 | 3194 | Get music drivers 3195 | ----------------- 3196 | 3197 | Since firmware version 2.5.6. 3198 | 3199 | HTTP request 3200 | ```````````` 3201 | 3202 | `GET /xled/v1/music/drivers` 3203 | 3204 | `X-Auth-Token` 3205 | Authentication token 3206 | 3207 | Response 3208 | ```````` 3209 | 3210 | The response will be an object. 3211 | 3212 | `drivers_number` 3213 | (integer), e.g. 26 3214 | 3215 | `unique_ids` 3216 | (array), each entry is UUID string 3217 | 3218 | `code` 3219 | (integer), application return code. 3220 | 3221 | Get music drivers sets 3222 | ---------------------- 3223 | 3224 | Since firmware version 2.5.6. 3225 | 3226 | HTTP request 3227 | ```````````` 3228 | 3229 | `GET /xled/v1/music/drivers/sets` 3230 | 3231 | `X-Auth-Token` 3232 | Authentication token 3233 | 3234 | Response 3235 | ```````` 3236 | 3237 | The response will be an object. 3238 | 3239 | `current` 3240 | (integer), e.g. 26 3241 | 3242 | `count` 3243 | (integer), e.g. 3 3244 | 3245 | `driversets` 3246 | (array) 3247 | 3248 | `code` 3249 | (integer), application return code. 3250 | 3251 | Where each item of `driversets` is an object: 3252 | 3253 | `id` 3254 | (integer) 3255 | 3256 | `count` 3257 | (integer) 3258 | 3259 | `unique_ids` 3260 | (array), each entry is UUID string 3261 | 3262 | Get current music driverset 3263 | --------------------------- 3264 | 3265 | Since firmware version 2.5.6. 3266 | 3267 | HTTP request 3268 | ```````````` 3269 | 3270 | `GET /xled/v1/music/drivers/sets/current` 3271 | 3272 | `X-Auth-Token` 3273 | Authentication token 3274 | 3275 | Response 3276 | ```````` 3277 | 3278 | The response will be an object. 3279 | 3280 | `driverset_id` 3281 | (integer), e.g. 0 3282 | 3283 | `code` 3284 | (integer), application return code. 3285 | --------------------------------------------------------------------------------