SerialImprov to Improv-WiFi-Library

This commit is contained in:
DTTerastar 2023-04-10 12:06:30 -04:00
parent 24c7fbb2fe
commit a50581506e
5 changed files with 23 additions and 302 deletions

View File

@ -59,6 +59,7 @@ lib_deps =
https://github.com/ESPresense/AsyncWiFiSettings.git@^1.0.8
https://github.com/ESPresense/SoftFilters.git
https://github.com/ESPresense/NimBLE-Arduino.git
https://github.com/jnthas/Improv-WiFi-Library.git
marvinroger/AsyncMqttClient@^0.9.0
bblanchon/ArduinoJson@^6.21.3
kitesurfer1404/WS2812FX@^1.4.2
@ -271,6 +272,18 @@ build_flags =
-D SENSORS
${esp32.build_flags}
[env:m5atoms3]
extends = esp32s3
platform = espressif32@6.1.0
board = m5stack-atoms3
lib_deps =
${esp32.lib_deps}
${sensors.lib_deps}
build_flags =p
-D FIRMWARE='"m5atoms3"'
-D SENSORS
${esp32s3.build_flags}
[env:macchina-a0]
extends = esp32
lib_deps =

View File

@ -1,290 +0,0 @@
#include <AsyncMqttClient.h>
#include <AsyncWiFiSettings.h>
#include "Network.h"
#include "SPIFFS.h"
#include "defaults.h"
#include "globals.h"
#include "mqtt.h"
#include "string_utils.h"
namespace SerialImprov {
#ifdef DEBUG_IMPROV
#define DIMPROV_PRINT(x) Serial2.print(x)
#define DIMPROV_PRINTLN(x) Serial2.println(x)
#define DIMPROV_PRINTF(x...) Serial2.printf(x)
#else
#define DIMPROV_PRINT(x)
#define DIMPROV_PRINTLN(x)
#define DIMPROV_PRINTF(x...)
#endif
#define IMPROV_VERSION 1
byte improvActive = 0;
byte improvError = 0;
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
};
void sendImprovStateResponse(uint8_t state, bool error = false);
void sendImprovRPCResponse(byte commandId);
void sendImprovInfoResponse();
// blocking function to parse an Improv Serial packet
void handleImprovPacket(bool provisioning) {
uint8_t header[6] = {'I', 'M', 'P', 'R', 'O', 'V'};
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);
switch (packetByte) {
case ImprovPacketByte::Version: {
if (next != IMPROV_VERSION) {
DIMPROV_PRINTLN(F("Invalid version"));
return;
}
break;
}
case ImprovPacketByte::PacketType: {
if (next != ImprovPacketType::RPC_Command) {
DIMPROV_PRINTF("Non RPC-command improv packet type %i\n", next);
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);
return;
}
switch (rpcCommandType) {
case ImprovRPCType::Command_Wifi:
parseWiFiCommand(rpcData);
break;
case ImprovRPCType::Request_State: {
uint8_t improvState = 0x02; // authorized
if (provisioning) 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);
}
}
return;
}
if (packetByte < 6) { // check header
if (next != header[packetByte]) {
DIMPROV_PRINTLN(F("Invalid improv header"));
return;
}
} else if (packetByte > 9) { // RPC data
rpcData[packetByte - 10] = next;
if (packetByte > 137) return; // prevent buffer overflow
}
}
}
checksum += next;
packetByte++;
}
}
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] = 10; // Firmware len ("WLED")
out[12] = 'E';
out[13] = 'S';
out[14] = 'P';
out[15] = 'r';
out[16] = 'e';
out[17] = 's';
out[18] = 'e';
out[19] = 'n';
out[20] = 's';
out[21] = 'e';
uint8_t lengthSum = 23;
#ifdef VERSION
uint8_t vlen = sprintf_P(out + lengthSum, VERSION);
#else
uint8_t vlen = sprintf_P(out + lengthSum, "Dev");
#endif
out[22] = vlen;
lengthSum += vlen;
uint8_t hlen = 7;
hlen = 5;
strcpy(out + lengthSum + 1, "esp32");
out[lengthSum] = hlen;
lengthSum += hlen + 1;
strcpy(out + lengthSum + 1, room.c_str());
uint8_t nlen = room.length();
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* data) {
uint8_t len = data[0];
if (!len || len > 126) return;
uint8_t ssid_length = data[1];
uint8_t ssid_start = 2;
size_t ssid_end = ssid_start + ssid_length;
uint8_t pass_length = data[ssid_end];
size_t pass_start = ssid_end + 1;
size_t pass_end = pass_start + pass_length;
std::string ssid(data + ssid_start, data + ssid_end);
std::string password(data + pass_start, data + pass_end);
sendImprovStateResponse(0x03); // provisioning
improvActive = 2;
spurt("/wifi-ssid", ssid.c_str());
spurt("/wifi-password", password.c_str());
ESP.restart();
}
bool setup = false;
void Setup() {
#ifdef DEBUG_IMPROV
Serial2.begin(115200)
DIMPROV_PRINT("Setup");
#endif
}
void Loop(bool provisioning) {
if (!setup) {
setup = true;
Setup();
}
while (Serial.available() > 0) {
yield();
byte next = Serial.peek();
if (next == 'I') {
handleImprovPacket(provisioning);
return;
}
Serial.read();
}
}
} // namespace SerialImprov

View File

@ -1,8 +0,0 @@
#pragma once
namespace SerialImprov
{
void Setup();
void Loop(bool wifiConnected);
}

View File

@ -208,16 +208,21 @@ void setupNetwork() {
#endif
improvSerial.onImprovError(onImprovWiFiErrorCb);
improvSerial.onImprovConnected(onImprovWiFiConnectedCb);
improvSerial.setCustomConnectWiFi(connectWifi);
improvSerial.setDeviceInfo(ImprovTypes::ChipFamily::CF_ESP32, "My-Device-9a4c2b", "2.1.5", "My Device");
unsigned int connectProgress = 0;
AsyncWiFiSettings.onWaitLoop = [&connectProgress]() {
GUI::Wifi(connectProgress++);
SerialImprov::Loop(true);
improvSerial.handleSerial();
return 50;
};
unsigned int portalProgress = 0;
AsyncWiFiSettings.onPortalWaitLoop = [&portalProgress, portalTimeout]() {
GUI::Portal(portalProgress++);
SerialImprov::Loop(false);
improvSerial.handleSerial();
if (millis() > portalTimeout)
ESP.restart();
@ -589,7 +594,7 @@ void loop() {
Switch::Loop();
Button::Loop();
HttpWebServer::Loop();
SerialImprov::Loop(false);
improvSerial.handleSerial();
#if M5STICK
AXP192::Loop();
#endif

View File

@ -21,7 +21,7 @@
#include "Switch.h"
#include "Button.h"
#include "Network.h"
#include "SerialImprov.h"
#include <ImprovWiFiLibrary.h>
#include "Updater.h"
#include "defaults.h"
#include "globals.h"
@ -47,6 +47,7 @@
#include "DS18B20.h"
#endif
ImprovWiFi improvSerial(&Serial);
TimerHandle_t reconnectTimer;
TaskHandle_t scanTaskHandle;