Merge branch 'master' into dev
This commit is contained in:
commit
65ac8d4b2b
14
CHANGELOG.md
14
CHANGELOG.md
@ -2,6 +2,20 @@
|
||||
|
||||
### Builds after release 0.12.0
|
||||
|
||||
#### Build 2111160
|
||||
|
||||
- Version bump to 0.13.0-b5 "Toki"
|
||||
- Improv Serial support (PR #2334)
|
||||
- Button improvements (PR #2284)
|
||||
- Added two time zones (PR #2264, 2311)
|
||||
- JSON in/decrementing support for brightness and presets
|
||||
- Fixed no gamma correction for JSON individual LED control
|
||||
- Preset cycle bugfix
|
||||
- Removed ledCount
|
||||
- LED settings buffer bugfix
|
||||
- Network pin conflict bugfix
|
||||
- Changed default ESP32 partition layout to 4M, 1M FS
|
||||
|
||||
#### Build 2110110
|
||||
|
||||
- Version bump to 0.13.0-b4 "Toki"
|
||||
|
@ -208,6 +208,8 @@ build_flags = -g
|
||||
-DCONFIG_LITTLEFS_FOR_IDF_3_2
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
|
||||
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
makuna/NeoPixelBus @ 2.6.7
|
||||
@ -293,6 +295,7 @@ platform = espressif32@2.0
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
[env:esp32_eth]
|
||||
board = esp32-poe
|
||||
@ -301,6 +304,7 @@ upload_speed = 921600
|
||||
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
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
[env:esp32s2_saola]
|
||||
board = esp32dev
|
||||
@ -407,6 +411,7 @@ build_flags = ${common.build_flags_esp32}
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
OneWire@~2.3.5
|
||||
olikraus/U8g2 @ ^2.28.8
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
[env:m5atom]
|
||||
board = esp32dev
|
||||
@ -414,6 +419,7 @@ build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
platform = espressif32@3.2
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
[env:sp501e]
|
||||
board = esp_wroom_02
|
||||
@ -499,3 +505,4 @@ monitor_filters = esp32_exception_decoder
|
||||
lib_deps =
|
||||
${esp32.lib_deps}
|
||||
TFT_eSPI @ ^2.3.70
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
@ -299,8 +299,11 @@ void handleIO()
|
||||
#ifdef ESP8266
|
||||
// turn off built-in LED if strip is turned off
|
||||
// this will break digital bus so will need to be reinitialised on On
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
PinOwner ledPinOwner = pinManager.getPinOwner(LED_BUILTIN);
|
||||
if (!strip.isOffRefreshRequred && (ledPinOwner == PinOwner::None || ledPinOwner == PinOwner::BusDigital)) {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
}
|
||||
#endif
|
||||
if (rlyPin>=0) {
|
||||
pinMode(rlyPin, OUTPUT);
|
||||
|
@ -272,9 +272,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
#define E131_MAX_UNIVERSE_COUNT 20
|
||||
#define E131_MAX_UNIVERSE_COUNT 20
|
||||
#else
|
||||
#define E131_MAX_UNIVERSE_COUNT 10
|
||||
#ifdef ESP8266
|
||||
#define E131_MAX_UNIVERSE_COUNT 9
|
||||
#else
|
||||
#define E131_MAX_UNIVERSE_COUNT 12
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit
|
||||
|
@ -97,6 +97,12 @@ void onHueConnect(void* arg, AsyncClient* client);
|
||||
void sendHuePoll();
|
||||
void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
|
||||
|
||||
//improv.cpp
|
||||
void handleImprovPacket();
|
||||
void sendImprovStateResponse(uint8_t state, bool error = false);
|
||||
void sendImprovInfoResponse();
|
||||
void sendImprovRPCResponse(uint8_t commandId);
|
||||
|
||||
//ir.cpp
|
||||
//bool decodeIRCustom(uint32_t code);
|
||||
void applyRepeatActions();
|
||||
|
244
wled00/improv.cpp
Normal file
244
wled00/improv.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
#include "wled.h"
|
||||
|
||||
#ifdef WLED_DEBUG_IMPROV
|
||||
#define DIMPROV_PRINT(x) Serial.print(x)
|
||||
#define DIMPROV_PRINTLN(x) Serial.println(x)
|
||||
#define DIMPROV_PRINTF(x...) Serial.printf(x)
|
||||
#else
|
||||
#define DIMPROV_PRINT(x)
|
||||
#define DIMPROV_PRINTLN(x)
|
||||
#define DIMPROV_PRINTF(x...)
|
||||
#endif
|
||||
|
||||
#define IMPROV_VERSION 1
|
||||
|
||||
void parseWiFiCommand(char *rpcData);
|
||||
|
||||
enum ImprovPacketType {
|
||||
Current_State = 0x01,
|
||||
Error_State = 0x02,
|
||||
RPC_Command = 0x03,
|
||||
RPC_Response = 0x04
|
||||
};
|
||||
|
||||
enum ImprovPacketByte {
|
||||
Version = 6,
|
||||
PacketType = 7,
|
||||
Length = 8,
|
||||
RPC_CommandType = 9
|
||||
};
|
||||
|
||||
enum ImprovRPCType {
|
||||
Command_Wifi = 0x01,
|
||||
Request_State = 0x02,
|
||||
Request_Info = 0x03
|
||||
};
|
||||
|
||||
//File dbgf;
|
||||
|
||||
//blocking function to parse an Improv Serial packet
|
||||
void handleImprovPacket() {
|
||||
uint8_t header[6] = {'I','M','P','R','O','V'};
|
||||
|
||||
//dbgf = WLED_FS.open("/improv.log","a");
|
||||
|
||||
bool timeout = false;
|
||||
uint8_t waitTime = 25;
|
||||
uint16_t packetByte = 0;
|
||||
uint8_t packetLen = 9;
|
||||
uint8_t checksum = 0;
|
||||
|
||||
uint8_t rpcCommandType = 0;
|
||||
char rpcData[128];
|
||||
rpcData[0] = 0;
|
||||
|
||||
while (!timeout) {
|
||||
if (Serial.available() < 1) {
|
||||
delay(1);
|
||||
waitTime--;
|
||||
if (!waitTime) timeout = true;
|
||||
continue;
|
||||
}
|
||||
byte next = Serial.read();
|
||||
|
||||
DIMPROV_PRINT("Received improv byte: "); DIMPROV_PRINTF("%x\r\n",next);
|
||||
//f.write(next);
|
||||
switch (packetByte) {
|
||||
case ImprovPacketByte::Version: {
|
||||
if (next != IMPROV_VERSION) {
|
||||
DIMPROV_PRINTLN(F("Invalid version"));
|
||||
//dbgf.close();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImprovPacketByte::PacketType: {
|
||||
if (next != ImprovPacketType::RPC_Command) {
|
||||
DIMPROV_PRINTF("Non RPC-command improv packet type %i\n",next);
|
||||
//dbgf.close();
|
||||
return;
|
||||
}
|
||||
if (!improvActive) improvActive = 1;
|
||||
break;
|
||||
}
|
||||
case ImprovPacketByte::Length: packetLen = 9 + next; break;
|
||||
case ImprovPacketByte::RPC_CommandType: rpcCommandType = next; break;
|
||||
default: {
|
||||
if (packetByte >= packetLen) { //end of packet, check checksum match
|
||||
|
||||
if (checksum != next) {
|
||||
DIMPROV_PRINTF("Got RPC checksum %i, expected %i",next,checksum);
|
||||
sendImprovStateResponse(0x01, true);
|
||||
//dbgf.close();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rpcCommandType) {
|
||||
case ImprovRPCType::Command_Wifi: parseWiFiCommand(rpcData); break;
|
||||
case ImprovRPCType::Request_State: {
|
||||
uint8_t improvState = 0x02; //authorized
|
||||
if (WLED_WIFI_CONFIGURED) improvState = 0x03; //provisioning
|
||||
if (Network.isConnected()) improvState = 0x04; //provisioned
|
||||
sendImprovStateResponse(improvState, false);
|
||||
if (improvState == 0x04) sendImprovRPCResponse(ImprovRPCType::Request_State);
|
||||
break;
|
||||
}
|
||||
case ImprovRPCType::Request_Info: sendImprovInfoResponse(); break;
|
||||
default: {
|
||||
DIMPROV_PRINTF("Unknown RPC command %i\n",next);
|
||||
sendImprovStateResponse(0x02, true);
|
||||
}
|
||||
}
|
||||
//dbgf.close();
|
||||
return;
|
||||
}
|
||||
if (packetByte < 6) { //check header
|
||||
if (next != header[packetByte]) {
|
||||
DIMPROV_PRINTLN(F("Invalid improv header"));
|
||||
//dbgf.close();
|
||||
return;
|
||||
}
|
||||
} else if (packetByte > 9) { //RPC data
|
||||
rpcData[packetByte - 10] = next;
|
||||
if (packetByte > 137) return; //prevent buffer overflow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checksum += next;
|
||||
packetByte++;
|
||||
}
|
||||
//dbgf.close();
|
||||
}
|
||||
|
||||
void sendImprovStateResponse(uint8_t state, bool error) {
|
||||
if (!error && improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true);
|
||||
if (error) improvError = state;
|
||||
char out[11] = {'I','M','P','R','O','V'};
|
||||
out[6] = IMPROV_VERSION;
|
||||
out[7] = error? ImprovPacketType::Error_State : ImprovPacketType::Current_State;
|
||||
out[8] = 1;
|
||||
out[9] = state;
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (uint8_t i = 0; i < 10; i++) checksum += out[i];
|
||||
out[10] = checksum;
|
||||
Serial.write((uint8_t*)out, 11);
|
||||
Serial.write('\n');
|
||||
}
|
||||
|
||||
void sendImprovRPCResponse(byte commandId) {
|
||||
if (improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true);
|
||||
uint8_t packetLen = 12;
|
||||
char out[64] = {'I','M','P','R','O','V'};
|
||||
out[6] = IMPROV_VERSION;
|
||||
out[7] = ImprovPacketType::RPC_Response;
|
||||
out[8] = 2; //Length (set below)
|
||||
out[9] = commandId;
|
||||
out[10] = 0; //Data len (set below)
|
||||
out[11] = '\0'; //URL len (set below)
|
||||
|
||||
if (Network.isConnected())
|
||||
{
|
||||
IPAddress localIP = Network.localIP();
|
||||
uint8_t len = sprintf(out+12, "http://%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
if (len > 24) return; //sprintf fail?
|
||||
out[11] = len;
|
||||
out[10] = 1 + len;
|
||||
out[8] = 3 + len; //RPC command type + data len + url len + url
|
||||
packetLen = 13 + len;
|
||||
}
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (uint8_t i = 0; i < packetLen -1; i++) checksum += out[i];
|
||||
out[packetLen -1] = checksum;
|
||||
Serial.write((uint8_t*)out, packetLen);
|
||||
Serial.write('\n');
|
||||
improvActive = 1; //no longer provisioning
|
||||
}
|
||||
|
||||
void sendImprovInfoResponse() {
|
||||
if (improvError > 0 && improvError < 3) sendImprovStateResponse(0x00, true);
|
||||
uint8_t packetLen = 12;
|
||||
char out[128] = {'I','M','P','R','O','V'};
|
||||
out[6] = IMPROV_VERSION;
|
||||
out[7] = ImprovPacketType::RPC_Response;
|
||||
//out[8] = 2; //Length (set below)
|
||||
out[9] = ImprovRPCType::Request_Info;
|
||||
//out[10] = 0; //Data len (set below)
|
||||
out[11] = 4; //Firmware len ("WLED")
|
||||
out[12] = 'W'; out[13] = 'L'; out[14] = 'E'; out[15] = 'D';
|
||||
uint8_t lengthSum = 17;
|
||||
uint8_t vlen = sprintf_P(out+lengthSum,PSTR("0.13.0-b5/%i"),VERSION);
|
||||
out[16] = vlen; lengthSum += vlen;
|
||||
uint8_t hlen = 7;
|
||||
#ifdef ESP8266
|
||||
strcpy(out+lengthSum+1,"esp8266");
|
||||
#else
|
||||
hlen = 5;
|
||||
strcpy(out+lengthSum+1,"esp32");
|
||||
#endif
|
||||
out[lengthSum] = hlen;
|
||||
lengthSum += hlen + 1;
|
||||
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
|
||||
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
|
||||
strcpy(out+lengthSum+1,useMdnsName ? cmDNS : serverDescription);
|
||||
uint8_t nlen = strlen(useMdnsName ? cmDNS : serverDescription);
|
||||
out[lengthSum] = nlen;
|
||||
lengthSum += nlen + 1;
|
||||
|
||||
packetLen = lengthSum +1;
|
||||
out[8] = lengthSum -9;
|
||||
out[10] = lengthSum -11;
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (uint8_t i = 0; i < packetLen -1; i++) checksum += out[i];
|
||||
out[packetLen -1] = checksum;
|
||||
Serial.write((uint8_t*)out, packetLen);
|
||||
Serial.write('\n');
|
||||
DIMPROV_PRINT("Info checksum");
|
||||
DIMPROV_PRINTLN(checksum);
|
||||
}
|
||||
|
||||
void parseWiFiCommand(char* rpcData) {
|
||||
uint8_t len = rpcData[0];
|
||||
if (!len || len > 126) return;
|
||||
|
||||
uint8_t ssidLen = rpcData[1];
|
||||
if (ssidLen > len -1 || ssidLen > 32) return;
|
||||
memset(clientSSID, 0, 32);
|
||||
memcpy(clientSSID, rpcData+2, ssidLen);
|
||||
|
||||
memset(clientPass, 0, 64);
|
||||
if (len > ssidLen +1) {
|
||||
uint8_t passLen = rpcData[2+ssidLen];
|
||||
memset(clientPass, 0, 64);
|
||||
memcpy(clientPass, rpcData+3+ssidLen, passLen);
|
||||
}
|
||||
|
||||
sendImprovStateResponse(0x03); //provisioning
|
||||
improvActive = 2;
|
||||
|
||||
forceReconnect = true;
|
||||
serializeConfig();
|
||||
}
|
@ -528,7 +528,7 @@ void serializeInfo(JsonObject root)
|
||||
leds[F("fps")] = strip.getFps();
|
||||
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
||||
leds[F("maxseg")] = strip.getMaxSegments();
|
||||
leds[F("seglock")] = false; //will be used in the future to prevent modifications to segment config
|
||||
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
||||
|
||||
root[F("str")] = syncToggleReceive;
|
||||
|
||||
@ -590,7 +590,7 @@ void serializeInfo(JsonObject root)
|
||||
root[F("resetReason0")] = (int)rtc_get_reset_reason(0);
|
||||
root[F("resetReason1")] = (int)rtc_get_reset_reason(1);
|
||||
#endif
|
||||
root[F("lwip")] = 0;
|
||||
root[F("lwip")] = 0; //deprecated
|
||||
#else
|
||||
root[F("arch")] = "esp8266";
|
||||
root[F("core")] = ESP.getCoreVersion();
|
||||
|
@ -137,6 +137,11 @@ bool PinManagerClass::isPinOk(byte gpio, bool output)
|
||||
return false;
|
||||
}
|
||||
|
||||
PinOwner PinManagerClass::getPinOwner(byte gpio) {
|
||||
if (!isPinOk(gpio, false)) return PinOwner::None;
|
||||
return ownerTag[gpio];
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
byte PinManagerClass::allocateLedc(byte channels)
|
||||
{
|
||||
|
@ -93,6 +93,8 @@ class PinManagerClass {
|
||||
// will return false for reserved pins
|
||||
bool isPinOk(byte gpio, bool output = true);
|
||||
|
||||
PinOwner getPinOwner(byte gpio);
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
byte allocateLedc(byte channels);
|
||||
void deallocateLedc(byte pos, byte channels);
|
||||
|
@ -312,6 +312,8 @@ void WLED::setup()
|
||||
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
|
||||
if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket();
|
||||
|
||||
strip.service();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
@ -329,6 +331,8 @@ void WLED::setup()
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
initDMX();
|
||||
#endif
|
||||
|
||||
if (Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket();
|
||||
// HTTP server page init
|
||||
initServer();
|
||||
|
||||
@ -659,14 +663,26 @@ void WLED::handleConnection()
|
||||
interfacesInited = false;
|
||||
initConnection();
|
||||
}
|
||||
if (now - lastReconnectAttempt > ((stac) ? 300000 : 20000) && WLED_WIFI_CONFIGURED)
|
||||
//send improv failed 6 seconds after second init attempt (24 sec. after provisioning)
|
||||
if (improvActive > 2 && now - lastReconnectAttempt > 6000) {
|
||||
sendImprovStateResponse(0x03, true);
|
||||
improvActive = 2;
|
||||
}
|
||||
if (now - lastReconnectAttempt > ((stac) ? 300000 : 18000) && WLED_WIFI_CONFIGURED) {
|
||||
if (improvActive == 2) improvActive = 3;
|
||||
initConnection();
|
||||
}
|
||||
if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN))
|
||||
initAP();
|
||||
} else if (!interfacesInited) { // newly connected
|
||||
} else if (!interfacesInited) { //newly connected
|
||||
DEBUG_PRINTLN("");
|
||||
DEBUG_PRINT(F("Connected! IP address: "));
|
||||
DEBUG_PRINTLN(Network.localIP());
|
||||
if (improvActive) {
|
||||
if (improvError == 3) sendImprovStateResponse(0x00, true);
|
||||
sendImprovStateResponse(0x04);
|
||||
if (improvActive > 1) sendImprovRPCResponse(0x01);
|
||||
}
|
||||
initInterfaces();
|
||||
userConnected();
|
||||
usermods.connected();
|
||||
|
@ -512,6 +512,10 @@ WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 25
|
||||
// blynk
|
||||
WLED_GLOBAL bool blynkEnabled _INIT(false);
|
||||
|
||||
//improv
|
||||
WLED_GLOBAL byte improvActive _INIT(0); //0: no improv packet received, 1: improv active, 2: provisioning
|
||||
WLED_GLOBAL byte improvError _INIT(0);
|
||||
|
||||
//playlists
|
||||
WLED_GLOBAL int16_t currentPlaylist _INIT(-1);
|
||||
//still used for "PL=~" HTTP API command
|
||||
|
@ -16,7 +16,7 @@ enum class AdaState {
|
||||
Data_Blue,
|
||||
TPM2_Header_Type,
|
||||
TPM2_Header_CountHi,
|
||||
TPM2_Header_CountLo
|
||||
TPM2_Header_CountLo,
|
||||
};
|
||||
|
||||
void handleSerial()
|
||||
@ -41,7 +41,12 @@ void handleSerial()
|
||||
else if (next == 0xC9) { //TPM2 start byte
|
||||
state = AdaState::TPM2_Header_Type;
|
||||
}
|
||||
else if (next == '{') { //JSON API
|
||||
else if (next == 'I') {
|
||||
handleImprovPacket();
|
||||
return;
|
||||
} else if (next == 'v') {
|
||||
Serial.print("WLED"); Serial.write(' '); Serial.println(VERSION);
|
||||
} else if (next == '{') { //JSON API
|
||||
bool verboseResponse = false;
|
||||
DEBUG_PRINTLN(F("Serial JSON buffer requested."));
|
||||
#ifdef WLED_USE_DYNAMIC_JSON
|
||||
@ -68,6 +73,7 @@ void handleSerial()
|
||||
serializeInfo(info);
|
||||
|
||||
serializeJson(doc, Serial);
|
||||
Serial.println();
|
||||
}
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user