ETAG control for http client

This commit is contained in:
2021-11-05 02:26:50 +03:00
parent 2ee8ad5ab6
commit 201f492e29
7 changed files with 145 additions and 54 deletions

3
compiled/due/upload.sh Executable file
View File

@@ -0,0 +1,3 @@
export PORT=cu.usbmodem14201
echo . | stty -f /dev/$PORT speed 1200
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -e -w -v -b firmware.bin -R

View File

@@ -1,6 +1,7 @@
#include "config.h" #include "config.h"
#include "main.h" #include "main.h"
String systemConfig::getMACString() String systemConfig::getMACString()
{ {
String res; String res;
@@ -293,11 +294,40 @@ return false;
String systemConfig::getETAG() String systemConfig::getETAG()
{ {
return "123"; debugSerial<<F("Get ETAG: ")<<currentConfigETAG<<endl;
return String("\"")+currentConfigETAG+String("\"");
} }
bool systemConfig::setETAG(String etag) bool systemConfig::setETAG(String etag)
{ {
debugSerial<<F("ETAG:")<<etag<<endl; int firstPos = etag.indexOf('"');
int lastPos = etag.lastIndexOf('"');
if ((firstPos>=0) && (lastPos>0)) currentConfigETAG=etag.substring(firstPos+1,lastPos);
else currentConfigETAG=etag;
debugSerial<<F("Set ETAG: ")<<currentConfigETAG<<endl;
return 1; return 1;
} }
bool systemConfig::saveETAG()
{
if (!stream || !isValidSysConf() || (currentConfigETAG.length()>=sizeof(systemConfigData::ETAG))) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,ETAG));
stream->print(currentConfigETAG);
int bytes = stream->write((uint8_t)'\0');
stream->close();
if (bytes) debugSerial<<F("Saved ETAG:")<<currentConfigETAG<<endl;
return bytes;
}
bool systemConfig::loadETAG()
{
if (!stream || !isValidSysConf()) return false;
openStream('r');
stream->seek(offsetof(systemConfigData,ETAG));
currentConfigETAG=stream->readStringUntil(0);
stream->close();
debugSerial<<F("Loaded ETAG:")<<currentConfigETAG<<endl;
return currentConfigETAG.length();
}

View File

