kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
OTA also for files (www/js/css)
rodzic
debaf57f88
commit
ef90bc3f34
|
@ -41,11 +41,13 @@ AXP20X_Class axp;
|
||||||
SemaphoreHandle_t axpSemaphore;
|
SemaphoreHandle_t axpSemaphore;
|
||||||
bool pmu_irq = false;
|
bool pmu_irq = false;
|
||||||
|
|
||||||
String updateHost = "rdzsonde.mooo.com";
|
const char *updateHost = "rdzsonde.mooo.com";
|
||||||
int updatePort = 80;
|
int updatePort = 80;
|
||||||
String updateBinM = "/master/update.ino.bin";
|
|
||||||
String updateBinD = "/devel/update.ino.bin";
|
const char *updatePrefixM = "/master/";
|
||||||
String *updateBin = &updateBinM;
|
const char *updatePrefixD = "/devel/";
|
||||||
|
const char *updatePrefix = updatePrefixM;
|
||||||
|
|
||||||
|
|
||||||
#define LOCALUDPPORT 9002
|
#define LOCALUDPPORT 9002
|
||||||
//Get real UTC time from NTP server
|
//Get real UTC time from NTP server
|
||||||
|
@ -1076,14 +1078,14 @@ const char *handleUpdatePost(AsyncWebServerRequest *request) {
|
||||||
Serial.println(param.c_str());
|
Serial.println(param.c_str());
|
||||||
if (param.equals("devel")) {
|
if (param.equals("devel")) {
|
||||||
Serial.println("equals devel");
|
Serial.println("equals devel");
|
||||||
updateBin = &updateBinD;
|
updatePrefix = updatePrefixD;
|
||||||
}
|
}
|
||||||
else if (param.equals("master")) {
|
else if (param.equals("master")) {
|
||||||
Serial.println("equals master");
|
Serial.println("equals master");
|
||||||
updateBin = &updateBinM;
|
updatePrefix = updatePrefixM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Serial.println("Updating: " + *updateBin);
|
Serial.printf("Updating: %supdate.ino.bin\n", updatePrefix);
|
||||||
enterMode(ST_UPDATE);
|
enterMode(ST_UPDATE);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -2901,27 +2903,81 @@ void execOTA() {
|
||||||
if ( ISOLED(sonde.config) ) {
|
if ( ISOLED(sonde.config) ) {
|
||||||
disp.rdis->setFont(FONT_SMALL);
|
disp.rdis->setFont(FONT_SMALL);
|
||||||
dispxs = dispys = 1;
|
dispxs = dispys = 1;
|
||||||
|
char uh[17];
|
||||||
|
strncpy(uh, updateHost, 17);
|
||||||
|
uh[16]=0;
|
||||||
|
disp.rdis->drawString(0, 0, uh);
|
||||||
} else {
|
} else {
|
||||||
disp.rdis->setFont(5);
|
disp.rdis->setFont(5);
|
||||||
dispxs = 18;
|
dispxs = 18;
|
||||||
dispys = 20;
|
dispys = 20;
|
||||||
|
disp.rdis->drawString(0, 0, updateHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
String dispHost = updateHost.substring(0, 16);
|
Serial.print("Connecting to: "); Serial.println(updateHost);
|
||||||
disp.rdis->drawString(0, 0, dispHost.c_str());
|
|
||||||
|
|
||||||
Serial.println("Connecting to: " + updateHost);
|
|
||||||
// Connect to Update host
|
// Connect to Update host
|
||||||
if (client.connect(updateHost.c_str(), updatePort)) {
|
if (!client.connect(updateHost, updatePort)) {
|
||||||
|
Serial.println("Connection to " + String(updateHost) + " failed. Please check your setup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, update file system
|
||||||
|
Serial.println("Fetching fs update");
|
||||||
|
disp.rdis->drawString(0, 1 * dispys, "Fetching fs...");
|
||||||
|
client.printf("GET %supdate.fs.bin HTTP/1.1\r\n"
|
||||||
|
"Host: %s\r\n"
|
||||||
|
"Cache-Control: no-cache\r\n"
|
||||||
|
"Connection: close\r\n\r\n", updatePrefix, updateHost);
|
||||||
|
// see if we get some data....
|
||||||
|
|
||||||
|
int type = 0;
|
||||||
|
int res = fetchHTTPheader(&type);
|
||||||
|
if(res < 0) { return; }
|
||||||
|
// process data...
|
||||||
|
while(client.available()) {
|
||||||
|
// get header...
|
||||||
|
char fn[128];
|
||||||
|
fn[0] = '/';
|
||||||
|
client.readBytesUntil('\n', fn+1, 128);
|
||||||
|
char *sz = strchr(fn, ' ');
|
||||||
|
if(!sz) { client.stop(); return; }
|
||||||
|
*sz = 0;
|
||||||
|
int len = atoi(sz+1);
|
||||||
|
Serial.printf("Updating file %s (%d bytes)\n", fn, len);
|
||||||
|
char fnstr[17];
|
||||||
|
memset(fnstr, ' ', 16);
|
||||||
|
strncpy(fnstr, fn, strlen(fn));
|
||||||
|
fnstr[16]=0;
|
||||||
|
disp.rdis->drawString(0, 2 * dispys, fnstr);
|
||||||
|
File f = SPIFFS.open(fn, FILE_WRITE);
|
||||||
|
// read sz bytes........
|
||||||
|
while(len>0) {
|
||||||
|
unsigned char buf[1024];
|
||||||
|
int r = client.read(buf, len>1024? 1024:len);
|
||||||
|
if(r==-1) { client.stop(); return; }
|
||||||
|
f.write(buf, r);
|
||||||
|
len -= r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client.stop();
|
||||||
|
|
||||||
|
Serial.print("Connecting to: "); Serial.println(updateHost);
|
||||||
|
// Connect to Update host
|
||||||
|
if (!client.connect(updateHost, updatePort)) {
|
||||||
|
Serial.println("Connection to " + String(updateHost) + " failed. Please check your setup");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Connection succeeded, fecthing the bin
|
// Connection succeeded, fecthing the bin
|
||||||
Serial.println("Fetching bin: " + String(*updateBin));
|
Serial.printf("Fetching bin: %supdate.ino.bin\n", updatePrefix);
|
||||||
disp.rdis->drawString(0, 1 * dispys, "Fetching update");
|
disp.rdis->drawString(0, 3 * dispys, "Fetching update");
|
||||||
|
|
||||||
// Get the contents of the bin file
|
// Get the contents of the bin file
|
||||||
client.print(String("GET ") + *updateBin + " HTTP/1.1\r\n" +
|
client.printf("GET %supdate.ino.bin HTTP/1.1\r\n"
|
||||||
"Host: " + updateHost + "\r\n" +
|
"Host: %s\r\n"
|
||||||
"Cache-Control: no-cache\r\n" +
|
"Cache-Control: no-cache\r\n"
|
||||||
"Connection: close\r\n\r\n");
|
"Connection: close\r\n\r\n",
|
||||||
|
updatePrefix, updateHost);
|
||||||
|
|
||||||
// Check what is being sent
|
// Check what is being sent
|
||||||
// Serial.print(String("GET ") + bin + " HTTP/1.1\r\n" +
|
// Serial.print(String("GET ") + bin + " HTTP/1.1\r\n" +
|
||||||
|
@ -2929,101 +2985,27 @@ void execOTA() {
|
||||||
// "Cache-Control: no-cache\r\n" +
|
// "Cache-Control: no-cache\r\n" +
|
||||||
// "Connection: close\r\n\r\n");
|
// "Connection: close\r\n\r\n");
|
||||||
|
|
||||||
unsigned long timeout = millis();
|
int validType = 0;
|
||||||
while (client.available() == 0) {
|
contentLength = fetchHTTPheader( &validType );
|
||||||
if (millis() - timeout > 5000) {
|
if(validType==1) isValidContentType = true;
|
||||||
Serial.println("Client Timeout !");
|
|
||||||
client.stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Once the response is available,
|
|
||||||
// check stuff
|
|
||||||
|
|
||||||
/*
|
|
||||||
Response Structure
|
|
||||||
HTTP/1.1 200 OK
|
|
||||||
x-amz-id-2: NVKxnU1aIQMmpGKhSwpCBh8y2JPbak18QLIfE+OiUDOos+7UftZKjtCFqrwsGOZRN5Zee0jpTd0=
|
|
||||||
x-amz-request-id: 2D56B47560B764EC
|
|
||||||
Date: Wed, 14 Jun 2017 03:33:59 GMT
|
|
||||||
Last-Modified: Fri, 02 Jun 2017 14:50:11 GMT
|
|
||||||
ETag: "d2afebbaaebc38cd669ce36727152af9"
|
|
||||||
Accept-Ranges: bytes
|
|
||||||
Content-Type: application/octet-stream
|
|
||||||
Content-Length: 357280
|
|
||||||
Server: AmazonS3
|
|
||||||
|
|
||||||
{{BIN FILE CONTENTS}}
|
|
||||||
|
|
||||||
*/
|
|
||||||
while (client.available()) {
|
|
||||||
// read line till /n
|
|
||||||
String line = client.readStringUntil('\n');
|
|
||||||
// remove space, to check if the line is end of headers
|
|
||||||
line.trim();
|
|
||||||
|
|
||||||
// if the the line is empty,
|
|
||||||
// this is end of headers
|
|
||||||
// break the while and feed the
|
|
||||||
// remaining `client` to the
|
|
||||||
// Update.writeStream();
|
|
||||||
if (!line.length()) {
|
|
||||||
//headers ended
|
|
||||||
break; // and get the OTA started
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the HTTP Response is 200
|
|
||||||
// else break and Exit Update
|
|
||||||
if (line.startsWith("HTTP/1.1")) {
|
|
||||||
if (line.indexOf("200") < 0) {
|
|
||||||
Serial.println("Got a non 200 status code from server. Exiting OTA Update.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract headers here
|
|
||||||
// Start with content length
|
|
||||||
if (line.startsWith("Content-Length: ")) {
|
|
||||||
contentLength = atoi((getHeaderValue(line, "Content-Length: ")).c_str());
|
|
||||||
Serial.println("Got " + String(contentLength) + " bytes from server");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, the content type
|
|
||||||
if (line.startsWith("Content-Type: ")) {
|
|
||||||
String contentType = getHeaderValue(line, "Content-Type: ");
|
|
||||||
Serial.println("Got " + contentType + " payload.");
|
|
||||||
if (contentType == "application/octet-stream") {
|
|
||||||
isValidContentType = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Connect to updateHost failed
|
|
||||||
// May be try?
|
|
||||||
// Probably a choppy network?
|
|
||||||
Serial.println("Connection to " + String(updateHost) + " failed. Please check your setup");
|
|
||||||
// retry??
|
|
||||||
// execOTA();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check what is the contentLength and if content type is `application/octet-stream`
|
// Check what is the contentLength and if content type is `application/octet-stream`
|
||||||
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
|
Serial.println("contentLength : " + String(contentLength) + ", isValidContentType : " + String(isValidContentType));
|
||||||
disp.rdis->drawString(0, 2 * dispys, "Len: ");
|
disp.rdis->drawString(0, 4 * dispys, "Len: ");
|
||||||
String cls = String(contentLength);
|
String cls = String(contentLength);
|
||||||
disp.rdis->drawString(5 * dispxs, 2 * dispys, cls.c_str());
|
disp.rdis->drawString(5 * dispxs, 4 * dispys, cls.c_str());
|
||||||
|
|
||||||
// check contentLength and content type
|
// check contentLength and content type
|
||||||
if (contentLength && isValidContentType) {
|
if (contentLength && isValidContentType) {
|
||||||
// Check if there is enough to OTA Update
|
// Check if there is enough to OTA Update
|
||||||
bool canBegin = Update.begin(contentLength);
|
bool canBegin = Update.begin(contentLength);
|
||||||
disp.rdis->drawString(0, 4 * dispys, "Starting update");
|
|
||||||
|
|
||||||
// If yes, begin
|
// If yes, begin
|
||||||
if (canBegin) {
|
if (canBegin) {
|
||||||
|
disp.rdis->drawString(0, 5 * dispys, "Starting update");
|
||||||
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
|
Serial.println("Begin OTA. This may take 2 - 5 mins to complete. Things might be quite for a while.. Patience!");
|
||||||
// No activity would appear on the Serial monitor
|
// No activity would appear on the Serial monitor
|
||||||
// So be patient. This may take 2 - 5mins to complete
|
// So be patient. This may take 2 - 5mins to complete
|
||||||
disp.rdis->drawString(0, 5 * dispys, "Please wait!");
|
|
||||||
size_t written = Update.writeStream(client);
|
size_t written = Update.writeStream(client);
|
||||||
|
|
||||||
if (written == contentLength) {
|
if (written == contentLength) {
|
||||||
|
@ -3062,6 +3044,77 @@ void execOTA() {
|
||||||
enterMode(ST_DECODER);
|
enterMode(ST_DECODER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fetchHTTPheader(int *validType) {
|
||||||
|
int contentLength = -1;
|
||||||
|
unsigned long timeout = millis();
|
||||||
|
while (client.available() == 0) {
|
||||||
|
if (millis() - timeout > 5000) {
|
||||||
|
Serial.println("Client Timeout !");
|
||||||
|
client.stop();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Once the response is available, check stuff
|
||||||
|
|
||||||
|
/*
|
||||||
|
Response Structure
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
x-amz-id-2: NVKxnU1aIQMmpGKhSwpCBh8y2JPbak18QLIfE+OiUDOos+7UftZKjtCFqrwsGOZRN5Zee0jpTd0=
|
||||||
|
x-amz-request-id: 2D56B47560B764EC
|
||||||
|
Date: Wed, 14 Jun 2017 03:33:59 GMT
|
||||||
|
Last-Modified: Fri, 02 Jun 2017 14:50:11 GMT
|
||||||
|
ETag: "d2afebbaaebc38cd669ce36727152af9"
|
||||||
|
Accept-Ranges: bytes
|
||||||
|
Content-Type: application/octet-stream
|
||||||
|
Content-Length: 357280
|
||||||
|
Server: AmazonS3
|
||||||
|
|
||||||
|
{{BIN FILE CONTENTS}}
|
||||||
|
|
||||||
|
*/
|
||||||
|
while (client.available()) {
|
||||||
|
// read line till \n
|
||||||
|
String line = client.readStringUntil('\n');
|
||||||
|
// remove space, to check if the line is end of headers
|
||||||
|
line.trim();
|
||||||
|
|
||||||
|
// if the the line is empty,
|
||||||
|
// this is end of headers
|
||||||
|
// break the while and feed the
|
||||||
|
// remaining `client` to the
|
||||||
|
// Update.writeStream();
|
||||||
|
if (!line.length()) {
|
||||||
|
//headers ended
|
||||||
|
break; // and get the OTA started
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the HTTP Response is 200
|
||||||
|
// else break and Exit Update
|
||||||
|
if (line.startsWith("HTTP/1.1")) {
|
||||||
|
if (line.indexOf("200") < 0) {
|
||||||
|
Serial.println("Got a non 200 status code from server. Exiting OTA Update.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract headers here
|
||||||
|
// Start with content length
|
||||||
|
if (line.startsWith("Content-Length: ")) {
|
||||||
|
contentLength = atoi((getHeaderValue(line, "Content-Length: ")).c_str());
|
||||||
|
Serial.println("Got " + String(contentLength) + " bytes from server");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, the content type
|
||||||
|
if (line.startsWith("Content-Type: ")) {
|
||||||
|
String contentType = getHeaderValue(line, "Content-Type: ");
|
||||||
|
Serial.println("Got " + contentType + " payload.");
|
||||||
|
if (contentType == "application/octet-stream") {
|
||||||
|
if(validType) *validType = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,6 @@ void ShFreqImport::setLabel(int idx, char *id, float lat, float lon) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShFreqImport::usekeyvalue() {
|
void ShFreqImport::usekeyvalue() {
|
||||||
printf("\nUSEKEYVALUE: key %s => value %s\n", keyword, value);
|
|
||||||
if(strcmp(keyword,"lat")==0) lat = atof(value);
|
if(strcmp(keyword,"lat")==0) lat = atof(value);
|
||||||
if(strcmp(keyword,"lon")==0) lon = atof(value);
|
if(strcmp(keyword,"lon")==0) lon = atof(value);
|
||||||
if(strcmp(keyword,"frequency")==0) freq = atof(value);
|
if(strcmp(keyword,"frequency")==0) freq = atof(value);
|
||||||
|
@ -56,7 +55,7 @@ void ShFreqImport::usekeyvalue() {
|
||||||
/* populate qrg.txt with frequency of near sonde */
|
/* populate qrg.txt with frequency of near sonde */
|
||||||
void ShFreqImport::populate(char *id, float lat, float lon, float freq, const char *type)
|
void ShFreqImport::populate(char *id, float lat, float lon, float freq, const char *type)
|
||||||
{
|
{
|
||||||
printf(" ID %s: %.5f, %.5f f=%.3f, type=%s \n", id, lat, lon, freq, type);
|
//printf(" ID %s: %.5f, %.5f f=%.3f, type=%s \n", id, lat, lon, freq, type);
|
||||||
// Skip if freq already exists
|
// Skip if freq already exists
|
||||||
int stype = stringToStype(type);
|
int stype = stringToStype(type);
|
||||||
if(stype<0) return; // unsupported type
|
if(stype<0) return; // unsupported type
|
||||||
|
@ -101,7 +100,7 @@ void ShFreqImport::populate(char *id, float lat, float lon, float freq, const ch
|
||||||
|
|
||||||
// clears all remaining automatically filled slots (no longer in SH data)
|
// clears all remaining automatically filled slots (no longer in SH data)
|
||||||
void ShFreqImport::cleanup() {
|
void ShFreqImport::cleanup() {
|
||||||
Serial.println("Cleanup called ********");
|
//Serial.println("Cleanup called ********");
|
||||||
for(int i=0; i<sonde.config.maxsonde; i++) {
|
for(int i=0; i<sonde.config.maxsonde; i++) {
|
||||||
if( (((inuse[i/8]>>(i&7))&1) == 0) && *sonde.sondeList[i].launchsite=='@' ) {
|
if( (((inuse[i/8]>>(i&7))&1) == 0) && *sonde.sondeList[i].launchsite=='@' ) {
|
||||||
Serial.printf("removing #%d\n", i);
|
Serial.printf("removing #%d\n", i);
|
||||||
|
@ -176,7 +175,7 @@ int ShFreqImport::handleChar(char c) {
|
||||||
if(c=='}') {
|
if(c=='}') {
|
||||||
// we have an ID and all key/value pairs, check if its good....
|
// we have an ID and all key/value pairs, check if its good....
|
||||||
if( !isnan(lat) && !isnan(lon) && !isnan(freq) && type[0] ) {
|
if( !isnan(lat) && !isnan(lon) && !isnan(freq) && type[0] ) {
|
||||||
printf("populate %s %f %f %f %s\n", id, lat, lon, freq, type);
|
printf("SondeHub import: populate %s %f %f %f %s\n", id, lat, lon, freq, type);
|
||||||
populate(id, lat, lon, freq, type);
|
populate(id, lat, lon, freq, type);
|
||||||
} else {
|
} else {
|
||||||
printf("Skipping incomplete %s\n", id);
|
printf("Skipping incomplete %s\n", id);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const char *version_name = "rdzTTGOsonde";
|
const char *version_name = "rdzTTGOsonde";
|
||||||
const char *version_id = "devel20210915";
|
const char *version_id = "devel20210916";
|
||||||
const int SPIFFS_MAJOR=2;
|
const int SPIFFS_MAJOR=2;
|
||||||
const int SPIFFS_MINOR=16;
|
const int SPIFFS_MINOR=16;
|
||||||
|
|
Ładowanie…
Reference in New Issue