This commit is contained in:
Gobol 2026-05-21 19:00:27 +02:00 committed by GitHub
commit d96e3e55d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 515 additions and 297 deletions

View file

@ -124,6 +124,8 @@ jobs:
arduino-cli lib install PubSubClient@${{ env.PUB_SUB_CLIENT_VERSION }} arduino-cli lib install PubSubClient@${{ env.PUB_SUB_CLIENT_VERSION }}
arduino-cli lib install SmartRC-CC1101-Driver-Lib@${{ env.SMARTRC_CC1101_VERSION }} arduino-cli lib install SmartRC-CC1101-Driver-Lib@${{ env.SMARTRC_CC1101_VERSION }}
arduino-cli lib install WebSockets@${{ env.WEB_SOCKET_VERSION }} arduino-cli lib install WebSockets@${{ env.WEB_SOCKET_VERSION }}
arduino-cli lib install "ESP Async WebServer"
arduino-cli lib install AsyncTCP
- name: Build ${{ matrix.name }} - name: Build ${{ matrix.name }}
run: | run: |

View file

@ -159,6 +159,8 @@ jobs:
arduino-cli lib install PubSubClient@${{ env.PUB_SUB_CLIENT_VERSION }} arduino-cli lib install PubSubClient@${{ env.PUB_SUB_CLIENT_VERSION }}
arduino-cli lib install SmartRC-CC1101-Driver-Lib@${{ env.SMARTRC_CC1101_VERSION }} arduino-cli lib install SmartRC-CC1101-Driver-Lib@${{ env.SMARTRC_CC1101_VERSION }}
arduino-cli lib install WebSockets@${{ env.WEB_SOCKET_VERSION }} arduino-cli lib install WebSockets@${{ env.WEB_SOCKET_VERSION }}
arduino-cli lib install "ESP Async WebServer"
arduino-cli lib install AsyncTCP
- name: Build ${{ matrix.name }} - name: Build ${{ matrix.name }}
run: | run: |

View file

@ -4,6 +4,7 @@
#include <esp_task_wdt.h> #include <esp_task_wdt.h>
#include "ConfigSettings.h" #include "ConfigSettings.h"
#include "Network.h" #include "Network.h"
#include "Somfy.h"
#include "Web.h" #include "Web.h"
#include "Sockets.h" #include "Sockets.h"
#include "Utils.h" #include "Utils.h"

View file

@ -1,7 +1,6 @@
#include <Preferences.h> #include <Preferences.h>
#include <ELECHOUSE_CC1101_SRC_DRV.h> #include <ELECHOUSE_CC1101_SRC_DRV.h>
#include <SPI.h> #include <SPI.h>
#include <WebServer.h>
#include <esp_task_wdt.h> #include <esp_task_wdt.h>
#include "Utils.h" #include "Utils.h"
#include "ConfigSettings.h" #include "ConfigSettings.h"

View file

