Merge branch 'master' into dev

This commit is contained in:
Blaž Kristan 2021-07-01 13:41:23 +02:00
commit b58efa3df0
18 changed files with 2382 additions and 1896 deletions

View File

@ -2,6 +2,14 @@
### Builds after release 0.12.0 ### Builds after release 0.12.0
#### Build 2106302
- Fixed settings page broken by using "%" in input fields
#### Build 2106301
- Fixed a problem with disabled buttons reverting to pin 0 causing conflict
#### Build 2106300 #### Build 2106300
- Version bump to 0.13.0-b0 "Toki" - Version bump to 0.13.0-b0 "Toki"

View File

@ -267,7 +267,7 @@ build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
[env:esp32dev] [env:esp32dev]
board = esp32dev board = esp32dev
platform = espressif32@3.2 platform = espressif32@2.0
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32
lib_ignore = lib_ignore =
@ -276,7 +276,7 @@ lib_ignore =
[env:esp32_eth] [env:esp32_eth]
board = esp32-poe board = esp32-poe
platform = espressif32@3.2 platform = espressif32@2.0
upload_speed = 921600 upload_speed = 921600
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
@ -354,19 +354,22 @@ build_flags = ${common.build_flags_esp8266} -D LEDPIN=12 -D IRPIN=-1 -D RLYPIN=2
[env:wemos_shield_esp32] [env:wemos_shield_esp32]
board = esp32dev board = esp32dev
platform = espressif32@^3.2 platform = espressif32@3.2
upload_port = /dev/cu.SLAB_USBtoUART
monitor_port = /dev/cu.SLAB_USBtoUART
upload_speed = 460800 upload_speed = 460800
build_unflags = ${common.build_unflags} build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32} -D LEDPIN=16 -D RLYPIN=19 -D BTNPIN=17 -D IRPIN=18 build_flags = ${common.build_flags_esp32}
-D USERMOD_DALLASTEMPERATURE -D LEDPIN=16
-D TEMPERATURE_PIN=23 -D RLYPIN=19
-D USERMOD_FOUR_LINE_DISPLAY -D BTNPIN=17
-D UWLED_USE_MY_CONFIG
; -D USERMOD_DALLASTEMPERATURE
; -D USERMOD_DALLASTEMPERATURE_CELCIUS
; -D USERMOD_FOUR_LINE_DISPLAY
; -D TEMPERATURE_PIN=21
lib_deps = ${env.lib_deps} lib_deps = ${env.lib_deps}
OneWire@~2.3.5 ; OneWire@~2.3.5
U8g2@~2.28.8 ; milesburton/DallasTemperature@^3.9.0
Wire ; U8g2@~2.27.2
lib_ignore = lib_ignore =
ESPAsyncTCP ESPAsyncTCP
ESPAsyncUDP ESPAsyncUDP
@ -456,3 +459,4 @@ monitor_filters = esp32_exception_decoder
lib_ignore = lib_ignore =
ESPAsyncTCP ESPAsyncTCP
ESPAsyncUDP ESPAsyncUDP

View File

@ -9,7 +9,6 @@
<a href="https://gitpod.io/#https://github.com/Aircoookie/WLED"><img src="https://img.shields.io/badge/Gitpod-ready--to--code-blue?style=flat-square&logo=gitpod"></a> <a href="https://gitpod.io/#https://github.com/Aircoookie/WLED"><img src="https://img.shields.io/badge/Gitpod-ready--to--code-blue?style=flat-square&logo=gitpod"></a>
</p> </p>
# Welcome to my project WLED! ✨ # Welcome to my project WLED! ✨
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102! A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102!

View File

