first commit

This commit is contained in:
编码猿
2024-09-27 01:22:07 +08:00
commit 1360daaab0
931 changed files with 131068 additions and 0 deletions

1
code/WS2812FX/.pydio Normal file
View File

@@ -0,0 +1 @@
b6c8e0fa-9dc7-4735-91cc-045e8299d171

View File

@@ -0,0 +1 @@
2ca40a17-d7d4-4f89-888b-e826845d588d

View File

@@ -0,0 +1,39 @@
#include <WS2812FX.h>
#define LED_COUNT 30
#define LED_PIN 0
#define TIMER_MS 5000
// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_RGB + NEO_KHZ800);
unsigned long last_change = 0;
unsigned long now = 0;
void setup() {
ws2812fx.init();
ws2812fx.setBrightness(255);
ws2812fx.setSpeed(1000);
ws2812fx.setColor(0x007BFF);
ws2812fx.setMode(FX_MODE_STATIC);
ws2812fx.start();
}
void loop() {
now = millis();
ws2812fx.service();
if(now - last_change > TIMER_MS) {
ws2812fx.setMode((ws2812fx.getMode() + 1) % ws2812fx.getModeCount());
last_change = now;
}
}

View File

@@ -0,0 +1 @@
61b104dd-68f6-4978-8795-c6180b37892a

View File

