Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
1aa0b191be | |||
200d3c06c9 | |||
539804fbc8 | |||
3132613ad5 | |||
18db8e2882 | |||
bdabc3f7cd | |||
938a2bd773 | |||
92c879b499 | |||
519e070130 | |||
489259711a | |||
b7c672a53f | |||
7a5feb09be | |||
053fbf1aed | |||
f2542fe996 |
@ -4,6 +4,6 @@
|
|||||||
"\\data",
|
"\\data",
|
||||||
"\\data\\images"
|
"\\data\\images"
|
||||||
],
|
],
|
||||||
"SelectedNode": "\\data\\index.htm",
|
"SelectedNode": "\\esp8266-fastled-webserver.ino",
|
||||||
"PreviewInSolutionExplorer": false
|
"PreviewInSolutionExplorer": false
|
||||||
}
|
}
|
BIN
.vs/slnx.sqlite
5319
NodeRED_Flow.txt
Normal file
284
README.md
@ -3,7 +3,7 @@ Nanoleaf Web Server
|
|||||||
|
|
||||||
This is a fork of [jasoncoon's esp8266 fastled webserver](https://github.com/jasoncoon/esp8266-fastled-webserver) that was adapted to control the colors of my [DIY-Nanoleaf Replica](https://www.thingiverse.com/thing:3354082).
|
This is a fork of [jasoncoon's esp8266 fastled webserver](https://github.com/jasoncoon/esp8266-fastled-webserver) that was adapted to control the colors of my [DIY-Nanoleaf Replica](https://www.thingiverse.com/thing:3354082).
|
||||||
|
|
||||||
[](https://www.thingiverse.com/thing:3354082)
|
[](https://www.thingiverse.com/thing:3354082)
|
||||||
|
|
||||||
Hardware
|
Hardware
|
||||||
--------
|
--------
|
||||||
@ -40,24 +40,28 @@ Features
|
|||||||
* Adjust the color
|
* Adjust the color
|
||||||
* Adapted patterns to look great on the [DIY-Nanoleaf Replica](https://www.thingiverse.com/thing:3354082)
|
* Adapted patterns to look great on the [DIY-Nanoleaf Replica](https://www.thingiverse.com/thing:3354082)
|
||||||
* OTA-Update support
|
* OTA-Update support
|
||||||
|
* **Node-RED** integration :white_check_mark:
|
||||||
|
* Simple Amazon **Alexa** integration :white_check_mark:
|
||||||
|
* Custom pattern designer :white_check_mark:
|
||||||
|
* **Node-RED** webinterface to store special patterns persistant :white_check_mark:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Upcoming Features
|
### Upcoming Features
|
||||||
|
|
||||||
- **Node-RED** integration
|
- **Node-RED** integration :white_check_mark:
|
||||||
- Custom-Alexa skill
|
- Simple Amazon **Alexa** integration :white_check_mark:
|
||||||
- Nanoleaf voice control
|
- Nanoleaf voice control :white_check_mark:
|
||||||
- Custom color pattern designer
|
- Custom pattern designer :white_check_mark:
|
||||||
- **Node-RED** webinterface to store special patterns persistant
|
- **Node-RED** webinterface to store special patterns persistant :white_check_mark:
|
||||||
- Controlling multiple nanoleafs at once
|
- Controlling multiple nanoleafs at once
|
||||||
|
- Advanced Amazon **Alexa** integration with custom skill (AWS account required, free)
|
||||||
> these features will be optional and require additional hardware (any linux/windows device that is in the same network)
|
> these features will be optional and require additional hardware (any linux/windows device that is in the same network)
|
||||||
|
|
||||||
Webinterface
|
Webinterface
|
||||||
--------
|
--------
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
The web app is stored in SPIFFS (on-board flash memory).
|
The web app is stored in SPIFFS (on-board flash memory).
|
||||||
|
|
||||||
@ -70,7 +74,7 @@ The app depends on the following libraries. They must either be downloaded from
|
|||||||
* [FastLED](https://github.com/FastLED/FastLED)
|
* [FastLED](https://github.com/FastLED/FastLED)
|
||||||
* [Arduino WebSockets](https://github.com/Links2004/arduinoWebSockets)
|
* [Arduino WebSockets](https://github.com/Links2004/arduinoWebSockets)
|
||||||
|
|
||||||
Download the app code from GitHub using the green Clone or Download button from [GitHub](https://github.com/NimmLor/esp8266-fastled-webserver) and click Download ZIP. Decompress the ZIP file in your Arduino sketch folder.
|
Download the app code from GitHub using the green Clone or Download button from [GitHub](https://github.com/NimmLor/esp8266-nanoleaf-webserver) and click Download ZIP. Decompress the ZIP file in your Arduino sketch folder. Rename the folder from *esp8266-nanoleaf-webserver-master* to *esp8266-nanoleaf-webserver*
|
||||||
|
|
||||||
The web app needs to be uploaded to the ESP8266's SPIFFS. You can do this within the Arduino IDE after installing the [Arduino ESP8266FS tool](http://esp8266.github.io/Arduino/versions/2.3.0/doc/filesystem.html#uploading-files-to-file-system). An alternative would be to install the [Visual Micro](https://www.visualmicro.com/) plugin for Visual Studio.
|
The web app needs to be uploaded to the ESP8266's SPIFFS. You can do this within the Arduino IDE after installing the [Arduino ESP8266FS tool](http://esp8266.github.io/Arduino/versions/2.3.0/doc/filesystem.html#uploading-files-to-file-system). An alternative would be to install the [Visual Micro](https://www.visualmicro.com/) plugin for Visual Studio.
|
||||||
|
|
||||||
@ -114,13 +118,269 @@ You should also set the milli-amps of your power supply to prevent power overloa
|
|||||||
|
|
||||||
### Without Logic-Level Converter
|
### Without Logic-Level Converter
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### With Logic-Level-Converter (required if leds 'glitch')
|
### With Logic-Level-Converter (required if leds 'glitch')
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Node-RED & Alexa integration Setup
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### **Amazon Alexa Integration** (optional)
|
||||||
|
|
||||||
|
It works with any language that is supported by Alexa and can be easily expanded to support more activities or patterns. How you want to call them (Nanoleaf, Nanoleafs, Nano, Triangles) must be set in the setup of the devices.
|
||||||
|
|
||||||
|
#### **Commands**:
|
||||||
|
|
||||||
|
- Turn on/off
|
||||||
|
- Control Brightness
|
||||||
|
- Control Pattern Speed
|
||||||
|
- Set Color
|
||||||
|
- Set into Rainbow mode
|
||||||
|
- Enable Autoplay and set Duration
|
||||||
|
- Activate custom activities
|
||||||
|
|
||||||
|
> *Alexa, turn Nanoleafs **on/off***
|
||||||
|
> *Alexa, set Nanoleafs 70%*
|
||||||
|
> Alexa, dim Nanoleafs
|
||||||
|
> *Alexa, Nanoleaf speed 20%*
|
||||||
|
> *Alexa, set Nanoleafs pink*
|
||||||
|
> *Alexa, turn Nanoleaf rainbow on*
|
||||||
|
> *Alexa, turn Nanoleaf Autoplay on*
|
||||||
|
> *Alexa, set Nanoleaf Autoplay 40*
|
||||||
|
>
|
||||||
|
> Alexa, Nanoleaf Default
|
||||||
|
> Alexa, Nanoleaf Mode 1
|
||||||
|
> Alexa, Nanoleaf Mode 2
|
||||||
|
> Alexa, Nanoleaf Mode 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Node-RED GUI
|
||||||
|
|
||||||
|
The Node-RED GUI is an addition to the regular UI that is running on the Wemos D1 mini. It allows to create and save custom patterns and also control all regular parameters same as the ESP8266 webserver. It can be accessed by any device.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Nanoleaf Designer
|
||||||
|
|
||||||
|
In the Node-RED GUI you can easily create your nanoleaf setup by using the *Nanoleaf Designer*. It's easy to use and allows almost any design that is possible. But it might have still some minor bugs.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Nanoleaf Custom Pattern Designer
|
||||||
|
|
||||||
|
With the *Nanoleaf Custom Pattern Designer* you can create custom patterns with effects. Currently the individual leafs can be set to *Static* mode and *Breathe* mode that allows to set a phase shift and lets the leafs breathe. Flow-mode follows in the next update.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## What you will need
|
||||||
|
|
||||||
|
- Any device that runs Node-RED, examples would be:
|
||||||
|
- (recommended) [Raspberry Pi](https://www.amazon.de/gp/product/B01CD5VC92?ie=UTF8&tag=surrbradl08-21&camp=1638&linkCode=xm2&creativeASIN=B01CD5VC92)
|
||||||
|
- Any Linux machine
|
||||||
|
- (instructions are provided for linux) Any Windows machine
|
||||||
|
- Any Amazon Alexa device for Alexa integration, works on Android and IOS too (**OPTIONAL**)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
#### 1. Install Node-RED
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 2. Install npm - this might be already installed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install nodejs npm -y
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. Install dashboard, alexa-home-skill, color-convert, config
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd $HOME/.node-red
|
||||||
|
npm install node-red-dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
- if you get an error try: `npm install --unsafe-perm node-red-dashboard`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install node-red-contrib-alexa-home-skill
|
||||||
|
npm install node-red-contrib-color-convert
|
||||||
|
npm install node-red-contrib-config
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 4. Setup a static IP-Address for your Raspberry Pi (optional)
|
||||||
|
|
||||||
|
- (recommended) Setup a static ip on your router
|
||||||
|
- [or on your Raspberry Pi](http://www.circuitbasics.com/how-to-set-up-a-static-ip-on-the-raspberry-pi/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 6. Run Node-RED
|
||||||
|
|
||||||
|
To start Node-RED type into the shell:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo node-red-start
|
||||||
|
```
|
||||||
|
|
||||||
|
Connect to the GUI by typing the following line into your browser:
|
||||||
|
|
||||||
|
- http://IP-ADDRESS:1880
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. Import the flow
|
||||||
|
|
||||||
|
- Click on the 3 dashes in the top right corner → import → clipboard
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Configure the IP-Address of the Wemos D1 mini
|
||||||
|
|
||||||
|
Edit the Nanoleaf-Config node to set the IP-Address.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Amazon Alexa setup
|
||||||
|
|
||||||
|
The Alexa integration uses the *Node-RED Alexa Home Skill Bridge* to redirect the commands from alexa to Node-RED.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 1. Create a new Bridge account
|
||||||
|
|
||||||
|
Head to https://alexa-node-red.bm.hardill.me.uk/newuser and create a new account.
|
||||||
|
|
||||||
|
Afterwards login into your account.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 2. Create the Devices
|
||||||
|
|
||||||
|
You have to create devices that are called by Alexa.
|
||||||
|
|
||||||
|
#### 2.1 Main Nanoleaf Device
|
||||||
|
|
||||||
|
First create the devices that control a few devices that are used to turn on/off the nanoleafs and controls the brightness. I've called them "Nanoleafs", "Nanoleaf", "Nano" and "Triangles", but a single one would be enough too.
|
||||||
|
|
||||||
|
Click the **Add Device** button and choose. Repeat this step for all your names.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 2.2 Autoplay control Device (optional)
|
||||||
|
|
||||||
|
To control the autoplay functionality, create a device with **On, Off, %, +%, -%, LIGHT**.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 2.3 Speed control Device (optional)
|
||||||
|
|
||||||
|
To control the speed of the animations, create a device with **%, +%, -%**.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### 2.4 Activities (optional)
|
||||||
|
|
||||||
|
Now create activities by clicking *Add Device* and selecting **On, Off, ACTIVITY**.
|
||||||
|
|
||||||
|
I've created one to set the *Rainbow* pattern, one for my default settings and Nanoleaf Mode 1-3 for some custom settings.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 3. Activating the Alexa skill
|
||||||
|
|
||||||
|
Open the app on your phone or head to https://alexa.amazon.de and click on **Skills**.
|
||||||
|
|
||||||
|
Search for **Node-RED** and activate the skill. Afterwards you are prompted to login into your account that you have created the devices beforehand.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 4. Add a new Alexa-Home-Skill configuration
|
||||||
|
|
||||||
|
Click on any Alexa node in the flow, and click *Add new alexa-home-configuration*. Afterwards hit the refresh button next to the devices list.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 5. Select the devices
|
||||||
|
|
||||||
|
Click the alexa skill nodes in the flow and select the corresponding devices. **Delete all unused alexa nodes**.
|
||||||
|
|
||||||
|
For me, it looked like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 6. Discover the Smart-Home Devices
|
||||||
|
|
||||||
|
Speak to Alexa and say to her: **Alexa, discover devices**. (Just say it in english, it works on every device)
|
||||||
|
|
||||||
|
If everything worked correctly she should tell you after around 30 seconds that she has found new devices.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -137,4 +397,4 @@ The only drawback to SPIFFS that I've found so far is uploading the files can be
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
The firmware implements basic [RESTful web services](https://en.wikipedia.org/wiki/Representational_state_transfer) using the ESP8266WebServer library. Current values are requested with HTTP GETs, and values are set with POSTs using query string parameters. It can run in connected or standalone access point modes.
|
The firmware implements basic [RESTful web services](https://en.wikipedia.org/wiki/Representational_state_transfer) using the ESP8266WebServer library. Current values are requested with HTTP GETs, and values are set with POSTs using query string parameters. It can run in connected or standalone access point modes.
|
||||||
|
5
Secrets.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const char WiFiAPPSK[] = "your-password";
|
||||||
|
|
||||||
|
// Wi-Fi network to connect to (if not in AP mode)
|
||||||
|
char* ssid = "WLAN23";
|
||||||
|
char* password = "57erChevy";
|
@ -1,20 +1,27 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>ESP8266 + FastLED by Evil Genius Labs</title>
|
<title>ESP8266 + FastLED by Evil Genius Labs</title>
|
||||||
|
|
||||||
<!-- request CSS from internet CDN -->
|
<!-- request CSS from internet CDN -->
|
||||||
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> -->
|
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> -->
|
||||||
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.2.4/jquery.minicolors.min.css" integrity="sha256-4wnSkPYU5B4yngAlx/rEb8LdfMah4teUth4AfhGEuaY=" crossorigin="anonymous" /> -->
|
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.2.4/jquery.minicolors.min.css" integrity="sha256-4wnSkPYU5B4yngAlx/rEb8LdfMah4teUth4AfhGEuaY=" crossorigin="anonymous" /> -->
|
||||||
|
|
||||||
<!-- request CSS from the ESP8266 web server -->
|
<!-- request CSS from the ESP8266 web server -->
|
||||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="css/minicolors.min.css">
|
<link rel="stylesheet" href="css/minicolors.min.css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="css/styles.css">
|
<link rel="stylesheet" href="css/styles.css">
|
||||||
|
|
||||||
<link rel="icon" href="images/atom196.png">
|
<link rel="icon" href="images/atom196.png">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav class="navbar navbar-default navbar-static-top" id="top" role="banner">
|
<nav class="navbar navbar-default navbar-static-top" id="top" role="banner">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
@ -29,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="collapse navbar-collapse" id="navbar-collapse-1">
|
<div class="collapse navbar-collapse" id="navbar-collapse-1">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li class="active"><a href="/">DIY Nanoleaf control <span class="sr-only">(current)</span></a></li>
|
<li class="active"><a href="/">ESP8266 + FastLED <span class="sr-only">(current)</span></a></li>
|
||||||
<li><a href="/simple.htm" target="_blank" title="Simple Mode">Simple</a></li>
|
<li><a href="/simple.htm" target="_blank" title="Simple Mode">Simple</a></li>
|
||||||
<li><a href="/edit.htm" target="_blank" title="Edit Files">Files</a></li>
|
<li><a href="/edit.htm" target="_blank" title="Edit Files">Files</a></li>
|
||||||
<li><a href="/update" target="_blank" title="Update Firmware">Firmware</a></li>
|
<li><a href="/update" target="_blank" title="Update Firmware">Firmware</a></li>
|
||||||
@ -45,15 +52,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div id="container" class="container">
|
<div id="container" class="container">
|
||||||
<form class="form-horizontal" id="form"></form>
|
|
||||||
|
<form class="form-horizontal" id="form">
|
||||||
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="templates" style="display: none">
|
<div id="templates" style="display: none">
|
||||||
|
|
||||||
<div id="sectionTemplate" class="form-group">
|
<div id="sectionTemplate" class="form-group">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<hr style="margin-bottom: 5px;margin-top: 5px;" />
|
<hr style="margin-bottom: 5px;margin-top: 5px;" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="numberTemplate" class="form-group">
|
<div id="numberTemplate" class="form-group">
|
||||||
<label class="col-sm-2 control-label"></label>
|
<label class="col-sm-2 control-label"></label>
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
@ -63,6 +77,7 @@
|
|||||||
<input class="form-control slider" type="range" step="1" min="0" max="255" />
|
<input class="form-control slider" type="range" step="1" min="0" max="255" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="booleanTemplate" class="form-group">
|
<div id="booleanTemplate" class="form-group">
|
||||||
<label class="col-sm-2 control-label"></label>
|
<label class="col-sm-2 control-label"></label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
@ -72,6 +87,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="selectTemplate" class="form-group">
|
||||||
|
<label class="col-sm-2 control-label"></label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<select class="form-control"><select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<div class="btn-group" role="group" aria-label="...">
|
||||||
|
<button type="button" class="btn btn-default btn-previous"
|
||||||
|
aria-label="Previous" title="Previous">
|
||||||
|
<span class="glyphicon glyphicon-chevron-left"></span>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-default btn-next"
|
||||||
|
aria-label="Next" title="Next">
|
||||||
|
<span class="glyphicon glyphicon-chevron-right"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="booleanTemplate" class="form-group">
|
||||||
|
<label class="col-sm-2 control-label"></label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button type="button" class="btn btn-default" id="btnOn">On</button>
|
||||||
|
<button type="button" class="btn btn-default" id="btnOff">Off</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="selectTemplate" class="form-group">
|
<div id="selectTemplate" class="form-group">
|
||||||
<label class="col-sm-2 control-label"></label>
|
<label class="col-sm-2 control-label"></label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
@ -91,36 +136,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="booleanTemplate" class="form-group">
|
<div id="colorPaletteTemplate" class="form-group">
|
||||||
<label class="col-sm-2 control-label"></label>
|
|
||||||
<div class="col-sm-10">
|
|
||||||
<div class="btn-group" role="group">
|
|
||||||
<button type="button" class="btn btn-default" id="btnOn">On</button>
|
|
||||||
<button type="button" class="btn btn-default" id="btnOff">Off</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="selectTemplate" class="form-group">
|
|
||||||
<label class="col-sm-2 control-label"></label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<select class="form-control"><select>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<div class="btn-group" role="group" aria-label="...">
|
|
||||||
<button type="button" class="btn btn-default btn-previous"
|
|
||||||
aria-label="Previous" title="Previous">
|
|
||||||
<span class="glyphicon glyphicon-chevron-left"></span>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-default btn-next"
|
|
||||||
aria-label="Next" title="Next">
|
|
||||||
<span class="glyphicon glyphicon-chevron-right"></span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="colorPaletteTemplate" class="form-group">
|
|
||||||
<label class="col-sm-2 control-label color-label"></label>
|
<label class="col-sm-2 control-label color-label"></label>
|
||||||
|
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="btn-group btn-group-justified" role="group">
|
<div class="btn-group btn-group-justified" role="group">
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
@ -165,6 +183,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="colorTemplate">
|
<div id="colorTemplate">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<!-- <label class="col-sm-2 control-label color-label"></label> -->
|
<!-- <label class="col-sm-2 control-label color-label"></label> -->
|
||||||
@ -200,7 +219,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="navbar navbar-default navbar-fixed-bottom">
|
<nav class="navbar navbar-default navbar-fixed-bottom">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
@ -223,16 +244,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- request js from internet CDN -->
|
<!-- request js from internet CDN -->
|
||||||
<!-- <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> -->
|
<!-- <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> -->
|
||||||
<!-- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> -->
|
<!-- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> -->
|
||||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.2.4/jquery.minicolors.min.js" integrity="sha256-XAFQ9dZ6hy8p/GRhU8h/8pMvM1etymiJLZW1CiHV3bQ=" crossorigin="anonymous"></script> -->
|
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-minicolors/2.2.4/jquery.minicolors.min.js" integrity="sha256-XAFQ9dZ6hy8p/GRhU8h/8pMvM1etymiJLZW1CiHV3bQ=" crossorigin="anonymous"></script> -->
|
||||||
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.min.js" integrity="sha256-A4JwlcDvqO4JXpvEtvWY1RH8JAEMu5W21wP8GUXLUNs=" crossorigin="anonymous"></script> -->
|
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.min.js" integrity="sha256-A4JwlcDvqO4JXpvEtvWY1RH8JAEMu5W21wP8GUXLUNs=" crossorigin="anonymous"></script> -->
|
||||||
|
|
||||||
<!-- request js from the ESP8266 web server -->
|
<!-- request js from the ESP8266 web server -->
|
||||||
<script src="js/jquery-3.1.1.min.js"></script>
|
<script src="js/jquery-3.1.1.min.js"></script>
|
||||||
<script src="js/bootstrap.min.js"></script>
|
<script src="js/bootstrap.min.js"></script>
|
||||||
<script src="js/minicolors.min.js"></script>
|
<script src="js/minicolors.min.js"></script>
|
||||||
<script src="js/r-websocket.min.js"></script>
|
<script src="js/r-websocket.min.js"></script>
|
||||||
|
|
||||||
<script src="js/app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -107,7 +107,7 @@ const uint8_t brightnessCount = 5;
|
|||||||
uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 };
|
uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 };
|
||||||
uint8_t brightnessIndex = 0;
|
uint8_t brightnessIndex = 0;
|
||||||
|
|
||||||
|
char vals[4 + LEAFCOUNT * 5][4] = {""};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -136,6 +136,10 @@ uint8_t currentPaletteIndex = 0;
|
|||||||
|
|
||||||
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
|
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
|
||||||
|
|
||||||
|
uint8_t breathe = 0; // value for starting custom pattern
|
||||||
|
uint8_t breathe_dir = 1; // 1== rising
|
||||||
|
char cpattern[500] = "";
|
||||||
|
|
||||||
CRGB solidColor = CRGB::Blue;
|
CRGB solidColor = CRGB::Blue;
|
||||||
|
|
||||||
// scale the brightness of all pixels down
|
// scale the brightness of all pixels down
|
||||||
@ -195,7 +199,9 @@ PatternAndNameList patterns = {
|
|||||||
{ fire, "Fire" },
|
{ fire, "Fire" },
|
||||||
{ water, "Water" },
|
{ water, "Water" },
|
||||||
|
|
||||||
{ showSolidColor, "Solid Color" }
|
{ showSolidColor, "Solid Color" },
|
||||||
|
|
||||||
|
{ SetCustomPattern, "Custom Pattern"}
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t patternCount = ARRAY_SIZE(patterns);
|
const uint8_t patternCount = ARRAY_SIZE(patterns);
|
||||||
@ -290,7 +296,7 @@ void setup() {
|
|||||||
uint8_t mac[WL_MAC_ADDR_LENGTH];
|
uint8_t mac[WL_MAC_ADDR_LENGTH];
|
||||||
WiFi.softAPmacAddress(mac);
|
WiFi.softAPmacAddress(mac);
|
||||||
String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
|
String macID = String(mac[WL_MAC_ADDR_LENGTH - 2], HEX) +
|
||||||
String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
|
String(mac[WL_MAC_ADDR_LENGTH - 1], HEX);
|
||||||
macID.toUpperCase();
|
macID.toUpperCase();
|
||||||
String AP_NameString = "ESP8266 Thing " + macID;
|
String AP_NameString = "ESP8266 Thing " + macID;
|
||||||
|
|
||||||
@ -385,12 +391,16 @@ void setup() {
|
|||||||
String b = webServer.arg("b");
|
String b = webServer.arg("b");
|
||||||
setSolidColor(r.toInt(), g.toInt(), b.toInt());
|
setSolidColor(r.toInt(), g.toInt(), b.toInt());
|
||||||
sendString(String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
|
sendString(String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
|
||||||
|
Serial.println(String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
|
||||||
});
|
});
|
||||||
|
|
||||||
webServer.on("/pattern", HTTP_POST, []() {
|
webServer.on("/pattern", HTTP_POST, []() {
|
||||||
String value = webServer.arg("value");
|
String value = webServer.arg("value");
|
||||||
setPattern(value.toInt());
|
if (value.toInt() <= 29)
|
||||||
sendInt(currentPatternIndex);
|
{
|
||||||
|
setPattern(value.toInt());
|
||||||
|
sendInt(currentPatternIndex);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
webServer.on("/patternName", HTTP_POST, []() {
|
webServer.on("/patternName", HTTP_POST, []() {
|
||||||
@ -441,6 +451,17 @@ void setup() {
|
|||||||
sendInt(selectedLeaf);
|
sendInt(selectedLeaf);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
webServer.on("/custom", HTTP_POST, []() {
|
||||||
|
String value = webServer.arg("value");
|
||||||
|
Serial.println(value);
|
||||||
|
value.toCharArray(cpattern, 500);
|
||||||
|
Serial.println(value);
|
||||||
|
sendString(value);
|
||||||
|
setPattern(30);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
//list directory
|
//list directory
|
||||||
webServer.on("/list", HTTP_GET, handleFileList);
|
webServer.on("/list", HTTP_GET, handleFileList);
|
||||||
//load editor
|
//load editor
|
||||||
@ -538,6 +559,14 @@ void loop() {
|
|||||||
gHue++; // slowly cycle the "base color" through the rainbow
|
gHue++; // slowly cycle the "base color" through the rainbow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVERY_N_MILLIS_I(thistimer, 128-(speed/2)) {
|
||||||
|
if (breathe_dir == 1)breathe++; else breathe--;
|
||||||
|
if (breathe >= 255)breathe_dir = 0;
|
||||||
|
else if (breathe <= 0) breathe_dir = 1;
|
||||||
|
//Serial.println(breathe);
|
||||||
|
}
|
||||||
|
thistimer.setPeriod(64-(speed/4));
|
||||||
|
|
||||||
if (autoplay && (millis() > autoPlayTimeout)) {
|
if (autoplay && (millis() > autoPlayTimeout)) {
|
||||||
adjustPattern(true);
|
adjustPattern(true);
|
||||||
autoPlayTimeout = millis() + (autoplayDuration * 1000);
|
autoPlayTimeout = millis() + (autoplayDuration * 1000);
|
||||||
@ -691,9 +720,10 @@ void setSolidColor(uint8_t r, uint8_t g, uint8_t b)
|
|||||||
EEPROM.write(4, b);
|
EEPROM.write(4, b);
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
|
|
||||||
setPattern(patternCount - 1);
|
setPattern(29);
|
||||||
|
|
||||||
broadcastString("color", String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
|
broadcastString("color", String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b));
|
||||||
|
FastLED.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
// increase or decrease the current pattern number, and wrap around at the ends
|
// increase or decrease the current pattern number, and wrap around at the ends
|
||||||
@ -884,21 +914,21 @@ void bpm()
|
|||||||
uint8_t beat = beatsin8(speed, 64, 255);
|
uint8_t beat = beatsin8(speed, 64, 255);
|
||||||
CRGBPalette16 palette = palettes[currentPaletteIndex];
|
CRGBPalette16 palette = palettes[currentPaletteIndex];
|
||||||
for (int i = 0; i < LEAFCOUNT; i++) {
|
for (int i = 0; i < LEAFCOUNT; i++) {
|
||||||
for (int i2 = 0; i2 < PIXELS_PER_LEAF; i2++)leds[i*PIXELS_PER_LEAF + i2] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
|
for (int i2 = 0; i2 < PIXELS_PER_LEAF; i2++)leds[i * PIXELS_PER_LEAF + i2] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BACKUP
|
// BACKUP
|
||||||
/*
|
/*
|
||||||
void bpm()
|
void bpm()
|
||||||
{
|
{
|
||||||
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
|
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
|
||||||
uint8_t beat = beatsin8(speed, 64, 255);
|
uint8_t beat = beatsin8(speed, 64, 255);
|
||||||
CRGBPalette16 palette = palettes[currentPaletteIndex];
|
CRGBPalette16 palette = palettes[currentPaletteIndex];
|
||||||
for (int i = 0; i < NUM_LEDS; i++) {
|
for (int i = 0; i < NUM_LEDS; i++) {
|
||||||
leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
|
leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void juggle()
|
void juggle()
|
||||||
@ -918,10 +948,10 @@ void juggle()
|
|||||||
if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment.
|
if (lastSecond != secondHand) { // Debounce to make sure we're not repeating an assignment.
|
||||||
lastSecond = secondHand;
|
lastSecond = secondHand;
|
||||||
switch (secondHand) {
|
switch (secondHand) {
|
||||||
case 0: numdots = 1; basebeat = 20; hueinc = 16; faderate = 2; thishue = 0; break; // You can change values here, one at a time , or altogether.
|
case 0: numdots = 1; basebeat = 20; hueinc = 16; faderate = 2; thishue = 0; break; // You can change values here, one at a time , or altogether.
|
||||||
case 10: numdots = 4; basebeat = 10; hueinc = 16; faderate = 8; thishue = 128; break;
|
case 10: numdots = 4; basebeat = 10; hueinc = 16; faderate = 8; thishue = 128; break;
|
||||||
case 20: numdots = 8; basebeat = 3; hueinc = 0; faderate = 8; thishue = random8(); break; // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows.
|
case 20: numdots = 8; basebeat = 3; hueinc = 0; faderate = 8; thishue = random8(); break; // Only gets called once, and not continuously for the next several seconds. Therefore, no rainbows.
|
||||||
case 30: break;
|
case 30: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,18 +1017,18 @@ void pride()
|
|||||||
|
|
||||||
for (int i2 = 0; i2 < (PIXELS_PER_LEAF / 3); i2++)
|
for (int i2 = 0; i2 < (PIXELS_PER_LEAF / 3); i2++)
|
||||||
{
|
{
|
||||||
nblend(leds[pixelnumber*(PIXELS_PER_LEAF / 3) + i2], newcolor, 64);
|
nblend(leds[pixelnumber * (PIXELS_PER_LEAF / 3) + i2], newcolor, 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#############BACKUP########################
|
//#############BACKUP########################
|
||||||
/*
|
/*
|
||||||
// Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5
|
// Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5
|
||||||
// This function draws rainbows with an ever-changing,
|
// This function draws rainbows with an ever-changing,
|
||||||
// widely-varying set of parameters.
|
// widely-varying set of parameters.
|
||||||
void pride()
|
void pride()
|
||||||
{
|
{
|
||||||
static uint16_t sPseudotime = 0;
|
static uint16_t sPseudotime = 0;
|
||||||
static uint16_t sLastMillis = 0;
|
static uint16_t sLastMillis = 0;
|
||||||
static uint16_t sHue16 = 0;
|
static uint16_t sHue16 = 0;
|
||||||
@ -1036,7 +1066,7 @@ void pride()
|
|||||||
|
|
||||||
nblend( leds[pixelnumber], newcolor, 64);
|
nblend( leds[pixelnumber], newcolor, 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1110,7 +1140,7 @@ extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
|
|||||||
extern const uint8_t gGradientPaletteCount;
|
extern const uint8_t gGradientPaletteCount;
|
||||||
|
|
||||||
uint8_t beatsaw8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255,
|
uint8_t beatsaw8(accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255,
|
||||||
uint32_t timebase = 0, uint8_t phase_offset = 0)
|
uint32_t timebase = 0, uint8_t phase_offset = 0)
|
||||||
{
|
{
|
||||||
uint8_t beat = beat8(beats_per_minute, timebase);
|
uint8_t beat = beat8(beats_per_minute, timebase);
|
||||||
uint8_t beatsaw = beat + phase_offset;
|
uint8_t beatsaw = beat + phase_offset;
|
||||||
@ -1180,7 +1210,7 @@ void colorwaves(CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette)
|
|||||||
pixelnumber = ((LEAFCOUNT * 3) - 1) - pixelnumber;
|
pixelnumber = ((LEAFCOUNT * 3) - 1) - pixelnumber;
|
||||||
for (int i2 = 0; i2 < (PIXELS_PER_LEAF / 3); i2++)
|
for (int i2 = 0; i2 < (PIXELS_PER_LEAF / 3); i2++)
|
||||||
{
|
{
|
||||||
nblend(leds[pixelnumber*(PIXELS_PER_LEAF / 3) + i2], newcolor, 128);
|
nblend(leds[pixelnumber * (PIXELS_PER_LEAF / 3) + i2], newcolor, 128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1193,3 +1223,96 @@ void palettetest(CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrent
|
|||||||
startindex--;
|
startindex--;
|
||||||
fill_palette(ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, 255, LINEARBLEND);
|
fill_palette(ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, 255, LINEARBLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Function: ExtractValues
|
||||||
|
Used to extract a given amount of values from the message with a start index
|
||||||
|
Parameters:
|
||||||
|
- startindex: position in the string where to start
|
||||||
|
- valuecount: amount of values to capture
|
||||||
|
*/
|
||||||
|
void ExtractValues(char receivedChars[], int startindex, int valuecount)
|
||||||
|
{
|
||||||
|
int pos = startindex;
|
||||||
|
for (int c = 0; c < valuecount; c++)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (receivedChars[pos] != ';' && receivedChars[pos] != '\0') {
|
||||||
|
vals[c][i] = receivedChars[pos];
|
||||||
|
pos++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
vals[c][i] = '\0';
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_SERIAL
|
||||||
|
for (int p = 0; p < valuecount; p++)
|
||||||
|
{
|
||||||
|
Serial.print("Extracting: "); Serial.println(vals[p]);
|
||||||
|
}
|
||||||
|
#endif // DEBUG_SERIAL
|
||||||
|
}
|
||||||
|
void cycle(CRGB endclr, CRGB midclr, uint8_t start) {
|
||||||
|
fill_gradient_RGB(leds, start, endclr, PIXELS_PER_LEAF/ 2, midclr);
|
||||||
|
fill_gradient_RGB(leds, PIXELS_PER_LEAF/ 2 + 1, midclr, PIXELS_PER_LEAF, endclr);
|
||||||
|
}
|
||||||
|
// Set Custom Pattern for the node red part
|
||||||
|
void SetCustomPattern()
|
||||||
|
{
|
||||||
|
uint8_t cnt = 0;
|
||||||
|
uint8_t isflow = 0;
|
||||||
|
|
||||||
|
ExtractValues(cpattern, 0, 2);
|
||||||
|
cnt = atoi(vals[0]);
|
||||||
|
isflow = atoi(vals[1]);
|
||||||
|
ExtractValues(cpattern, 0, 2 + 5 * cnt);
|
||||||
|
if (isflow == 0)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
int8_t cmode = atoi(vals[2 + i * 5]);
|
||||||
|
uint8_t phase = atoi(vals[2 + i * 5 + 1]);
|
||||||
|
int mul = breathe;
|
||||||
|
if (breathe_dir == 1)
|
||||||
|
{
|
||||||
|
if ((mul + phase) > 255)mul = 255 + (255 - mul - phase);
|
||||||
|
else mul += phase;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((mul - phase) < 0)mul = -mul + phase;
|
||||||
|
else mul -= phase;
|
||||||
|
}
|
||||||
|
if (cmode == 0)mul = 255;
|
||||||
|
double fac = (mul * 100) / 255.00;
|
||||||
|
//if(cmode==1)Serial.printf("%d ", mul);
|
||||||
|
for (uint8_t x = 0; x < PIXELS_PER_LEAF; x++)
|
||||||
|
{
|
||||||
|
//Serial.printf("Setting %d to %d, %d, %d\n", cnt*PIXELS_PER_LEAF+x,atoi(vals[2+i*5+2]), atoi(vals[2+i*5+3]), atoi(vals[2+i*5+4]));
|
||||||
|
leds[i * PIXELS_PER_LEAF + x] = CRGB((atoi(vals[2 + i * 5 + 2]) * fac) / 100.00, (atoi(vals[2 + i * 5 + 3]) * fac) / 100.00, (atoi(vals[2 + i * 5 + 4]) * fac) / 100.00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
if (i != (cnt - 1))
|
||||||
|
{
|
||||||
|
//uint8_t speed = beatsin8(6,0,255);
|
||||||
|
CRGB endclr = blend(CRGB(atoi(vals[2 + i * 5 + 2]), atoi(vals[2 + i * 5 + 3]), atoi(vals[2 + i * 5 + 4])), CRGB(atoi(vals[2 + (i + 1) * 5 + 2]), atoi(vals[2 + (i + 1) * 5 + 3]), atoi(vals[2 + (i + 1) * 5 + 4])), breathe);
|
||||||
|
CRGB midclr = blend(CRGB(atoi(vals[2 + (i + 1) * 5 + 2]), atoi(vals[2 + (i + 1) * 5 + 3]), atoi(vals[2 + (i + 1) * 5 + 4])), CRGB(atoi(vals[2 + i * 5 + 2]), atoi(vals[2 + i * 5 + 3]), atoi(vals[2 + i * 5 + 4])), breathe);
|
||||||
|
cycle(endclr, midclr, i*PIXELS_PER_LEAF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//uint8_t speed = beatsin8(6,0,255);
|
||||||
|
CRGB endclr = blend(CRGB(atoi(vals[2 + 2]), atoi(vals[2 + 3]), atoi(vals[2 + 4])), CRGB(atoi(vals[2 + (i + 1) * 5 + 2]), atoi(vals[2 + (i + 1) * 5 + 3]), atoi(vals[2 + (i + 1) * 5 + 4])), breathe);
|
||||||
|
CRGB midclr = blend(CRGB(atoi(vals[2 + (i + 1) * 5 + 2]), atoi(vals[2 + (i + 1) * 5 + 3]), atoi(vals[2 + (i + 1) * 5 + 4])), CRGB(atoi(vals[2 + 2]), atoi(vals[2 + 3]), atoi(vals[2 + 4])), breathe);
|
||||||
|
cycle(endclr, midclr, i*PIXELS_PER_LEAF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Serial.println("");
|
||||||
|
}
|
BIN
gallery/NodeRED_UI/alexa_skill.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
gallery/NodeRED_UI/autoplay_and_parameters.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
gallery/NodeRED_UI/conf_1.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
gallery/NodeRED_UI/config_1.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
gallery/NodeRED_UI/config_2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
gallery/NodeRED_UI/device_1.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
gallery/NodeRED_UI/device_2.png
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
gallery/NodeRED_UI/device_3.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
gallery/NodeRED_UI/device_4.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
gallery/NodeRED_UI/device_config.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
gallery/NodeRED_UI/full.png
Normal file
After Width: | Height: | Size: 147 KiB |
BIN
gallery/NodeRED_UI/import.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
gallery/NodeRED_UI/main.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
gallery/NodeRED_UI/nanoleaf_designer.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
gallery/NodeRED_UI/nanoleaf_designer_2.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
gallery/NodeRED_UI/pattern_designer.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
gallery/NodeRED_UI/pattern_designer_2.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
gallery/NodeRED_UI/patternlist.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
gallery/NodeRED_UI/patterns.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
gallery/electronics_box.jpg
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
gallery/electronics_box_level_shift.jpg
Normal file
After Width: | Height: | Size: 3.1 MiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 31 KiB |
BIN
web-app.png
Before Width: | Height: | Size: 83 KiB |
BIN
webapp.png
Before Width: | Height: | Size: 65 KiB |