From fb7c0f004d0553ac10b52351b454dc64f073b7d5 Mon Sep 17 00:00:00 2001 From: Pawel Jalocha Date: Sat, 6 Mar 2021 17:06:50 +0000 Subject: [PATCH] Prepare to download log files as IGC from HTTP interface --- main/http.cpp | 36 ++++++++++++++++++++++++++++++++++-- main/ognconv.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- main/ognconv.h | 6 ++++-- main/sdlog.cpp | 16 +++++++++++++++- main/wifi.cpp | 5 +++++ utils/ognconv.cpp | 17 ++++++++--------- utils/ognconv.h | 4 ++-- 7 files changed, 108 insertions(+), 18 deletions(-) diff --git a/main/http.cpp b/main/http.cpp index bdc7aa9..9eca982 100644 --- a/main/http.cpp +++ b/main/http.cpp @@ -16,6 +16,7 @@ #include "gps.h" #include "log.h" #include "http.h" +#include "ognconv.h" // #define DEBUG_PRINT @@ -691,6 +692,33 @@ static int LogFileName(char *Name, time_t Time, const char *Ext=0) if(Ext) Len+=Format_String(Name+Len, Ext); Name[Len]=0; return Len; } +// send give log file in the IGC format +static esp_err_t SendLog_IGC(httpd_req_t *Req, const char *FileName, uint32_t FileTime) +{ char ContDisp[64]; + char Line[1000]; int Len=0; + Len=Format_String(ContDisp, "attachement; filename=\""); Len+=LogFileName(ContDisp+Len, FileTime, ".IGC"); ContDisp[Len++]='\"'; ContDisp[Len]=0; + httpd_resp_set_hdr(Req, "Content-Disposition", ContDisp); + httpd_resp_set_type(Req, "text/plain"); + FILE *File = fopen(FileName, "rb"); if(File==0) { httpd_resp_send_chunk(Req, 0, 0); return ESP_OK; } + // here we should write the IGC header + OGN_LogPacket Packet; + for( ; ; ) + { if(fread(&Packet, Packet.Bytes, 1, File)!=1) break; // read the next packet + if(!Packet.isCorrect()) continue; + uint32_t Time = Packet.getTime(FileTime); // [sec] get exact time from short time in the packet and the file start time + Len+=Format_String(Line+Len, "LGNE "); // attach APRS as LGNE record + char *APRS=Line+Len; + Len+=Packet.Packet.WriteAPRS(Line+Len, Time); // packet in the APRS format + bool Own = Packet.Packet.Header.Address==Parameters.Address && Packet.Packet.Header.AddrType==Parameters.AddrType; + if(Own && !Packet.Packet.Header.NonPos && !Packet.Packet.Header.Encrypted) + Len+=APRS2IGC(Line+Len, APRS, GPS_GeoidSepar); // IGC B-record + if(Len>=800) { httpd_resp_send_chunk(Req, Line, Len); Len=0; } // when more than 800 bytes then write this part to the socket + vTaskDelay(1); } + fclose(File); + if(Len) { httpd_resp_send_chunk(Req, Line, Len); Len=0; } + httpd_resp_send_chunk(Req, 0, 0); + return ESP_OK; } + // send give log file in the APRS format static esp_err_t SendLog_APRS(httpd_req_t *Req, const char *FileName, uint32_t FileTime) { char ContDisp[64]; @@ -748,6 +776,7 @@ static esp_err_t log_get_handler(httpd_req_t *Req) uint32_t Time=FlashLog_ReadShortFileTime(Name); if(Time) { if(strcmp(Format, "APRS")==0) return SendLog_APRS(Req, FullName, Time); + if(strcmp(Format, "IGC" )==0) return SendLog_IGC(Req, FullName, Time); return SendLog_TLG(Req, FullName, Time); } } } @@ -779,7 +808,7 @@ static esp_err_t log_get_handler(httpd_req_t *Req) closedir(Dir); std::sort(FileList.begin(), FileList.end()); - httpd_resp_sendstr_chunk(Req, "\n\n"); + httpd_resp_sendstr_chunk(Req, "
File[KB]Date
\n\n"); for(size_t Idx=0; Idx"); + Len+=Format_String(Line+Len, "
File[KB]Date
APRS"); + Len+=Format_String(Line+Len, "\">APRSIGC"); Len+=Format_UnsDec(Line+Len, (Size+512)>>10); Len+=Format_String(Line+Len, ""); Len+=Format_DateTime(Line+Len, Time); diff --git a/main/ognconv.cpp b/main/ognconv.cpp index 5ca9959..33cf913 100644 --- a/main/ognconv.cpp +++ b/main/ognconv.cpp @@ -1,11 +1,13 @@ #include +#include +#include "format.h" #include "ognconv.h" // ============================================================================================== -uint32_t FeetToMeters(uint32_t Altitude) { return (Altitude*312+512)>>10; } // [feet] => [m] -uint32_t MetersToFeet(uint32_t Altitude) { return (Altitude*3360+512)>>10; } // [m] => [feet] +int32_t FeetToMeters(int32_t Altitude) { return (Altitude*312+512)>>10; } // [feet] => [m] +int32_t MetersToFeet(int32_t Altitude) { return (Altitude*3360+512)>>10; } // [m] => [feet] // ============================================================================================== @@ -269,3 +271,39 @@ uint8_t DecodeAscii85(uint32_t &Word, const char *Ascii) // ============================================================================================== +int APRS2IGC(char *Out, const char *Inp, int GeoidSepar) // convert APRS positon message into IGC B-record +{ int Len=0; + const char *Msg = strchr(Inp, ':'); if(Msg==0) return 0; // colon: separates header and message + Msg++; // where message starts + if(Msg[0]!='/' || Msg[7]!='h') return 0; + const char *Pos = Msg+8; if(Pos[4]!='.' || Pos[14]!='.') return 0; // where position starts + const char *ExtPos = strstr(Pos+18, " !W"); if(ExtPos[5]=='!') ExtPos+=3; else ExtPos=0; + Out[Len++]='B'; // B-record + memcpy(Out+Len, Msg+1, 6); Len+=6; // copy UTC time + memcpy(Out+Len, Pos, 4); Len+=4; // copy DDMM + memcpy(Out+Len, Pos+5, 2); Len+=2; // copy fractional MM + Out[Len++] = ExtPos?ExtPos[0]:'0'; // extended precision + Out[Len++] = Pos[7]; // copy N/S sign + memcpy(Out+Len, Pos+9, 5); Len+=5; // copy DDMM + memcpy(Out+Len, Pos+15,2); Len+=2; // copy fractional MM + Out[Len++] = ExtPos?ExtPos[1]:'0'; // extended precision + Out[Len++] = Pos[17]; // copy E/W sign + Out[Len++] = 'A'; + memcpy(Out+Len, " ", 10); + const char *FL = strstr(Pos+18, " FL"); + int32_t AltH=0; int32_t AltL=0; + if(FL && FL[6]=='.' && Read_Int(AltH, FL+3)==3 && Read_Int(AltL, FL+7)==2) // pressure altitude + { int Alt = AltH*100+AltL; Alt=FeetToMeters(Alt); + if(Alt<0) { Alt = (-Alt); Out[Len] = '-'; Format_UnsDec(Out+Len+1, (uint32_t)Alt, 4); } + else { Format_UnsDec(Out+Len, (uint32_t)Alt, 5); } + } + Len+=5; int32_t Alt=0; + if(Pos[27]=='A' && Pos[28]=='=' && Read_Int(Alt, Pos+29)==6) // geometrical altitude + { Alt=FeetToMeters(Alt); Alt+=GeoidSepar; // convert to meters and add GeoidSepar for HAE + if(Alt<0) { Alt = (-Alt); Out[Len] = '-'; Format_UnsDec(Out+Len+1, (uint32_t)Alt, 4); } + else { Format_UnsDec(Out+Len, (uint32_t)Alt, 5); } + } + Len+=5; + Out[Len]=0; return Len; } + +// ============================================================================================== diff --git a/main/ognconv.h b/main/ognconv.h index 7b931ef..5854e96 100644 --- a/main/ognconv.h +++ b/main/ognconv.h @@ -3,8 +3,8 @@ #include -uint32_t FeetToMeters(uint32_t Altitude); // -uint32_t MetersToFeet(uint32_t Altitude); // +int32_t FeetToMeters(int32_t Altitude); // +int32_t MetersToFeet(int32_t Altitude); // uint16_t EncodeUR2V8(uint16_t Value); // Encode unsigned 12bit (0..3832) as 10bit uint16_t DecodeUR2V8(uint16_t Value); // Decode 10bit 0..0x3FF @@ -82,4 +82,6 @@ void xorshift64(uint64_t &Seed); uint8_t EncodeAscii85( char *Ascii, uint32_t Word ); // Encode 32-bit Word into 5-char Ascii-85 string uint8_t DecodeAscii85(uint32_t &Word, const char *Ascii); // Decode 5-char Ascii-85 to 32-bit Word +int APRS2IGC(char *Out, const char *Inp, int GeoidSepar); // convert APRS message to IGC B-record + #endif // __OGNCONV_H__ diff --git a/main/sdlog.cpp b/main/sdlog.cpp index 3157bd0..db5696d 100644 --- a/main/sdlog.cpp +++ b/main/sdlog.cpp @@ -174,7 +174,7 @@ static int IGC_LogLine(const char *Line, int Len) static int IGC_LogLine(const char *Line) { return IGC_LogLine(Line, strlen(Line)); } -static char Line[192]; +static char Line[512]; static int IGC_HeadParm(const char *Name, const char *Parm1, const char *Parm2=0, const char *Parm3=0) { int Len=Format_String(Line, Name); @@ -211,8 +211,22 @@ static int IGC_Header(const GPS_Position &Pos) // write the Line[Len++]='\n'; Line[Len]=0; IGC_LogLine(Line, Len); } IGC_LogLine("HFRFWFirmwareVersion:ESP32-OGN-TRACKER " __DATE__ " " __TIME__ "\n"); // firmware version, compile date/time +#ifdef WITH_FollowMe IGC_LogLine("HFGPSReceiver:L80\n"); // GPS sensor +#else +#ifdef WITH_GPS_UBX + IGC_LogLine("HFGPSReceiver:UBX\n"); // GPS sensor +#endif +#ifdef WITH_GPS_MTK + IGC_LogLine("HFGPSReceiver:MTK\n"); // GPS sensor +#endif +#endif +#ifdef WITH_BMP280 IGC_LogLine("HFPRSPressAltSensor:BMP280\n"); // pressure sensor +#endif +#ifdef WITH_BME280 + IGC_LogLine("HFPRSPressAltSensor:BME280\n"); // pressure sensor +#endif return 0; } int IGC_ID(void) diff --git a/main/wifi.cpp b/main/wifi.cpp index 241d05d..8aa4e29 100644 --- a/main/wifi.cpp +++ b/main/wifi.cpp @@ -73,6 +73,11 @@ esp_err_t WIFI_StartAP(const char *SSID, const char *Pass, int MaxConnections) else WIFI_Config.ap.password[0]=0; WIFI_Config.ap.max_connection = MaxConnections; WIFI_Config.ap.authmode = (Pass && Pass[0]) ? WIFI_AUTH_WPA_WPA2_PSK:WIFI_AUTH_OPEN; + // tcpip_adapter_ip_info_t IPinfo; // attempt to change the IP range to 192.168.1.1 but does not work + // IP4_ADDR(&IPinfo.ip, 192,168,1,1); + // IP4_ADDR(&IPinfo.gw, 192,168,1,1); + // IP4_ADDR(&IPinfo.netmask, 255,255,255,0); + // tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &IPinfo); Err = esp_wifi_set_config(ESP_IF_WIFI_AP, &WIFI_Config); if(Err!=ESP_OK) return Err; Err = esp_wifi_set_mode(WIFI_MODE_AP); if(Err!=ESP_OK) return Err; Err = esp_wifi_start(); diff --git a/utils/ognconv.cpp b/utils/ognconv.cpp index 32b3457..33cf913 100644 --- a/utils/ognconv.cpp +++ b/utils/ognconv.cpp @@ -1,15 +1,13 @@ #include -#include #include -#include #include "format.h" #include "ognconv.h" // ============================================================================================== -uint32_t FeetToMeters(uint32_t Altitude) { return (Altitude*312+512)>>10; } // [feet] => [m] -uint32_t MetersToFeet(uint32_t Altitude) { return (Altitude*3360+512)>>10; } // [m] => [feet] +int32_t FeetToMeters(int32_t Altitude) { return (Altitude*312+512)>>10; } // [feet] => [m] +int32_t MetersToFeet(int32_t Altitude) { return (Altitude*3360+512)>>10; } // [m] => [feet] // ============================================================================================== @@ -293,14 +291,15 @@ int APRS2IGC(char *Out, const char *Inp, int GeoidSepar) // convert Out[Len++] = 'A'; memcpy(Out+Len, " ", 10); const char *FL = strstr(Pos+18, " FL"); - if(FL) // pressure altitude - { float PressAlt=atof(FL+3); PressAlt*=30.4; int32_t Alt=floor(PressAlt+0.5); + int32_t AltH=0; int32_t AltL=0; + if(FL && FL[6]=='.' && Read_Int(AltH, FL+3)==3 && Read_Int(AltL, FL+7)==2) // pressure altitude + { int Alt = AltH*100+AltL; Alt=FeetToMeters(Alt); if(Alt<0) { Alt = (-Alt); Out[Len] = '-'; Format_UnsDec(Out+Len+1, (uint32_t)Alt, 4); } else { Format_UnsDec(Out+Len, (uint32_t)Alt, 5); } } - Len+=5; - if(Pos[27]=='A' && Pos[28]=='=') // geometrical altitude - { int32_t Alt=atol(Pos+29); Alt=(Alt*3+5)/10; Alt+=GeoidSepar; // convert to meters and add GeoidSepar for HAE + Len+=5; int32_t Alt=0; + if(Pos[27]=='A' && Pos[28]=='=' && Read_Int(Alt, Pos+29)==6) // geometrical altitude + { Alt=FeetToMeters(Alt); Alt+=GeoidSepar; // convert to meters and add GeoidSepar for HAE if(Alt<0) { Alt = (-Alt); Out[Len] = '-'; Format_UnsDec(Out+Len+1, (uint32_t)Alt, 4); } else { Format_UnsDec(Out+Len, (uint32_t)Alt, 5); } } diff --git a/utils/ognconv.h b/utils/ognconv.h index 4883a80..5854e96 100644 --- a/utils/ognconv.h +++ b/utils/ognconv.h @@ -3,8 +3,8 @@ #include -uint32_t FeetToMeters(uint32_t Altitude); // -uint32_t MetersToFeet(uint32_t Altitude); // +int32_t FeetToMeters(int32_t Altitude); // +int32_t MetersToFeet(int32_t Altitude); // uint16_t EncodeUR2V8(uint16_t Value); // Encode unsigned 12bit (0..3832) as 10bit uint16_t DecodeUR2V8(uint16_t Value); // Decode 10bit 0..0x3FF