@@ -0,0 +1,284 @@
/*
WS2812FX Webinterface.
Harm Aldick - 2016
www.aldick.org
FEATURES
* Webinterface with mode, color, speed and brightness selectors
LICENSE
The MIT License (MIT)
Copyright (c) 2016 Harm Aldick
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:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
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.
CHANGELOG
2016-11-26 initial version
2018-01-06 added custom effects list option and auto-cycle feature
*/
#ifdef ARDUINO_ARCH_ESP32
#include <WiFi.h>
#include <WebServer.h>
#define WEB_SERVER WebServer
#define ESP_RESET ESP.restart()
#else
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define WEB_SERVER ESP8266WebServer
#define ESP_RESET ESP.reset()
#endif
#include <WS2812FX.h>
extern const char index_html[];
extern const char main_js[];
#define WIFI_SSID "bmy"
#define WIFI_PASSWORD "lb714500"
//#define STATIC_IP // uncomment for static IP, set IP below
#ifdef STATIC_IP
IPAddress ip(192,168,0,123);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
#endif
// QUICKFIX...See https://github.com/esp8266/Arduino/issues/263
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define LED_PIN 0 // 0 = GPIO0, 2=GPIO2
#define LED_COUNT 30
#define WIFI_TIMEOUT 30000 // checks WiFi every ...ms. Reset after this time, if WiFi cannot reconnect.
#define HTTP_PORT 80
#define DEFAULT_COLOR 0xFF5900
#define DEFAULT_BRIGHTNESS 128
#define DEFAULT_SPEED 1500
#define DEFAULT_MODE FX_MODE_STATIC
unsigned long auto_last_change = 0;
unsigned long last_wifi_check_time = 0;
String modes = "";
uint8_t myModes[] = {}; // *** optionally create a custom list of effect/mode numbers
bool auto_cycle = false;
WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
WEB_SERVER server(HTTP_PORT);
void setup(){
Serial.begin(115200);
delay(500);
Serial.println("\n\nStarting...");
modes.reserve(5000);
modes_setup();
Serial.println("WS2812FX setup");
ws2812fx.init();
ws2812fx.setMode(DEFAULT_MODE);
ws2812fx.setColor(DEFAULT_COLOR);
ws2812fx.setSpeed(DEFAULT_SPEED);
ws2812fx.setBrightness(DEFAULT_BRIGHTNESS);
ws2812fx.start();
Serial.println("Wifi setup");
wifi_setup();
Serial.println("HTTP server setup");
server.on("/", srv_handle_index_html);
server.on("/main.js", srv_handle_main_js);
server.on("/modes", srv_handle_modes);
server.on("/set", srv_handle_set);
server.onNotFound(srv_handle_not_found);
server.begin();
Serial.println("HTTP server started.");
Serial.println("ready!");
}
void loop() {
unsigned long now = millis();
server.handleClient();
ws2812fx.service();
if(now - last_wifi_check_time > WIFI_TIMEOUT) {
Serial.print("Checking WiFi... ");
if(WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi connection lost. Reconnecting...");
wifi_setup();
} else {
Serial.println("OK");
}
last_wifi_check_time = now;
}
if(auto_cycle && (now - auto_last_change > 10000)) { // cycle effect mode every 10 seconds
uint8_t next_mode = (ws2812fx.getMode() + 1) % ws2812fx.getModeCount();
if(sizeof(myModes) > 0) { // if custom list of modes exists
for(uint8_t i=0; i < sizeof(myModes); i++) {
if(myModes[i] == ws2812fx.getMode()) {
next_mode = ((i + 1) < sizeof(myModes)) ? myModes[i + 1] : myModes[0];
break;
}
}
}
ws2812fx.setMode(next_mode);
Serial.print("mode is "); Serial.println(ws2812fx.getModeName(ws2812fx.getMode()));
auto_last_change = now;
}
}
/*
* Connect to WiFi. If no connection is made within WIFI_TIMEOUT, ESP gets resettet.
*/
void wifi_setup() {
Serial.println();
Serial.print("Connecting to ");
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
WiFi.mode(WIFI_STA);
#ifdef STATIC_IP
WiFi.config(ip, gateway, subnet);
#endif
unsigned long connect_start = millis();
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if(millis() - connect_start > WIFI_TIMEOUT) {
Serial.println();
Serial.print("Tried ");
Serial.print(WIFI_TIMEOUT);
Serial.print("ms. Resetting ESP now.");
ESP_RESET;
}
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.println();
}
/*
* Build <li> string for all modes.
*/
void modes_setup() {
modes = "";
uint8_t num_modes = sizeof(myModes) > 0 ? sizeof(myModes) : ws2812fx.getModeCount();
for(uint8_t i=0; i < num_modes; i++) {
uint8_t m = sizeof(myModes) > 0 ? myModes[i] : i;
modes += "<li><a href='#'>";
modes += ws2812fx.getModeName(m);
modes += "</a></li>";
}
}
/* #####################################################
# Webserver Functions
##################################################### */
void srv_handle_not_found() {
server.send(404, "text/plain", "File Not Found");
}
void srv_handle_index_html() {
server.send_P(200,"text/html", index_html);
}
void srv_handle_main_js() {
server.send_P(200,"application/javascript", main_js);
}
void srv_handle_modes() {
server.send(200,"text/plain", modes);
}
void srv_handle_set() {
for (uint8_t i=0; i < server.args(); i++){
if(server.argName(i) == "c") {
uint32_t tmp = (uint32_t) strtol(server.arg(i).c_str(), NULL, 10);
Serial.print("tmp ========= ");
Serial.println(tmp);
if(tmp >= 0x000000 && tmp <= 0xFFFFFF) {
ws2812fx.setColor(tmp);
}
}
if(server.argName(i) == "m") {
uint8_t tmp = (uint8_t) strtol(server.arg(i).c_str(), NULL, 10);
uint8_t new_mode = sizeof(myModes) > 0 ? myModes[tmp % sizeof(myModes)] : tmp % ws2812fx.getModeCount();
ws2812fx.setMode(new_mode);
Serial.print("mode is "); Serial.println(ws2812fx.getModeName(ws2812fx.getMode()));
}
if(server.argName(i) == "b") {
if(server.arg(i)[0] == '-') {
ws2812fx.setBrightness(ws2812fx.getBrightness() * 0.8);
} else if(server.arg(i)[0] == ' ') {
ws2812fx.setBrightness(min(max(ws2812fx.getBrightness(), 5) * 1.2, 255));
} else { // set brightness directly
uint8_t tmp = (uint8_t) strtol(server.arg(i).c_str(), NULL, 10);
ws2812fx.setBrightness(tmp);
}
Serial.print("brightness is "); Serial.println(ws2812fx.getBrightness());
}
if(server.argName(i) == "s") {
if(server.arg(i)[0] == '-') {
ws2812fx.setSpeed(max(ws2812fx.getSpeed(), 5) * 1.2);
} else if(server.arg(i)[0] == ' ') {
ws2812fx.setSpeed(ws2812fx.getSpeed() * 0.8);
} else {
uint16_t tmp = (uint16_t) strtol(server.arg(i).c_str(), NULL, 10);
ws2812fx.setSpeed(tmp);
}
Serial.print("speed is "); Serial.println(ws2812fx.getSpeed());
}
if(server.argName(i) == "a") {
if(server.arg(i)[0] == '-') {
auto_cycle = false;
} else {
auto_cycle = true;
auto_last_change = 0;
}
}
}
server.send(200, "text/plain", "OK");
}

View File

@@ -0,0 +1,114 @@
#include <pgmspace.h>
char index_html[] PROGMEM = R"=====(
<!doctype html>
<html lang='en' dir='ltr'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
<title>WS2812FX Control</title>
<script type='text/javascript' src='main.js'></script>
<style>
body {
font-family:Arial,sans-serif;
margin:10px;
padding:0;
background-color:#202020;
color:#909090;
text-align:center;
}
.flex-row {
display:flex;
flex-direction:row;
}
.flex-row-wrap {
display:flex;
flex-direction:row;
flex-wrap:wrap;
}
.flex-col {
display:flex;
flex-direction:column;
align-items:center;
}
input[type='text'] {
background-color: #d0d0d0;
color:#404040;
}
ul {
list-style-type: none;
}
ul li a {
display:block;
margin:3px;
padding:10px;
border:2px solid #404040;
border-radius:5px;
color:#909090;
text-decoration:none;
}
ul#modes li a {
min-width:220px;
}
ul.control li a {
min-width:60px;
min-height:24px;
}
ul.control {
display:flex;
flex-direction:row;
justify-content: flex-end;
align-items: center;
padding: 0px;
}
ul li a.active {
border:2px solid #909090;
}
</style>
</head>
<body>
<h1>WS2812FX Control</h1>
<div class='flex-row'>
<div class='flex-col'>
<div><canvas id='color-canvas' width='360' height='360'></canvas><br/></div>
<div><input type='text' id='color-value' oninput='onColor(event, this.value)'/></div>
<div>
<ul class='control'>
<li>Brightness:</li>
<li><a href='#' onclick="onBrightness(event, '-')">&#9788;</a></li>
<li><a href='#' onclick="onBrightness(event, '+')">&#9728;</a></li>
</ul>
<ul class='control'>
<li>Speed:</li>
<li><a href='#' onclick="onSpeed(event, '-')">&#8722;</a></li>
<li><a href='#' onclick="onSpeed(event, '+')">&#43;</a></li>
</ul>
<ul class='control'>
<li>Auto cycle:</li>
<li><a href='#' onclick="onAuto(event, '-')">&#9632;</a></li>
<li><a href='#' onclick="onAuto(event, '+')">&#9658;</a></li>
</ul>
</div>
</div>
<div>
<ul id='modes' class='flex-row-wrap'>
</div>
</div>
</body>
</html>
)=====";