@ -1,4 +1,5 @@
#include "WResp.h" #include "WResp.h"
#include "Web.h"
void JsonSockEvent::beginEvent(WebSocketsServer *server, const char *evt, char *buff, size_t buffSize) { void JsonSockEvent::beginEvent(WebSocketsServer *server, const char *evt, char *buff, size_t buffSize) {
this->server = server; this->server = server;
this->buff = buff; this->buff = buff;
@ -33,22 +34,22 @@ void JsonSockEvent::_safecat(const char *val, bool escape) {
else strcat(this->buff, val); else strcat(this->buff, val);
if(escape) strcat(this->buff, "\""); if(escape) strcat(this->buff, "\"");
} }
void JsonResponse::beginResponse(WebServer *server, char *buff, size_t buffSize) { void JsonResponse::beginResponse(WebRequestCompat *server, char *buff, size_t buffSize) {
this->server = server; this->server = server;
this->buff = buff; this->buff = buff;
this->buffSize = buffSize; this->buffSize = buffSize;
this->buff[0] = 0x00; this->buff[0] = 0x00;
this->_nocomma = true; this->_nocomma = true;
server->setContentLength(CONTENT_LENGTH_UNKNOWN); this->_headersSent = false;
this->response = server->beginResponseStream("application/json");
} }
void JsonResponse::endResponse() { void JsonResponse::endResponse() {
if(strlen(buff)) this->send(); if(strlen(buff)) this->send();
server->sendContent("", 0); server->send(this->response);
this->response = nullptr;
} }
void JsonResponse::send() { void JsonResponse::send() {
if(!this->_headersSent) server->send_P(200, "application/json", this->buff); if(this->response != nullptr) this->response->print(this->buff);
else server->sendContent(this->buff);
//Serial.printf("Sent %d bytes %d\n", strlen(this->buff), this->buffSize);
this->buff[0] = 0x00; this->buff[0] = 0x00;
this->_headersSent = true; this->_headersSent = true;
} }

10
WResp.h
View file

@ -1,9 +1,10 @@
#include <WebServer.h> #include <ESPAsyncWebServer.h>
#include <WebSocketsServer.h> #include <WebSocketsServer.h>
#include "Somfy.h"
#ifndef wresp_h #ifndef wresp_h
#define wresp_h #define wresp_h
class WebRequestCompat;
class JsonFormatter { class JsonFormatter {
protected: protected:
char *buff; char *buff;
@ -56,8 +57,9 @@ class JsonResponse : public JsonFormatter {
protected: protected:
void _safecat(const char *val, bool escape = false) override; void _safecat(const char *val, bool escape = false) override;
public: public:
WebServer *server; WebRequestCompat *server;
void beginResponse(WebServer *server, char *buff, size_t buffSize); AsyncResponseStream *response = nullptr;
void beginResponse(WebRequestCompat *server, char *buff, size_t buffSize);
void endResponse(); void endResponse();
void send(); void send();
}; };

634
Web.cpp

File diff suppressed because it is too large Load diff

121
Web.h
View file

@ -1,37 +1,87 @@
#include <WebServer.h> #include <ArduinoJson.h>
#include "Somfy.h" #include <ESPAsyncWebServer.h>
#include <vector>
#ifndef webserver_h #ifndef webserver_h
#define webserver_h #define webserver_h
using HTTPMethod = uint8_t;
struct AsyncRequestContext {
String body;
bool bodyEnabled = true;
std::vector<std::pair<String, String>> headers;
};
class WebClientCompat {
public:
explicit WebClientCompat(AsyncWebServerRequest *request = nullptr) : request(request) {}
IPAddress remoteIP() const;
void bind(AsyncWebServerRequest *request);
private:
AsyncWebServerRequest *request;
};
class WebRequestCompat {
public:
explicit WebRequestCompat(AsyncWebServerRequest *request);
HTTPMethod method() const;
bool hasArg(const char *name) const;
String arg(const char *name) const;
bool hasHeader(const char *name) const;
String header(const char *name) const;
void sendHeader(const char *name, const char *value);
void sendHeader(const char *name, const String &value);
void sendHeader(const String &name, const String &value);
void sendHeader(const __FlashStringHelper *name, const __FlashStringHelper *value);
void sendHeader(const __FlashStringHelper *name, const char *value);
void send(int code);
void send(int code, const char *body);
void send(int code, const char *contentType, const char *content);
void send(int code, const char *contentType, const String &content);
void send(AsyncWebServerResponse *response);
AsyncResponseStream *beginResponseStream(const char *contentType);
String uri() const;
WebClientCompat &client();
AsyncWebServerRequest *raw() const;
private:
AsyncRequestContext *ctx() const;
void addPendingHeaders(AsyncWebServerResponse *response);
void clearContext();
AsyncWebServerRequest *request;
mutable WebClientCompat requestClient;
};
class Web { class Web {
public: public:
bool uploadSuccess = false; bool uploadSuccess = false;
void sendCORSHeaders(WebServer &server); void sendCORSHeaders(WebRequestCompat &server);
void sendCacheHeaders(uint32_t seconds=604800); void sendCacheHeaders(WebRequestCompat &server, uint32_t seconds=604800);
void startup(); void startup();
void handleLogin(WebServer &server); void handleLogin(WebRequestCompat &server);
void handleLogout(WebServer &server); void handleLogout(WebRequestCompat &server);
void handleStreamFile(WebServer &server, const char *filename, const char *encoding); void handleStreamFile(WebRequestCompat &server, const char *filename, const char *encoding);
void handleController(WebServer &server); void handleController(WebRequestCompat &server);
void handleLoginContext(WebServer &server); void handleLoginContext(WebRequestCompat &server);
void handleGetRepeaters(WebServer &server); void handleGetRepeaters(WebRequestCompat &server);
void handleGetRooms(WebServer &server); void handleGetRooms(WebRequestCompat &server);
void handleGetShades(WebServer &server); void handleGetShades(WebRequestCompat &server);
void handleGetGroups(WebServer &server); void handleGetGroups(WebRequestCompat &server);
void handleShadeCommand(WebServer &server); void handleShadeCommand(WebRequestCompat &server);
void handleRepeatCommand(WebServer &server); void handleRepeatCommand(WebRequestCompat &server);
void handleGroupCommand(WebServer &server); void handleGroupCommand(WebRequestCompat &server);
void handleTiltCommand(WebServer &server); void handleTiltCommand(WebRequestCompat &server);
void handleDiscovery(WebServer &server); void handleDiscovery(WebRequestCompat &server);
void handleNotFound(WebServer &server); void handleNotFound(WebRequestCompat &server);
void handleRoom(WebServer &server); void handleRoom(WebRequestCompat &server);
void handleShade(WebServer &server); void handleShade(WebRequestCompat &server);
void handleGroup(WebServer &server); void handleGroup(WebRequestCompat &server);
void handleSetPositions(WebServer &server); void handleSetPositions(WebRequestCompat &server);
void handleSetSensor(WebServer &server); void handleSetSensor(WebRequestCompat &server);
void handleDownloadFirmware(WebServer &server); void handleDownloadFirmware(WebRequestCompat &server);
void handleBackup(WebServer &server, bool attach = false); void handleBackup(WebRequestCompat &server, bool attach = false);
void handleReboot(WebServer &server); void handleReboot(WebRequestCompat &server);
void handleDeserializationError(WebServer &server, DeserializationError &err); void handleDeserializationError(WebRequestCompat &server, DeserializationError &err);
void begin(); void begin();
void loop(); void loop();
void end(); void end();
@ -40,11 +90,16 @@ class Web {
bool createAPIToken(const char *payload, char *token); bool createAPIToken(const char *payload, char *token);
bool createAPIPinToken(const IPAddress ipAddress, const char *pin, char *token); bool createAPIPinToken(const IPAddress ipAddress, const char *pin, char *token);
bool createAPIPasswordToken(const IPAddress ipAddress, const char *username, const char *password, char *token); bool createAPIPasswordToken(const IPAddress ipAddress, const char *username, const char *password, char *token);
bool isAuthenticated(WebServer &server, bool cfg = false); bool isAuthenticated(WebRequestCompat &server, bool cfg = false);
//void chunkRoomsResponse(WebServer &server, const char *elem = nullptr); static AsyncRequestContext *ensureRequestContext(AsyncWebServerRequest *request);
//void chunkShadesResponse(WebServer &server, const char *elem = nullptr); static AsyncRequestContext *findRequestContext(AsyncWebServerRequest *request);
//void chunkGroupsResponse(WebServer &server, const char *elem = nullptr); static void releaseRequestContext(AsyncWebServerRequest *request);
//void chunkGroupResponse(WebServer &server, SomfyGroup *, const char *prefix = nullptr); static void collectBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total);
//void chunkRoomsResponse(WebRequestCompat &server, const char *elem = nullptr);
//void chunkShadesResponse(WebRequestCompat &server, const char *elem = nullptr);
//void chunkGroupsResponse(WebRequestCompat &server, const char *elem = nullptr);
//void chunkGroupResponse(WebRequestCompat &server, SomfyGroup *, const char *prefix = nullptr);
}; };
#endif #endif

View file

@ -8,9 +8,9 @@
<meta name="apple-mobile-web-app-title" content="ESPSomfy RTS App"> <meta name="apple-mobile-web-app-title" content="ESPSomfy RTS App">
<meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="main.css?v=2.4.7c" type="text/css" /> <link rel="stylesheet" href="main.css?v=2.4.7e" type="text/css" />
<link rel="stylesheet" href="widgets.css?v=2.4.7c" type="text/css" /> <link rel="stylesheet" href="widgets.css?v=2.4.7e" type="text/css" />
<link rel="stylesheet" href="icons.css?v=2.4.7c" type="text/css" /> <link rel="stylesheet" href="icons.css?v=2.4.7e" type="text/css" />
<link rel="icon" type="image/png" href="favicon.png" /> <link rel="icon" type="image/png" href="favicon.png" />
<!-- iPad retina icon --> <!-- iPad retina icon -->
@ -114,7 +114,7 @@
rel="apple-touch-startup-image"> rel="apple-touch-startup-image">
<script type="text/javascript" src="index.js?v=2.4.7c"></script> <script type="text/javascript" src="index.js?v=2.4.7e"></script>
</head> </head>
<body> <body>
<div id="divContainer" class="container main" data-auth="false"> <div id="divContainer" class="container main" data-auth="false">

View file

@ -719,6 +719,7 @@ class UIBinder {
return val; return val;
} }
toElement(el, val) { toElement(el, val) {
if (!el) return;
let flds = el.querySelectorAll('*[data-bind]'); let flds = el.querySelectorAll('*[data-bind]');
flds.forEach((fld) => { flds.forEach((fld) => {
let prop = fld.getAttribute('data-bind'); let prop = fld.getAttribute('data-bind');
@ -1673,8 +1674,10 @@ class Wifi {
ui.serviceError(err); ui.serviceError(err);
} }
else { else {
document.getElementById('cbHardwired').checked = settings.connType >= 2; let cbHardwired = document.getElementById('cbHardwired');
document.getElementById('cbFallbackWireless').checked = settings.connType === 3; let cbFallbackWireless = document.getElementById('cbFallbackWireless');
if (cbHardwired) cbHardwired.checked = settings.connType >= 2;
if (cbFallbackWireless) cbFallbackWireless.checked = settings.connType === 3;
ui.toElement(pnl, settings); ui.toElement(pnl, settings);
/* /*
if (settings.connType >= 2) { if (settings.connType >= 2) {
@ -1691,9 +1694,12 @@ class Wifi {
} }
*/ */
ui.toElement(document.getElementById('divDHCP'), settings); ui.toElement(document.getElementById('divDHCP'), settings);
document.getElementById('divETHSettings').style.display = settings.ethernet.boardType === 0 ? '' : 'none'; let divETHSettings = document.getElementById('divETHSettings');
document.getElementById('divStaticIP').style.display = settings.ip.dhcp ? 'none' : ''; let divStaticIP = document.getElementById('divStaticIP');
document.getElementById('spanCurrentIP').innerHTML = settings.ip.ip; let spanCurrentIP = document.getElementById('spanCurrentIP');
if (divETHSettings) divETHSettings.style.display = settings.ethernet.boardType === 0 ? '' : 'none';
if (divStaticIP) divStaticIP.style.display = settings.ip.dhcp ? 'none' : '';
if (spanCurrentIP) spanCurrentIP.innerHTML = settings.ip.ip;
this.useEthernetClicked(); this.useEthernetClicked();
this.hiddenSSIDClicked(); this.hiddenSSIDClicked();
} }
@ -4230,7 +4236,8 @@ class MQTT {
else { else {
console.log(settings); console.log(settings);
ui.toElement(document.getElementById('divMQTT'), { mqtt: settings }); ui.toElement(document.getElementById('divMQTT'), { mqtt: settings });
document.getElementById('divDiscoveryTopic').style.display = settings.pubDisco ? '' : 'none'; let divDiscoveryTopic = document.getElementById('divDiscoveryTopic');
if (divDiscoveryTopic) divDiscoveryTopic.style.display = settings.pubDisco ? '' : 'none';
} }
}); });
} }
@ -4800,4 +4807,3 @@ class Firmware {
} }
} }
var firmware = new Firmware(); var firmware = new Firmware();