@@ -12,12 +12,14 @@
class systemConfig { class systemConfig {
private: private:
flashStream * stream; flashStream * stream;
String currentConfigETAG;
int openStream(char mode = '\0'); int openStream(char mode = '\0');
public: public:
macAddress mac; macAddress mac;
systemConfig() {stream=NULL;};
systemConfig(flashStream * fs){stream=fs;}; systemConfig():currentConfigETAG() {stream=NULL;};
systemConfig(flashStream * fs):currentConfigETAG() {stream=fs;};
bool isValidSysConf(); bool isValidSysConf();
@@ -56,6 +58,8 @@ class systemConfig {
bool setLoadHTTPConfig(bool); bool setLoadHTTPConfig(bool);
String getETAG(); String getETAG();
bool setETAG(String etag); bool setETAG(String etag);
bool saveETAG();
bool loadETAG();
//bool Save(); //bool Save();
}; };

View File

@@ -172,7 +172,7 @@ NRFFlashStorage EEPROM;
unsigned int flashStream::seek(unsigned int _pos) unsigned int flashStream::seek(unsigned int _pos)
{ pos=min(_pos, streamSize); { pos=min(_pos, streamSize);
debugSerial<<F("Seek:")<<pos<<endl; //debugSerial<<F("Seek:")<<pos<<endl;
return pos; return pos;
}; };

View File

@@ -571,7 +571,7 @@ lan_status lanLoop() {
if (!configOk) if (!configOk)
{ {
if (loadConfigFromHttp(0, NULL)) lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER; if (loadConfigFromHttp()) lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
else if (configLoaded) { else if (configLoaded) {
infoSerial<<F("Continue with previously loaded config")<<endl; infoSerial<<F("Continue with previously loaded config")<<endl;
lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER; lanStatus = IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
@@ -1315,19 +1315,23 @@ int loadConfigFromEEPROM()
sysConfStream.close(); sysConfStream.close();
if (!root) { if (!root) {
errorSerial<<F("load failed")<<endl; errorSerial<<F("load failed")<<endl;
sysConf.setETAG("");
// sysConfStream.close(); // sysConfStream.close();
return 0; return 0;
} }
infoSerial<<F("Loaded")<<endl; infoSerial<<F("Loaded")<<endl;
applyConfig(); applyConfig();
sysConf.loadETAG();
//ethClient.stop(); //Refresh MQTT connect to get retained info //ethClient.stop(); //Refresh MQTT connect to get retained info
return 1; return 1;
} else { } else if (sysConfStream.available())
{
sysConfStream.putEOF(); //truncate garbage sysConfStream.putEOF(); //truncate garbage
infoSerial<<F("No stored config")<<endl; sysConf.setETAG("");
sysConfStream.close(); sysConf.saveETAG();
return 0;
} }
sysConfStream.close();
infoSerial<<F("No stored config")<<endl;
return 0; return 0;
} }
@@ -1371,6 +1375,7 @@ if (arg_cnt>1)
sysConfStream.close(); sysConfStream.close();
infoSerial<<F("Saved to EEPROM")<<endl; infoSerial<<F("Saved to EEPROM")<<endl;
#endif #endif
sysConf.saveETAG();
return 200; return 200;
} }
@@ -1453,6 +1458,14 @@ int cmdFunctionClearEEPROM(int arg_cnt, char **args){
if (SPIFFS.format()) infoSerial<<F("FS Formatted\n"); if (SPIFFS.format()) infoSerial<<F("FS Formatted\n");
#endif #endif
if (sysConf.clear()) infoSerial<<F("EEPROM cleared\n"); if (sysConf.clear()) infoSerial<<F("EEPROM cleared\n");
#if defined(FS_STORAGE)
sysConfStream.open("/config.json",'r');
#else
sysConfStream.open(FN_CONFIG_JSON,'r');
#endif
sysConfStream.putEOF();
sysConfStream.close();
return 200; return 200;
} }
@@ -1498,8 +1511,20 @@ if (arg_cnt>1)
infoSerial<<F("Loading HTTP config on startup:")<<sysConf.getLoadHTTPConfig()<<endl; infoSerial<<F("Loading HTTP config on startup:")<<sysConf.getLoadHTTPConfig()<<endl;
sysConf.setServer(args[1]);
infoSerial<<args[1]<<F(" Saved")<<endl;
} }
if (lanStatus>=HAVE_IP_ADDRESS)
{
configOk=false;
lanStatus=LIBS_INITIALIZED;
return 200;
}
errorSerial<<F("No IP adress")<<endl;
return 500;
/*
if (loadConfigFromHttp(arg_cnt, args)) if (loadConfigFromHttp(arg_cnt, args))
{ {
lanStatus =IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER; lanStatus =IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
@@ -1508,25 +1533,20 @@ if (arg_cnt>1)
// Not Loaded // Not Loaded
if (configLoaded) lanStatus =IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER; if (configLoaded) lanStatus =IP_READY_CONFIG_LOADED_CONNECTING_TO_BROKER;
else lanStatus = READ_RE_CONFIG; else lanStatus = READ_RE_CONFIG;
return 500; return 500; */
} }
void printBool(bool arg) { (arg) ? infoSerial<<F("+") : infoSerial<<F("-"); } void printBool(bool arg) { (arg) ? infoSerial<<F("+") : infoSerial<<F("-"); }
const char * headerKeys[]={"ETag"};
bool loadConfigFromHttp(int arg_cnt, char **args) bool loadConfigFromHttp()
{ {
//macAddress * mac = sysConf.getMAC(); //macAddress * mac = sysConf.getMAC();
int responseStatusCode = 0; int responseStatusCode = 0;
char URI[64]; char URI[64];
char configServer[32]=""; char configServer[32]="";
String etag=sysConf.getETAG(); if (!sysConf.getServer(configServer,sizeof(configServer)))
if (arg_cnt > 1) {
strncpy(configServer, args[1], sizeof(configServer) - 1);
sysConf.setServer(configServer);
//saveFlash(OFFSET_CONFIGSERVER, configServer);
infoSerial<<configServer<<F(" Saved")<<endl;
} else if (!sysConf.getServer(configServer,sizeof(configServer)))
{ {
strncpy_P(configServer,configserver,sizeof(configServer)); strncpy_P(configServer,configserver,sizeof(configServer));
infoSerial<<F(" Default config server used: ")<<configServer<<endl; infoSerial<<F(" Default config server used: ")<<configServer<<endl;
@@ -1573,6 +1593,7 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
if (!root) if (!root)
{ {
sysConf.setETAG("");
errorSerial<<F("Config parsing failed\n"); errorSerial<<F("Config parsing failed\n");
return false; return false;
} }
@@ -1583,7 +1604,14 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
return true; return true;
} }
} else { }
else if (responseStatusCode == 304)
{
errorSerial<<F("Config not changed\n");
return false;
}
else
{
errorSerial<<F("ERROR: Server returned "); errorSerial<<F("ERROR: Server returned ");
errorSerial<<responseStatusCode<<endl; errorSerial<<responseStatusCode<<endl;
return false; return false;
@@ -1600,7 +1628,7 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
#else #else
EthernetClient configEthClient; EthernetClient configEthClient;
#endif #endif
String response; //String response;
HttpClient htclient = HttpClient(configEthClient, configServer, 80); HttpClient htclient = HttpClient(configEthClient, configServer, 80);
//htclient.stop(); //_socket =MAX //htclient.stop(); //_socket =MAX
htclient.setHttpResponseTimeout(4000); htclient.setHttpResponseTimeout(4000);
@@ -1608,8 +1636,8 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
//debugSerial<<"making GET request");get //debugSerial<<"making GET request");get
debugSerial<<F("Before request: Free:")<<freeRam()<<endl; debugSerial<<F("Before request: Free:")<<freeRam()<<endl;
htclient.beginRequest(); htclient.beginRequest();
htclient.sendHeader("If-None-Match:",etag);
responseStatusCode = htclient.get(URI); responseStatusCode = htclient.get(URI);
htclient.sendHeader("If-None-Match",sysConf.getETAG());
htclient.endRequest(); htclient.endRequest();
if (responseStatusCode == HTTP_SUCCESS) if (responseStatusCode == HTTP_SUCCESS)
@@ -1618,24 +1646,27 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
responseStatusCode = htclient.responseStatusCode(); responseStatusCode = htclient.responseStatusCode();
while (htclient.headerAvailable()) while (htclient.headerAvailable())
if (htclient.readHeaderName() == "ETAG") sysConf.setETAG(htclient.readHeaderValue()); if (htclient.readHeaderName().equalsIgnoreCase("ETAG")) sysConf.setETAG(htclient.readHeaderValue());
//response = htclient.responseBody();
response = htclient.responseBody();
htclient.stop();
wdt_res(); wdt_res();
infoSerial<<F("HTTP Status code: ")<<responseStatusCode<<endl; infoSerial<<F("HTTP Status code: ")<<responseStatusCode<<endl;
if (responseStatusCode == 200) { if (responseStatusCode == 200) {
aJsonStream socketStream = aJsonStream(&htclient);
debugSerial<<F("Free:")<<freeRam()<<endl; debugSerial<<F("Free:")<<freeRam()<<endl;
debugSerial<<F("Response Len:")<<response.length()<<endl; //debugSerial<<F("Response Len:")<<response.length()<<endl;
//debugSerial<<F("GET Response: ")<<response<<endl; //debugSerial<<F("GET Response: ")<<response<<endl;
cleanConf(); cleanConf();
debugSerial<<F("Configuration cleaned")<<endl; debugSerial<<F("Configuration cleaned")<<endl;
debugSerial<<F("Free:")<<freeRam()<<endl; debugSerial<<F("Free:")<<freeRam()<<endl;
root = aJson.parse((char *) response.c_str()); //root = aJson.parse((char *) response.c_str());
root = aJson.parse(&socketStream);
htclient.stop();
if (!root) { if (!root) {
errorSerial<<F("Config parsing failed\n"); errorSerial<<F("Config parsing failed\n");
sysConf.setETAG("");
return false; return false;
} }
else { else {
@@ -1645,15 +1676,18 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
infoSerial<<F("Done.\n"); infoSerial<<F("Done.\n");
return true; return true;
} }
} else {
errorSerial<<F("Config retrieving failed\n");
return false;
}
} }
else if (responseStatusCode == 304) else if (responseStatusCode == 304)
{ {
errorSerial<<F("Config not changed\n"); errorSerial<<F("Config not changed\n");
htclient.stop();
return false; return false;
}
else {
errorSerial<<F("Config retrieving failed\n");
htclient.stop();
return false;
}
} }
else else
{ {
@@ -1676,33 +1710,54 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
fullURI+=URI; fullURI+=URI;
#if defined(ARDUINO_ARCH_ESP8266) #if defined(ARDUINO_ARCH_ESP8266)
httpClient.begin(configEthClient,fullURI); httpClient.begin(configEthClient,fullURI);
#else #else
httpClient.begin(fullURI); httpClient.begin(fullURI);
#endif #endif
httpClient.addHeader("If-None-Match",sysConf.getETAG());
httpClient.collectHeaders(headerKeys,1);
responseStatusCode = httpClient.GET();
int httpResponseCode = httpClient.GET(); if (responseStatusCode > 0) {
infoSerial.printf("[HTTP] GET... code: %d\n", responseStatusCode);
if (httpResponseCode > 0) { if (responseStatusCode == HTTP_CODE_OK)
infoSerial.printf("[HTTP] GET... code: %d\n", httpResponseCode); {
if (httpResponseCode == HTTP_CODE_OK) { WiFiClient * stream = httpClient.getStreamPtr();
String response = httpClient.getString(); if (stream)
{
aJsonStream socketStream = aJsonStream(stream);
sysConf.setETAG(httpClient.header("ETag"));
//String response = httpClient.getString();
//debugSerial<<response;
cleanConf();
//root = aJson.parse((char *) response.c_str());
root = aJson.parse(&socketStream);
httpClient.end(); httpClient.end();
} else
debugSerial<<response; {
cleanConf(); httpClient.end();
root = aJson.parse((char *) response.c_str()); return false;
}
if (!root) { if (!root) {
sysConf.setETAG("");
errorSerial<<F("Config parsing failed\n"); errorSerial<<F("Config parsing failed\n");
return false; return false;
} else { } else {
infoSerial<<F("Config OK, Applying\n"); infoSerial<<F("Config OK, Applying\n");
applyConfig(); applyConfig();
infoSerial<<F("Done.\n"); infoSerial<<F("Done.\n");
return true; return true;
} }
} }
else if (responseStatusCode == HTTP_CODE_NOT_MODIFIED)
{
httpClient.end();
errorSerial<<F("Config not changed\n");
return false;
}
else else
{ {
httpClient.end(); httpClient.end();
@@ -1711,7 +1766,7 @@ bool loadConfigFromHttp(int arg_cnt, char **args)
} }
} else } else
{ {
errorSerial.printf("[HTTP] GET... failed, error: %s\n", httpClient.errorToString(httpResponseCode).c_str()); errorSerial.printf("[HTTP] GET... failed, error: %s\n", httpClient.errorToString(responseStatusCode).c_str());
httpClient.end(); httpClient.end();
return false; return false;
} }
@@ -1805,7 +1860,7 @@ void setup_main() {
debugSerial<<F("FLASH Init: ")<<streamSize<<endl; debugSerial<<F("FLASH Init: ")<<streamSize<<endl;
#endif #endif
#endif #endif
//Checkin EEPROM integrity (signature) //debugSerialPort << "Checkin EEPROM integrity (signature)"<<endl;
if (!sysConf.isValidSysConf()) if (!sysConf.isValidSysConf())
{ {

View File

@@ -280,7 +280,7 @@ void saveFlash(short n, IPAddress& ip);
int ipLoadFromFlash(short n, IPAddress &ip); int ipLoadFromFlash(short n, IPAddress &ip);
*/ */
bool loadConfigFromHttp(int arg_cnt = 0, char **args = NULL); bool loadConfigFromHttp();
void preTransmission(); void preTransmission();

View File

@@ -5,7 +5,7 @@
#define MAXFLASHSTR 32 #define MAXFLASHSTR 32
#define PWDFLASHSTR 16 #define PWDFLASHSTR 16
#define EEPROM_SIGNATURE "LHCF" #define EEPROM_SIGNATURE "LHC0"
#define EEPROM_SIGNATURE_LENGTH 4 #define EEPROM_SIGNATURE_LENGTH 4
//#define EEPROM_offsetJSON IFLASH_PAGE_SIZE //#define EEPROM_offsetJSON IFLASH_PAGE_SIZE
@@ -40,9 +40,8 @@ const char EEPROM_signature[] = EEPROM_SIGNATURE;
flashstr configURL; flashstr configURL;
flashpwd MQTTpwd; flashpwd MQTTpwd;
flashpwd OTApwd; flashpwd OTApwd;
flashstr ETAG;
uint16_t sysConfigHash; uint16_t sysConfigHash;
uint16_t JSONHash;
} systemConfigData; } systemConfigData;
#pragma (pop) #pragma (pop)