View File

@@ -0,0 +1,110 @@
#include <pgmspace.h>
/*
The tiny Javascript/canvas based color picker is based on the clever work of the folks
at Sparkbox. https://seesparkbox.com/foundry/how_i_built_a_canvas_color_picker
*/
char main_js[] PROGMEM = R"=====(
var activeButton = null;
var colorCanvas = null;
window.addEventListener('DOMContentLoaded', (event) => {
// init the canvas color picker
colorCanvas = document.getElementById('color-canvas');
var colorctx = colorCanvas.getContext('2d');
// Create color gradient
var gradient = colorctx.createLinearGradient(0, 0, colorCanvas.width - 1, 0);
gradient.addColorStop(0, "rgb(255, 0, 0)");
gradient.addColorStop(0.16, "rgb(255, 0, 255)");
gradient.addColorStop(0.33, "rgb(0, 0, 255)");
gradient.addColorStop(0.49, "rgb(0, 255, 255)");
gradient.addColorStop(0.66, "rgb(0, 255, 0)");
gradient.addColorStop(0.82, "rgb(255, 255, 0)");
gradient.addColorStop(1, "rgb(255, 0, 0)");
// Apply gradient to canvas
colorctx.fillStyle = gradient;
colorctx.fillRect(0, 0, colorCanvas.width - 1, colorCanvas.height - 1);
// Create semi transparent gradient (white -> transparent -> black)
gradient = colorctx.createLinearGradient(0, 0, 0, colorCanvas.height - 1);
gradient.addColorStop(0, "rgba(255, 255, 255, 1)");
gradient.addColorStop(0.48, "rgba(255, 255, 255, 0)");
gradient.addColorStop(0.52, "rgba(0, 0, 0, 0)");
gradient.addColorStop(1, "rgba(0, 0, 0, 1)");
// Apply gradient to canvas
colorctx.fillStyle = gradient;
colorctx.fillRect(0, 0, colorCanvas.width - 1, colorCanvas.height - 1);
// setup the canvas click listener
colorCanvas.addEventListener('click', (event) => {
var imageData = colorCanvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1);
var selectedColor = 'rgb(' + imageData.data[0] + ',' + imageData.data[1] + ',' + imageData.data[2] + ')';
//console.log('click: ' + event.offsetX + ', ' + event.offsetY + ', ' + selectedColor);
document.getElementById('color-value').value = selectedColor;
selectedColor = imageData.data[0] * 65536 + imageData.data[1] * 256 + imageData.data[2];
submitVal('c', selectedColor);
});
// get list of modes from ESP
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
document.getElementById('modes').innerHTML = xhttp.responseText;
modes = document.querySelectorAll('ul#modes li a');
modes.forEach(initMode);
}
};
xhttp.open('GET', 'modes', true);
xhttp.send();
});
function initMode(mode, index) {
mode.addEventListener('click', (event) => onMode(event, index));
}
function onColor(event, color) {
event.preventDefault();
var match = color.match(/rgb\(([0-9]*),([0-9]*),([0-9]*)\)/);
if(match) {
var colorValue = Number(match[1]) * 65536 + Number(match[2]) * 256 + Number(match[3]);
//console.log('onColor:' + match[1] + "," + match[2] + "," + match[3] + "," + colorValue);
submitVal('c', colorValue);
}
}
function onMode(event, mode) {
event.preventDefault();
if(activeButton) activeButton.classList.remove('active')
activeButton = event.target;
activeButton.classList.add('active');
submitVal('m', mode);
}
function onBrightness(event, dir) {
event.preventDefault();
submitVal('b', dir);
}
function onSpeed(event, dir) {
event.preventDefault();
submitVal('s', dir);
}
function onAuto(event, dir) {
event.preventDefault();
submitVal('a', dir);
}
function submitVal(name, val) {
var xhttp = new XMLHttpRequest();
xhttp.open('GET', 'set?' + name + '=' + val, true);
xhttp.send();
}
)=====";