@ -0,0 +1,72 @@
# ST7789 TFT IPS Color display 240x240pxwith ESP32 boards
This usermod allow to use 240x240 display to display following:
* Network SSID;
* IP address;
* Brightness;
* Chosen effect;
* Chosen palette;
* Estimated current in mA;
## Hardware
***
![Hardware](images/ST7789_guide.jpg)
## Library used
[Bodmer/TFT_eSPI](https://github.com/Bodmer/TFT_eSPI)
## Setup
***
### Platformio.ini changes
In the `platformio.ini` file, uncomment the `TFT_eSPI` line within the [common] section, under `lib_deps`:
```ini
# platformio.ini
...
[common]
...
lib_deps =
...
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
#TFT_eSPI
...
```
Also, while in the `platformio.ini` file, you must change the environment setup to build for just the esp32dev platform as follows:
Add lines to section:
```ini
default_envs = esp32dev
build_flags = ${common.build_flags_esp32}
-D USERMOD_ST7789_DISPLAY
```
Save the `platformio.ini` file. Once this is saved, the required library files should be automatically downloaded for modifications in a later step.
### TFT_eSPI Library Adjustments
We need to modify a file in the `TFT_eSPI` library. If you followed the directions to modify and save the `platformio.ini` file above, the `User_Setup_Select.h` file can be found in the `/.pio/libdeps/esp32dev/TFT_eSPI` folder.
Modify the `User_Setup_Select.h` file as follows:
* Comment out the following line (which is the 'default' setup file):
```ini
//#include <User_Setup.h> // Default setup is root library folder
```
* Add following line:
```ini
#include <User_Setups/Setup_ST7789_Display.h> // Setup file for ESP32 ST7789V SPI bus TFT
```
* Copy file `"Setup_ST7789_Display.h"` from usermod folder to `/.pio/libdeps/esp32dev/TFT_eSPI/User_Setups`

View File

@ -0,0 +1,350 @@
// Credits to @mrVanboy, @gwaland and my dearest friend @westward
// Also for @spiff72 for usermod TTGO-T-Display
// 210217
#pragma once
#include "wled.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#define USERMOD_ST7789_DISPLAY 97
#ifndef TFT_DISPOFF
#define TFT_DISPOFF 0x28
#endif
#ifndef TFT_SLPIN
#define TFT_SLPIN 0x10
#endif
#define TFT_MOSI 21
#define TFT_SCLK 22
#define TFT_DC 18
#define TFT_RST 5
#define TFT_BL 26 // Display backlight control pin
TFT_eSPI tft = TFT_eSPI(240, 240); // Invoke custom library
// How often we are redrawing screen
#define USER_LOOP_REFRESH_RATE_MS 1000
//class name. Use something descriptive and leave the ": public Usermod" part :)
class St7789DisplayUsermod : public Usermod {
private:
//Private class members. You can declare variables and functions only accessible to your usermod here
unsigned long lastTime = 0;
bool displayTurnedOff = false;
long lastRedraw = 0;
// needRedraw marks if redraw is required to prevent often redrawing.
bool needRedraw = true;
// Next variables hold the previous known values to determine if redraw is required.
String knownSsid = "";
IPAddress knownIp;
uint8_t knownBrightness = 0;
uint8_t knownMode = 0;
uint8_t knownPalette = 0;
uint8_t tftcharwidth = 19; // Number of chars that fit on screen with text size set to 2
long lastUpdate = 0;
public:
//Functions called by WLED
/*
* setup() is called once at boot. WiFi is not yet connected at this point.
* You can use it to initialize variables, sensors or similar.
*/
void setup()
{
tft.init();
tft.setRotation(0); //Rotation here is set up for the text to be readable with the port on the left. Use 1 to flip.
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_RED);
tft.setCursor(60, 100);
tft.setTextDatum(MC_DATUM);
tft.setTextSize(2);
tft.print("Loading...");
if (TFT_BL > 0)
{ // TFT_BL has been set in the TFT_eSPI library
pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
digitalWrite(TFT_BL, HIGH); // Turn backlight on.
}
}
/*
* connected() is called every time the WiFi is (re)connected
* Use it to initialize network interfaces
*/
void connected() {
//Serial.println("Connected to WiFi!");
}
/*
* loop() is called continuously. Here you can check for events, read sensors, etc.
*
* Tips:
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
*
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
* Instead, use a timer check as shown here.
*/
void loop() {
// Check if we time interval for redrawing passes.
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS)
{
return;
}
lastUpdate = millis();
// Turn off display after 5 minutes with no change.
if(!displayTurnedOff && millis() - lastRedraw > 5*60*1000)
{
digitalWrite(TFT_BL, LOW); // Turn backlight off.
displayTurnedOff = true;
}
// Check if values which are shown on display changed from the last time.
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid)
{
needRedraw = true;
}
else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP()))
{
needRedraw = true;
}
else if (knownBrightness != bri)
{
needRedraw = true;
}
else if (knownMode != strip.getMode())
{
needRedraw = true;
}
else if (knownPalette != strip.getSegment(0).palette)
{
needRedraw = true;
}
if (!needRedraw)
{
return;
}
needRedraw = false;
if (displayTurnedOff)
{
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); // Turn backlight on.
displayTurnedOff = false;
}
lastRedraw = millis();
// Update last known values.
#if defined(ESP8266)
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
#else
knownSsid = WiFi.SSID();
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
tft.fillScreen(TFT_BLACK);
tft.setTextSize(2);
// First row with Wifi name
tft.setTextColor(TFT_SILVER);
tft.setCursor(3, 40);
tft.print(knownSsid.substring(0, tftcharwidth > 1 ? tftcharwidth - 1 : 0));
// Print `~` char to indicate that SSID is longer, than our dicplay
if (knownSsid.length() > tftcharwidth)
tft.print("~");
// Second row with AP IP and Password or IP
tft.setTextColor(TFT_GREEN);
tft.setTextSize(2);
tft.setCursor(3, 64);
// Print AP IP and password in AP mode or knownIP if AP not active.
if (apActive)
{
tft.setTextColor(TFT_YELLOW);
tft.print("AP IP: ");
tft.print(knownIp);
tft.setCursor(3,86);
tft.setTextColor(TFT_YELLOW);
tft.print("AP Pass:");
tft.print(apPass);
}
else
{
tft.setTextColor(TFT_GREEN);
tft.print("IP: ");
tft.print(knownIp);
tft.setCursor(3,86);
//tft.print("Signal Strength: ");
//tft.print(i.wifi.signal);
tft.setTextColor(TFT_WHITE);
tft.print("Bri: ");
tft.print(((float(bri)/255)*100),0);
tft.print("%");
}
// Third row with mode name
tft.setCursor(3, 108);
uint8_t qComma = 0;
bool insideQuotes = false;
uint8_t printedChars = 0;
char singleJsonSymbol;
// Find the mode name in JSON
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++)
{
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
switch (singleJsonSymbol)
{
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownMode))
break;
tft.setTextColor(TFT_MAGENTA);
tft.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > tftcharwidth - 1))
break;
}
// Fourth row with palette name
tft.setTextColor(TFT_YELLOW);
tft.setCursor(3, 130);
qComma = 0;
insideQuotes = false;
printedChars = 0;
// Looking for palette name in JSON.
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++)
{
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
switch (singleJsonSymbol)
{
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownPalette))
break;
tft.print(singleJsonSymbol);
printedChars++;
}
// The following is modified from the code from the u8g2/u8g8 based code (knownPalette was knownMode)
if ((qComma > knownPalette) || (printedChars > tftcharwidth - 1))
break;
}
// Fifth row with estimated mA usage
tft.setTextColor(TFT_SILVER);
tft.setCursor(3, 152);
// Print estimated milliamp usage (must specify the LED type in LED prefs for this to be a reasonable estimate).
tft.print("Current: ");
tft.print(strip.currentMilliamps);
tft.print("mA");
}
/*
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
* Below it is shown how this could be used for e.g. a light sensor
*/
/*
void addToJsonInfo(JsonObject& root)
{
int reading = 20;
//this code adds "u":{"Light":[20," lux"]} to the info object
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
JsonArray lightArr = user.createNestedArray("Light"); //name
lightArr.add(reading); //value
lightArr.add(" lux"); //unit
}
*/
/*
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void addToJsonState(JsonObject& root)
{
//root["user0"] = userVar0;
}
/*
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
* Values in the state object may be modified by connected clients
*/
void readFromJsonState(JsonObject& root)
{
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
}
/*
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
* If you want to force saving the current state, use serializeConfig() in your loop().
*
* CAUTION: serializeConfig() will initiate a filesystem write operation.
* It might cause the LEDs to stutter and will cause flash wear if called too often.
* Use it sparingly and always in the loop, never in network callbacks!
*
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
*
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
*/
void addToConfig(JsonObject& root)
{
JsonObject top = root.createNestedObject("exampleUsermod");
top["great"] = userVar0; //save this var persistently whenever settings are saved
}
/*
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
*
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
*/
void readFromConfig(JsonObject& root)
{
JsonObject top = root["top"];
userVar0 = top["great"] | 42; //The value right of the pipe "|" is the default value in case your setting was not present in cfg.json (e.g. first boot)
}
/*
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
* This could be used in the future for the system to determine whether your usermod is installed.
*/
uint16_t getId()
{
return USERMOD_ST7789_DISPLAY;
}
//More methods can be added in the future, this example will then be extended.
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
};

