Skip to content

Commit 05355cd

Browse files
committed
Merge branch 'dev' into main
2 parents 3353f1b + 7bd4c73 commit 05355cd

30 files changed

+1463
-1475
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11

2+
.vscode/arduino.json
23
node_modules/*
3-
package-lock.json
4+
package-lock.json
5+
6+
*.bin

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
"initializer_list": "cpp",
2424
"sstream": "cpp",
2525
"iosfwd": "cpp",
26-
"xlocbuf": "cpp"
26+
"xlocbuf": "cpp",
27+
"random": "cpp",
28+
"chrono": "cpp",
29+
"system_error": "cpp",
30+
"cstddef": "cpp"
2731
}
2832
}

FSexplorer.ino

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,36 @@ const char Helper[] = R"(
5858
)";
5959
const char Header[] = "HTTP/1.1 303 OK\r\nLocation:FSexplorer.html\r\nCache-Control: no-cache\r\n";
6060

61+
62+
6163
//=====================================================================================
62-
void setupFSexplorer() // Funktionsaufruf "LittleFS();" muss im Setup eingebunden werden
63-
{
64+
void startWebserver(){
65+
if (!LittleFS.exists("/index.html")) {
66+
httpServer.serveStatic("/", LittleFS, "/FSexplorer.html");
67+
httpServer.serveStatic("/index", LittleFS, "/FSexplorer.html");
68+
httpServer.serveStatic("/index.html", LittleFS, "/FSexplorer.html");
69+
} else{
70+
httpServer.serveStatic("/", LittleFS, "/index.html");
71+
httpServer.serveStatic("/index", LittleFS, "/index.html");
72+
httpServer.serveStatic("/index.html", LittleFS, "/index.html");
73+
}
74+
httpServer.serveStatic("/FSexplorer.png", LittleFS, "/FSexplorer.png");
75+
httpServer.serveStatic("/index.css", LittleFS, "/index.css");
76+
httpServer.serveStatic("/index.js", LittleFS, "/index.js");
77+
//otgw pic functions
78+
httpServer.on("/pic", upgradepic);
79+
// all other api calls are catched in FSexplorer onNotFounD!
80+
httpServer.on("/api", HTTP_ANY, processAPI); //was only HTTP_GET (20210110)
81+
82+
httpServer.begin();
83+
// Set up first message as the IP address
84+
OTGWSerial.println("\nHTTP Server started\r");
85+
sprintf(cMsg, "%03d.%03d.%d.%d", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);
86+
OTGWSerial.printf("\nAssigned IP=%s\r\n", cMsg);
87+
}
88+
//=====================================================================================
89+
void setupFSexplorer(){
6490
LittleFS.begin();
65-
6691
if (LittleFS.exists("/FSexplorer.html"))
6792
{
6893
httpServer.serveStatic("/FSexplorer.html", LittleFS, "/FSexplorer.html");
@@ -72,12 +97,12 @@ void setupFSexplorer() // Funktionsaufruf "LittleFS();" muss im Setup eingebu
7297
{
7398
httpServer.send(200, "text/html", Helper); //Upload the FSexplorer.html
7499
}
75-
httpServer.on("/api/listfiles", APIlistFiles);
100+
httpServer.on("/api/firmwarefilelist", apifirmwarefilelist);
101+
httpServer.on("/api/listfiles", apilistfiles);
76102
httpServer.on("/LittleFSformat", formatLittleFS);
77103
httpServer.on("/upload", HTTP_POST, []() {}, handleFileUpload);
78104
httpServer.on("/ReBoot", reBootESP);
79-
httpServer.on("/update", updateFirmware);
80-
httpServer.on("/upgradepic", upgradePIC);
105+
81106
httpServer.onNotFound([]()
82107
{
83108
if (Verbose) DebugTf("in 'onNotFound()'!! [%s] => \r\n", String(httpServer.uri()).c_str());
@@ -104,9 +129,48 @@ void setupFSexplorer() // Funktionsaufruf "LittleFS();" muss im Setup eingebu
104129

105130
} // setupFSexplorer()
106131

132+
//=====================================================================================
133+
void apifirmwarefilelist() {
134+
char *s, buffer[400];
135+
String version, fwversion;
136+
Dir dir;
137+
File f;
138+
139+
s = buffer;
140+
s += sprintf(buffer, "[");
141+
dir = LittleFS.openDir("/");
142+
while (dir.next()) {
143+
if (dir.fileName().endsWith(".hex")) {
144+
version="";fwversion="";
145+
String verfile = "/" + dir.fileName();
146+
verfile.replace(".hex", ".ver");
147+
f = LittleFS.open(verfile, "r");
148+
if (f) {
149+
version = f.readStringUntil('\n');
150+
version.trim();
151+
f.close();
152+
}
153+
fwversion = GetVersion("/"+dir.fileName()); // only check if gateway firmware
154+
DebugTf("GetVersion(%s) returned %s\n", dir.fileName().c_str(), fwversion.c_str());
155+
if (fwversion.length() && strcmp(fwversion.c_str(),version.c_str())) { // versions do not match
156+
version=fwversion; // assign hex file version to version
157+
if (f = LittleFS.open(verfile, "w")) { // write to .ver file
158+
DebugTf("writing %s to %s\n",version.c_str(),verfile.c_str());
159+
f.print(version + "\n");
160+
f.close();
161+
}
162+
}
163+
s += snprintf( s, sizeof(buffer), "{\"name\":\"%s\",\"version\":\"%s\",\"size\":%d},", CSTR(dir.fileName()), CSTR(version), dir.fileSize());
164+
}
165+
}
166+
s += sprintf(--s, "]\n");
167+
DebugTf("filelist response: [%s]\r\n", buffer);
168+
httpServer.send(200, "application/json", buffer);
169+
}
170+
107171

108172
//=====================================================================================
109-
void APIlistFiles() // Senden aller Daten an den Client
173+
void apilistfiles() // Senden aller Daten an den Client
110174
{
111175
FSInfo LittleFSinfo;
112176

@@ -118,7 +182,7 @@ void APIlistFiles() // Senden aller Daten an den Client
118182

119183
_fileMeta dirMap[MAX_FILES_IN_LIST+1];
120184
int fileNr = 0;
121-
185+
122186
Dir dir = LittleFS.openDir("/"); // List files on LittleFS
123187
while (dir.next() && (fileNr < MAX_FILES_IN_LIST))
124188
{
@@ -160,18 +224,17 @@ void APIlistFiles() // Senden aller Daten an den Client
160224
for (int f=0; f < fileNr; f++)
161225
{
162226
DebugTf("[%3d] >> [%s]\r\n", f, dirMap[f].Name);
163-
if (temp != "[") temp += ",";
164-
temp += R"({"name":")" + String(dirMap[f].Name) + R"(","size":")" + formatBytes(dirMap[f].Size) + R"("})";
227+
temp += R"({"name":")" + String(dirMap[f].Name) + R"(","size":")" + formatBytes(dirMap[f].Size) + R"("},)";
165228
}
166229

167230
LittleFS.info(LittleFSinfo);
168-
temp += R"(,{"usedBytes":")" + formatBytes(LittleFSinfo.usedBytes * 1.05) + R"(",)" + // Berechnet den verwendeten Speicherplatz + 5% Sicherheitsaufschlag
231+
temp += R"({"usedBytes":")" + formatBytes(LittleFSinfo.usedBytes * 1.05) + R"(",)" + // Berechnet den verwendeten Speicherplatz + 5% Sicherheitsaufschlag
169232
R"("totalBytes":")" + formatBytes(LittleFSinfo.totalBytes) + R"(","freeBytes":")" + // Zeigt die Größe des Speichers
170233
(LittleFSinfo.totalBytes - (LittleFSinfo.usedBytes * 1.05)) + R"("}])"; // Berechnet den freien Speicherplatz + 5% Sicherheitsaufschlag
171234

172235
httpServer.send(200, "application/json", temp);
173236

174-
} // APIlistFiles()
237+
} // apilistfiles()
175238

176239

177240
//=====================================================================================
@@ -269,28 +332,11 @@ bool freeSpace(uint16_t const& printsize)
269332

270333
} // freeSpace()
271334

272-
//=====================================================================================
273-
void upgradePIC()
274-
{
275-
DebugTln(F("Redirect to upgrade PIC .."));
276-
doRedirect("Upgrade OTGW PIC ", 120, "/FSexplorer", false);
277-
upgradenow();
278-
} // upgradePIC()
279-
280-
281-
//=====================================================================================
282-
void updateFirmware()
283-
{
284-
DebugTln(F("Redirect to updateIndex .."));
285-
doRedirect("wait ... ", 1, "/updateIndex", false);
286-
} // updateFirmware()
287-
288-
289335
//=====================================================================================
290336
void reBootESP()
291337
{
292338
DebugTln(F("Redirect and ReBoot .."));
293-
doRedirect("Reboot OTGW firmware ..", 60, "/", true);
339+
doRedirect("Reboot OTGW firmware ..", 120, "/", true);
294340
} // reBootESP()
295341

296342
//=====================================================================================

MQTTstuff.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
***************************************************************************
33
** Program : MQTTstuff
4-
** Version : v0.7.5
4+
** Version : v0.7.6
55
**
66
** Copyright (c) 2021 Robert van den Breemen
77
** Modified version from (c) 2020 Willem Aandewiel

OTGW-Core.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
***************************************************************************
33
** Program : Header file: OTGW-Core.h
4-
** Version : v0.7.5
4+
** Version : v0.7.6
55
**
66
** Copyright (c) 2021 Robert van den Breemen
77
** Borrowed from OpenTherm library from:
@@ -25,7 +25,7 @@ TelnetStreamClass OTGWstream(OTGW_SERIAL_PORT);
2525

2626
typedef struct {
2727
uint16_t Status = 0; // flag8 / flag8 Master and Slave Status flags.
28-
float Tset = 0.0; // f8.8 Control setpoint ie CH water temperature setpoint (°C)
28+
float TSet = 0.0; // f8.8 Control setpoint ie CH water temperature setpoint (°C)
2929
uint16_t MConfigMMemberIDcode = 0; // flag8 / u8 Master Configuration Flags / Master MemberID Code
3030
uint16_t SConfigSMemberIDcode = 0; // flag8 / u8 Slave Configuration Flags / Slave MemberID Code
3131
uint16_t Command = 0; // u8 / u8 Remote Command
@@ -401,6 +401,8 @@ enum OpenThermMessageID {
401401

402402
#define OT_MSGID_MAX 133
403403

404+
time_t msglastupdated[255] = {0}; //all msg, even if they are unknown
405+
404406
enum OpenThermStatus {
405407
OT_NOT_INITIALIZED,
406408
OT_READY,

OTGW-Core.ino

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
***************************************************************************
33
** Program : OTGW-Core.ino
4-
** Version : v0.7.5
4+
** Version : v0.7.6
55
**
66
** Copyright (c) 2021 Robert van den Breemen
77
** Borrowed from OpenTherm library from:
@@ -22,6 +22,12 @@
2222
#define PIN_I2C_SDA 4 //D2
2323
#define PIN_I2C_SCL 5 //D1
2424

25+
//used by update firmware functions
26+
const char *hexheaders[] = {
27+
"Last-Modified",
28+
"X-Version"
29+
};
30+
2531
//Macro to Feed the Watchdog
2632
#define FEEDWATCHDOGNOW Wire.beginTransmission(EXT_WD_I2C_ADDRESS); Wire.write(0xA5); Wire.endTransmission();
2733

@@ -215,6 +221,7 @@ String initWatchDog() {
215221
// Code here is based on ESPEasy code, modified to work in the project.
216222

217223
// configure hardware pins according to eeprom settings.
224+
DebugTln("Setup Watchdog");
218225
DebugTln(F("INIT : I2C"));
219226
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL); //configure the I2C bus
220227
//=============================================
@@ -835,13 +842,16 @@ void processOTGW(const char * buf, int len)
835842
Debugf("[%-30s]\t", messageIDToString(static_cast<OpenThermMessageID>(OTdata.id)));
836843
DebugFlush();
837844

845+
//keep track of update
846+
msglastupdated[OTdata.id] = now();
847+
838848
//next step interpret the OT protocol
839849
if (static_cast<OpenThermMessageType>(OTdata.type) == OT_READ_ACK || static_cast<OpenThermMessageType>(OTdata.type) == OT_WRITE_DATA) {
840850

841851
//#define OTprint(data, value, text, format) ({ data= value; Debugf("[%37s]", text); Debugf("= [format]", data)})
842852
//interpret values f8.8
843853
switch (static_cast<OpenThermMessageID>(OTdata.id)) {
844-
case TSet: OTdataObject.Tset = print_f88(); break;
854+
case TSet: OTdataObject.TSet = print_f88(); break;
845855
case CoolingControl: OTdataObject.CoolingControl = print_f88(); break;
846856
case TsetCH2: OTdataObject.TsetCH2 = print_f88(); break;
847857
case TrOverride: OTdataObject.TrOverride = print_f88(); break;
@@ -1029,7 +1039,7 @@ void handleOTGW()
10291039
String getOTGWValue(int msgid)
10301040
{
10311041
switch (static_cast<OpenThermMessageID>(msgid)) {
1032-
case TSet: return String(OTdataObject.Tset); break;
1042+
case TSet: return String(OTdataObject.TSet); break;
10331043
case CoolingControl: return String(OTdataObject.CoolingControl); break;
10341044
case TsetCH2: return String(OTdataObject.TsetCH2); break;
10351045
case TrOverride: return String(OTdataObject.TrOverride); break;
@@ -1127,10 +1137,10 @@ void startOTGWstream()
11271137
OTGWstream.begin();
11281138
}
11291139

1130-
void upgradenow() {
1140+
void upgradepicnow(const char *filename) {
11311141
if (OTGWSerial.busy()) return; // if already in programming mode, never call it twice
11321142
DebugTln("Start PIC upgrade now.");
1133-
fwupgradestart(FIRMWARE);
1143+
fwupgradestart(filename);
11341144
while (OTGWSerial.busy()){
11351145
feedWatchDog();
11361146
//blink the led during flash...
@@ -1161,6 +1171,8 @@ void fwupgradedone(OTGWError result, short errors = 0, short retries = 0) {
11611171
}
11621172
}
11631173

1174+
1175+
// Schelte's firmware integration
11641176
void fwupgradestart(const char *hexfile) {
11651177
OTGWError result;
11661178

@@ -1173,6 +1185,76 @@ void fwupgradestart(const char *hexfile) {
11731185
}
11741186
}
11751187

1188+
String checkforupdatepic(String filename){
1189+
WiFiClient client;
1190+
HTTPClient http;
1191+
String latest = "";
1192+
int code;
1193+
1194+
http.begin(client, "http://otgw.tclcode.com/download/" + filename);
1195+
http.collectHeaders(hexheaders, 2);
1196+
code = http.sendRequest("HEAD");
1197+
if (code == HTTP_CODE_OK) {
1198+
for (int i = 0; i< http.headers(); i++) {
1199+
DebugTf("%s: %s\n", hexheaders[i], http.header(i).c_str());
1200+
}
1201+
latest = http.header(1);
1202+
DebugTf("Update %s -> %s\n", filename.c_str(), latest.c_str());
1203+
http.end();
1204+
}
1205+
return latest;
1206+
}
1207+
1208+
void refreshpic(String filename, String version) {
1209+
WiFiClient client;
1210+
HTTPClient http;
1211+
String latest;
1212+
int code;
1213+
1214+
if (latest=checkforupdatepic(filename) != "") {
1215+
if (latest != version) {
1216+
DebugTf("Update %s: %s -> %s\n", filename.c_str(), version.c_str(), latest.c_str());
1217+
http.begin(client, "http://otgw.tclcode.com/download/" + filename);
1218+
code = http.GET();
1219+
if (code == HTTP_CODE_OK) {
1220+
File f = LittleFS.open("/" + filename, "w");
1221+
if (f) {
1222+
http.writeToStream(&f);
1223+
f.close();
1224+
String verfile = "/" + filename;
1225+
verfile.replace(".hex", ".ver");
1226+
f = LittleFS.open(verfile, "w");
1227+
if (f) {
1228+
f.print(latest + "\n");
1229+
f.close();
1230+
DebugTf("Update successful\n");
1231+
}
1232+
}
1233+
}
1234+
}
1235+
}
1236+
http.end();
1237+
}
1238+
1239+
void upgradepic() {
1240+
String action = httpServer.arg("action");
1241+
String filename = httpServer.arg("name");
1242+
String version = httpServer.arg("version");
1243+
DebugTf("Action: %s %s %s\r\n", action.c_str(), filename.c_str(), version.c_str());
1244+
if (action == "upgrade") {
1245+
upgradepicnow(String("/" + filename).c_str());
1246+
} else if (action == "refresh") {
1247+
refreshpic(filename, version);
1248+
} else if (action == "delete") {
1249+
String path = "/" + filename;
1250+
LittleFS.remove(path);
1251+
path.replace(".hex", ".ver");
1252+
LittleFS.remove(path);
1253+
}
1254+
httpServer.sendHeader("Location", "index.html#tabPICflash", true);
1255+
httpServer.send(303, "text/html", "<a href='index.html#tabPICflash'>Return</a>");
1256+
}
1257+
11761258
/***************************************************************************
11771259
*
11781260
* Permission is hereby granted, free of charge, to any person obtaining a

0 commit comments

Comments
 (0)