View File

@ -0,0 +1,39 @@
// Setup for the ESP32 board with 1.5" 240x240 display
// See SetupX_Template.h for all options available
#define ST7789_DRIVER
#define TFT_SDA_READ // Display has a bidirectionsl SDA pin
#define TFT_WIDTH 240
#define TFT_HEIGHT 240
#define CGRAM_OFFSET // Library will add offsets required
//#define TFT_MISO -1
#define TFT_MOSI 21
#define TFT_SCLK 22
//#define TFT_CS 5
#define TFT_DC 18
#define TFT_RST 5
#define TFT_BL 26 // Display backlight control pin
#define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options
#define LOAD_GLCD
#define LOAD_FONT2
#define LOAD_FONT4
#define LOAD_FONT6
#define LOAD_FONT7
#define LOAD_FONT8
#define LOAD_GFXFF
//#define SMOOTH_FONT
//#define SPI_FREQUENCY 27000000
#define SPI_FREQUENCY 40000000 // Maximum for ILI9341
#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

View File

@ -23,7 +23,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
getStringFromJson(serverDescription, id[F("name")], 33); getStringFromJson(serverDescription, id[F("name")], 33);
getStringFromJson(alexaInvocationName, id[F("inv")], 33); getStringFromJson(alexaInvocationName, id[F("inv")], 33);
JsonObject nw_ins_0 = doc["nw"][F("ins")][0]; JsonObject nw_ins_0 = doc["nw"]["ins"][0];
getStringFromJson(clientSSID, nw_ins_0[F("ssid")], 33); getStringFromJson(clientSSID, nw_ins_0[F("ssid")], 33);
//int nw_ins_0_pskl = nw_ins_0[F("pskl")]; //int nw_ins_0_pskl = nw_ins_0[F("pskl")];
//The WiFi PSK is normally not contained in the regular file for security reasons. //The WiFi PSK is normally not contained in the regular file for security reasons.
@ -126,7 +126,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
uint8_t s = 0; uint8_t s = 0;
for (JsonObject btn : hw_btn_ins) { for (JsonObject btn : hw_btn_ins) {
CJSON(buttonType[s], btn["type"]); CJSON(buttonType[s], btn["type"]);
int8_t pin = btn[F("pin")][0] | -1; int8_t pin = btn["pin"][0] | -1;
if (pin > -1 && pinManager.allocatePin(pin,false)) { if (pin > -1 && pinManager.allocatePin(pin,false)) {
btnPin[s] = pin; btnPin[s] = pin;
pinMode(btnPin[s], INPUT_PULLUP); pinMode(btnPin[s], INPUT_PULLUP);
@ -731,7 +731,7 @@ bool deserializeConfigSec() {
bool success = readObjectFromFile("/wsec.json", nullptr, &doc); bool success = readObjectFromFile("/wsec.json", nullptr, &doc);
if (!success) return false; if (!success) return false;
JsonObject nw_ins_0 = doc["nw"][F("ins")][0]; JsonObject nw_ins_0 = doc["nw"]["ins"][0];
getStringFromJson(clientPass, nw_ins_0["psk"], 65); getStringFromJson(clientPass, nw_ins_0["psk"], 65);
JsonObject ap = doc["ap"]; JsonObject ap = doc["ap"];

View File

@ -282,11 +282,11 @@ Color Order:
<option value="4">BGR</option> <option value="4">BGR</option>
<option value="5">GBR</option> <option value="5">GBR</option>
</select><br> </select><br>
<span id="p0d${i}">GPIO:</span><input type="number" name="L0${i}" min="0" max="33" required class="sml" onchange="UI()"/> <span id="p0d${i}">GPIO:</span><input type="number" name="L0${i}" min="0" max="33" required class="s" onchange="UI()"/>
<span id="p1d${i}"></span><input type="number" name="L1${i}" min="0" max="33" class="sml" onchange="UI()"/> <span id="p1d${i}"></span><input type="number" name="L1${i}" min="0" max="33" class="s" onchange="UI()"/>
<span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="33" class="sml" onchange="UI()"/> <span id="p2d${i}"></span><input type="number" name="L2${i}" min="0" max="33" class="s" onchange="UI()"/>
<span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="33" class="sml" onchange="UI()"/> <span id="p3d${i}"></span><input type="number" name="L3${i}" min="0" max="33" class="s" onchange="UI()"/>
<span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="33" class="sml" onchange="UI()"/> <span id="p4d${i}"></span><input type="number" name="L4${i}" min="0" max="33" class="s" onchange="UI()"/>
<br> <br>
<span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" readonly required />&nbsp; <span id="psd${i}">Start:</span> <input type="number" name="LS${i}" id="ls${i}" min="0" max="8191" value="${lastEnd(i)}" readonly required />&nbsp;
<div id="dig${i}" style="display:inline"> <div id="dig${i}" style="display:inline">
@ -310,7 +310,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
var c = gId("btns").innerHTML; var c = gId("btns").innerHTML;
var bt = "BT" + i; var bt = "BT" + i;
var be = "BE" + i; var be = "BE" + i;
c += `Button ${i} GPIO: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" class="sml" value="${p}">`; c += `Button ${i} GPIO: <input type="number" min="-1" max="40" name="${bt}" onchange="UI()" class="s" value="${p}">`;
c += `<select name="${be}">` c += `<select name="${be}">`
c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`; c += `<option value="0" ${t==0?"selected":""}>Disabled</option>`;
c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`; c += `<option value="2" ${t==2?"selected":""}>Pushbutton</option>`;
@ -392,7 +392,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
</div><hr style="width:260px"> </div><hr style="width:260px">
<div id="btns"></div> <div id="btns"></div>
Touch threshold: <input type="number" min="0" max="100" name="TT" required><br> Touch threshold: <input type="number" min="0" max="100" name="TT" required><br>
IR GPIO: <input type="number" min="-1" max="40" name="IR" onchange="UI()" class="sml"><select name="IT" onchange="UI()"> IR GPIO: <input type="number" min="-1" max="40" name="IR" onchange="UI()" class="s"><select name="IT" onchange="UI()">
<option value="0">Remote disabled</option> <option value="0">Remote disabled</option>
<option value="1">24-key RGB</option> <option value="1">24-key RGB</option>
<option value="2">24-key with CT</option> <option value="2">24-key with CT</option>
@ -406,7 +406,7 @@ Reverse (rotated 180°): <input type="checkbox" name="CV${i}">
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"> <input type="button" value="Upload" onclick="uploadFile('/ir.json');"><br></div> <div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"> <input type="button" value="Upload" onclick="uploadFile('/ir.json');"><br></div>
<div id="toast"></div> <div id="toast"></div>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><br> <a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a><br>
Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()" class="sml"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')">&nbsp;&#215;</span><br> Relay pin: <input type="number" min="-1" max="40" name="RL" onchange="UI()" class="s"> invert <input type="checkbox" name="RM"><span style="cursor: pointer;" onclick="off('RL')">&nbsp;&#215;</span><br>
<hr style="width:260px"> <hr style="width:260px">
<h3>Defaults</h3> <h3>Defaults</h3>
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br> Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>

View File

@ -86,11 +86,11 @@
td = tr.insertCell(0); td = tr.insertCell(0);
td.innerHTML = `Button ${i}:`; td.innerHTML = `Button ${i}:`;
td = tr.insertCell(1); td = tr.insertCell(1);
td.innerHTML = `<input name="MP${i}" type="number" class="med" min="0" max="250" value="${p}" required>`; td.innerHTML = `<input name="MP${i}" type="number" class="m" min="0" max="250" value="${p}" required>`;
td = tr.insertCell(2); td = tr.insertCell(2);
td.innerHTML = `<input name="ML${i}" type="number" class="med" min="0" max="250" value="${l}" required>`; td.innerHTML = `<input name="ML${i}" type="number" class="m" min="0" max="250" value="${l}" required>`;
td = tr.insertCell(3); td = tr.insertCell(3);
td.innerHTML = `<input name="MD${i}" type="number" class="med" min="0" max="250" value="${d}" required>`; td.innerHTML = `<input name="MD${i}" type="number" class="m" min="0" max="250" value="${d}" required>`;
} }
function GetV() function GetV()
{ {
@ -134,8 +134,8 @@
</select><br> </select><br>
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br> UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
Current local time is <span class="times">unknown</span>.<br> Current local time is <span class="times">unknown</span>.<br>
Latitude (N): <input name="LT" type="number" class="big" min="-66.6" max="66.6" step="0.01"> Latitude (N): <input name="LT" type="number" class="xl" min="-66.6" max="66.6" step="0.01">
Longitude (E): <input name="LN" type="number" class="big" min="-180" max="180" step="0.01"> Longitude (E): <input name="LN" type="number" class="xl" min="-180" max="180" step="0.01">
<div id="sun" class="times"></div> <div id="sun" class="times"></div>
<h3>Clock</h3> <h3>Clock</h3>
Clock Overlay: Clock Overlay:

View File

@ -81,7 +81,7 @@
case "number": case "number":
c = `value="${o}"`; c = `value="${o}"`;
if (f.substr(-3)==="pin") { if (f.substr(-3)==="pin") {
c += ' max="39" min="-1" class="sml"'; c += ' max="39" min="-1" class="s"';
t = "int"; t = "int";
} else { } else {
c += ' step="0.00001" class="xxl"'; c += ' step="0.00001" class="xxl"';

View File

@ -32,20 +32,20 @@
Network name (SSID, empty to not connect): <br><input name="CS" maxlength="32"><br> Network name (SSID, empty to not connect): <br><input name="CS" maxlength="32"><br>
Network password: <br> <input type="password" name="CP" maxlength="63"><br> Network password: <br> <input type="password" name="CP" maxlength="63"><br>
Static IP (leave at 0.0.0.0 for DHCP):<br> Static IP (leave at 0.0.0.0 for DHCP):<br>
<input name="I0" type="number" min="0" max="255" required> . <input name="I0" type="number" class="s" min="0" max="255" required> .
<input name="I1" type="number" min="0" max="255" required> . <input name="I1" type="number" class="s" min="0" max="255" required> .
<input name="I2" type="number" min="0" max="255" required> . <input name="I2" type="number" class="s" min="0" max="255" required> .
<input name="I3" type="number" min="0" max="255" required><br> <input name="I3" type="number" class="s" min="0" max="255" required><br>
Static gateway:<br> Static gateway:<br>
<input name="G0" type="number" min="0" max="255" required> . <input name="G0" type="number" class="s" min="0" max="255" required> .
<input name="G1" type="number" min="0" max="255" required> . <input name="G1" type="number" class="s" min="0" max="255" required> .
<input name="G2" type="number" min="0" max="255" required> . <input name="G2" type="number" class="s" min="0" max="255" required> .
<input name="G3" type="number" min="0" max="255" required><br> <input name="G3" type="number" class="s" min="0" max="255" required><br>
Static subnet mask:<br> Static subnet mask:<br>
<input name="S0" type="number" min="0" max="255" required> . <input name="S0" type="number" class="s" min="0" max="255" required> .
<input name="S1" type="number" min="0" max="255" required> . <input name="S1" type="number" class="s" min="0" max="255" required> .
<input name="S2" type="number" min="0" max="255" required> . <input name="S2" type="number" class="s" min="0" max="255" required> .
<input name="S3" type="number" min="0" max="255" required><br> <input name="S3" type="number" class="s" min="0" max="255" required><br>
mDNS address (leave empty for no mDNS):<br/> mDNS address (leave empty for no mDNS):<br/>
http:// <input name="CM" maxlength="32"> .local<br> http:// <input name="CM" maxlength="32"> .local<br>
Client IP: <span class="sip"> Not connected </span> <br> Client IP: <span class="sip"> Not connected </span> <br>
@ -53,7 +53,7 @@
AP SSID (leave empty for no AP):<br> <input name="AS" maxlength="32"><br> AP SSID (leave empty for no AP):<br> <input name="AS" maxlength="32"><br>
Hide AP name: <input type="checkbox" name="AH"><br> Hide AP name: <input type="checkbox" name="AH"><br>
AP password (leave empty for open):<br> <input type="password" name="AP" maxlength="63" pattern="(.{8,63})|()" title="Empty or min. 8 characters"><br> AP password (leave empty for open):<br> <input type="password" name="AP" maxlength="63" pattern="(.{8,63})|()" title="Empty or min. 8 characters"><br>
Access Point WiFi channel: <input name="AC" type="number" min="1" max="13" required><br> Access Point WiFi channel: <input name="AC" type="number" class="xs" min="1" max="13" required><br>
AP opens: AP opens:
<select name="AB"> <select name="AB">
<option value="0">No connection after boot</option> <option value="0">No connection after boot</option>

View File

@ -50,14 +50,20 @@ input[type="number"] {
input[type="number"].xxl { input[type="number"].xxl {
width: 100px; width: 100px;
} }
input[type="number"].big { input[type="number"].xl {
width: 85px; width: 85px;
} }
input[type="number"].med { input[type="number"].l {
width: 60px;
}
input[type="number"].m {
width: 55px; width: 55px;
} }
input[type="number"].sml { input[type="number"].s {
width: 40px; width: 42px;
}
input[type="number"].xs {
width: 35px;
} }
select { select {
margin: 2px; margin: 2px;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -167,22 +167,22 @@ void decodeIR(uint32_t code)
// if (decodeIRCustom(code)) return; // if (decodeIRCustom(code)) return;
if (code > 0xFFFFFF) return; //invalid code if (code > 0xFFFFFF) return; //invalid code
switch (irEnabled) { switch (irEnabled) {
case 1: case 1:
if (code > 0xF80000) { if (code > 0xF80000) {
decodeIR24OLD(code); // white 24-key remote (old) - it sends 0xFF0000 values decodeIR24OLD(code); // white 24-key remote (old) - it sends 0xFF0000 values
} else { } else {
decodeIR24(code); //is in 24-key remote range decodeIR24(code); // 24-key remote - 0xF70000 to 0xF80000
} }
break; break;
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
case 5: decodeIR21(code); break; // white 21-key remote case 5: decodeIR21(code); break; // white 21-key remote
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness, case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE" // "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
// sets bright plain white // sets bright plain white
case 7: decodeIR9(code); break; case 7: decodeIR9(code); break;
case 8: decodeIRJson(code); break; // any remote configurable with ir.json file case 8: decodeIRJson(code); break; // any remote configurable with ir.json file
default: return; default: return;
} }
@ -537,8 +537,8 @@ void decodeIR9(uint32_t code)
lastValidCode = code; lastValidCode = code;
} }
/* /*
Code by Scott R Bailey @ https://github.com/scottrbailey
This allows users to customize IR actions without the need to edit C code and compile. This allows users to customize IR actions without the need to edit C code and compile.
From the https://github.com/Aircoookie/WLED/wiki/Infrared-Control page, download the starter From the https://github.com/Aircoookie/WLED/wiki/Infrared-Control page, download the starter
ir.json file that corresponds to the number of buttons on your remote. ir.json file that corresponds to the number of buttons on your remote.

View File

@ -455,11 +455,8 @@ void WLED::beginStrip()
colorUpdated(NOTIFIER_CALL_MODE_INIT); colorUpdated(NOTIFIER_CALL_MODE_INIT);
// init relay pin // init relay pin
if (rlyPin>=0) digitalWrite(rlyPin, (bri ? rlyMde : !rlyMde)); if (rlyPin>=0)
digitalWrite(rlyPin, (rlyMde ? bri : !bri));
// disable button if it is "pressed" unintentionally
//if (btnPin>=0 && buttonType == BTN_TYPE_PUSH && isButtonPressed())
// buttonType = BTN_TYPE_NONE;
} }
void WLED::initAP(bool resetAP) void WLED::initAP(bool resetAP)

View File

@ -159,13 +159,24 @@ void sappends(char stype, const char* key, char* val)
{ {
switch(stype) switch(stype)
{ {
case 's': //string (we can interpret val as char*) case 's': { //string (we can interpret val as char*)
oappend("d.Sf."); oappend("d.Sf.");
oappend(key); oappend(key);
oappend(".value=\""); oappend(".value=\"");
oappend(val); //convert "%" to "%%" to make EspAsyncWebServer happy
char buf[130];
uint8_t len = strlen(val) +1;
uint8_t s = 0;
for (uint8_t i = 0; i < len; i++) {
buf[i+s] = val[i];
if (val[i] == '%') {
s++; buf[i+s] = '%';
}
}
oappend(buf);
oappend("\";"); oappend("\";");
break; break; }
case 'm': //message case 'm': //message
oappend(SET_F("d.getElementsByClassName")); oappend(SET_F("d.getElementsByClassName"));
oappend(key); oappend(key);