diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino old mode 100755 new mode 100644 index 487a018..cf0eb32 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -59,7 +59,19 @@ WiFiClient client; #define SONDEHUB_MOBILE_STATION_UPDATE_TIME (30*1000) // 30 sec WiFiClient shclient; // Sondehub v2 unsigned long time_last_update = 0; +/* SH_LOC_OFF: never send position information to SondeHub + SH_LOC_FIXED: send fixed position (if specified in config) or GPS position (if there is a GPS fix) as fixed station position (no chase mode) to sondehub + SH_LOC_CHASE: always activate chase mode and send GPS position (if available) + SH_LOC_AUTO: if there is no valid GPS position, or GPS position < MIN_LOC_AUTO_DIST away from known fixed position: use FIXED mode + otherwise, i.e. if there is a valid GPS position and (either no fixed position in config, or GPS position is far away from fixed position), use CHASE mode. +*/ +enum { SH_LOC_OFF, SH_LOC_FIXED, SH_LOC_CHASE, SH_LOC_AUTO }; +/* auto mode is chase if valid GPS position and (no fixed location entered OR valid GPS position and distance in lat/lon deg to fixed location > threshold) */ +#define MIN_LOC_AUTO_DIST 200 /* meter */ +#define SH_LOC_AUTO_IS_CHASE ( gpsPos.valid && ( (isnan(sonde.config.sondehub.lat) || isnan(sonde.config.sondehub.lon) ) || \ + calcLatLonDist( gpsPos.lat, gpsPos.lon, sonde.config.sondehub.lat, sonde.config.sondehub.lon ) > MIN_LOC_AUTO_DIST ) ) #endif +extern float calcLatLonDist(float lat1, float lon1, float lat2, float lon2); // KISS over TCP for communicating with APRSdroid WiFiServer tncserver(14580); @@ -418,14 +430,14 @@ const char *createSondeHubMap() { HTMLBODY(ptr, "map.html"); if (!sonde.config.sondehub.active) { strcat(ptr, "
NOTE: SondeHub uploading is not enabled, detected sonde will not be visable on map
"); - if ((*s->ser == 0) && (sonde.config.sondehub.lat[0] != '\0')) { - sprintf(ptr + strlen(ptr), "", sonde.config.sondehub.lat, sonde.config.sondehub.lon); + if ((*s->ser == 0) && ( !isnan(sonde.config.sondehub.lat))) { + sprintf(ptr + strlen(ptr), "", sonde.config.sondehub.lat, sonde.config.sondehub.lon); } else { sprintf(ptr + strlen(ptr), "", s-> ser); } } else { - if ((*s->ser == 0) && (sonde.config.sondehub.lat[0] != '\0')) { - sprintf(ptr, "", sonde.config.sondehub.lat, sonde.config.sondehub.lon); + if ((*s->ser == 0) && (!isnan(sonde.config.sondehub.lat))) { + sprintf(ptr, "", sonde.config.sondehub.lat, sonde.config.sondehub.lon); } else { sprintf(ptr, "", s-> ser); } @@ -537,7 +549,7 @@ const char *createLiveJson() { long lat = nmea.getLatitude(); long lon = nmea.getLongitude(); long alt = -1; - bool b = nmea.getAltitude(alt); + /*bool b = */nmea.getAltitude(alt); bool valid = nmea.isValid(); uint8_t hdop = nmea.getHDOP(); if (valid) { @@ -656,12 +668,12 @@ struct st_configitems config_list[] = { #if FEATURE_SONDEHUB /* SondeHub settings */ {"", "SondeHub settings", -5, NULL}, - {"sondehub.active", "SondeHub reporting active (0=disabled, 1=active)", 0, &sonde.config.sondehub.active}, - {"sondehub.chase", "SondeHub chase location active (0=fixed location, 1=GPS mobile station)", 0, &sonde.config.sondehub.chase}, + {"sondehub.active", "SondeHub reporting (0=disabled, 1=active)", 0, &sonde.config.sondehub.active}, + {"sondehub.chase", "SondeHub location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)", 0, &sonde.config.sondehub.chase}, {"sondehub.host", "SondeHub host (DO NOT CHANGE)", 63, &sonde.config.sondehub.host}, {"sondehub.callsign", "Callsign", 63, &sonde.config.sondehub.callsign}, - {"sondehub.lat", "Latitude (optional, required to show station on SondeHub Tracker)", 19, &sonde.config.sondehub.lat}, - {"sondehub.lon", "Longitude (optional, required to show station on SondeHub Tracker)", 19, &sonde.config.sondehub.lon}, + {"sondehub.lat", "Latitude (optional, required to show station on SondeHub Tracker)", -7, &sonde.config.sondehub.lat}, + {"sondehub.lon", "Longitude (optional, required to show station on SondeHub Tracker)", -7, &sonde.config.sondehub.lon}, {"sondehub.alt", "Altitude (optional, visible on SondeHub tracker)", 19, &sonde.config.sondehub.alt}, {"sondehub.antenna", "Antenna (optional, visisble on SondeHub tracker)", 63, &sonde.config.sondehub.antenna}, {"sondehub.email", "SondeHub email (optional, only used to contact in case of upload errors)", 63, &sonde.config.sondehub.email}, @@ -677,6 +689,10 @@ void addConfigNumEntry(char *ptr, int idx, const char *label, int *value) { sprintf(ptr + strlen(ptr), "%s\n", label, idx, *value); } +void addConfigDblEntry(char *ptr, int idx, const char *label, double *value) { + sprintf(ptr + strlen(ptr), "%s\n", + label, idx, *value); +} void addConfigButtonEntry(char *ptr, int idx, const char *label, int *value) { int v = *value, ck = 0; if (v == 255) v = -1; @@ -751,6 +767,9 @@ const char *createConfigForm() { case -4: addConfigButtonEntry(ptr, i, config_list[i].label, (int *)config_list[i].data); break; + case -7: /* double for lat/lon */ + addConfigDblEntry(ptr, i, config_list[i].label, (double *)config_list[i].data); + break; default: addConfigStringEntry(ptr, i, config_list[i].label, config_list[i].type, (char *)config_list[i].data); break; @@ -1043,9 +1062,9 @@ const char *createUpdateForm(boolean run) { if (run) { strcat(ptr, "

Doing update, wait until reboot

"); } else { - sprintf(ptr+strlen(ptr), "

Currently installed: %s-%c%d

\n", version_id, SPIFFS_MAJOR+'A'-1, SPIFFS_MINOR); + sprintf(ptr + strlen(ptr), "

Currently installed: %s-%c%d

\n", version_id, SPIFFS_MAJOR + 'A' - 1, SPIFFS_MINOR); strcat(ptr, "

Available master::
" - "Available devel:

"); + "Available devel:

"); strcat(ptr, "
"); strcat(ptr, "

Note: If suffix is the same, update should work fully. If the number is different, update contains changes in the file system. A full re-flash is required to get all new features, but the update should not break anything. If the letter is different, a full re-flash is mandatory, update will not work

"); } @@ -2481,8 +2500,8 @@ void enableNetwork(bool enable) { #endif #if FEATURE_SONDEHUB if (sonde.config.sondehub.active && wifi_state != WIFI_APMODE) { + time_last_update = millis() + 1000; /* force sending update */ sondehub_station_update(&shclient, &sonde.config.sondehub); - time_last_update = millis(); } #endif configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); @@ -3040,17 +3059,8 @@ void loop() { #if FEATURE_SONDEHUB if (sonde.config.sondehub.active) { - unsigned long time_now = millis(); - // time_delta will be correct, even if time_now overflows - unsigned long time_delta = time_now - time_last_update; - if ((sonde.config.sondehub.chase == 0) && (time_delta >= SONDEHUB_STATION_UPDATE_TIME) && (wifi_state != WIFI_APMODE)) { // 60 min - sondehub_station_update(&shclient, &sonde.config.sondehub); - time_last_update = time_now; - } - else if ((sonde.config.sondehub.chase == 1) && (time_delta >= SONDEHUB_MOBILE_STATION_UPDATE_TIME) && (wifi_state != WIFI_APMODE)) { // 30 sec - sondehub_station_update(&shclient, &sonde.config.sondehub); - time_last_update = time_now; - } + // interval check moved to sondehub_station_update to avoid having to calculate distance in auto mode twice + sondehub_station_update(&shclient, &sonde.config.sondehub); } #endif } @@ -3060,12 +3070,33 @@ void loop() { /* Update station data to the sondehub v2 DB */ +/* which_pos: 0=none, 1=fixed, 2=gps */ void sondehub_station_update(WiFiClient *client, struct st_sondehub *conf) { #define STATION_DATA_LEN 300 char data[STATION_DATA_LEN]; char *w; + // If there is no connection to some WiFi AP, we cannot upload any data at all.... + if ( wifi_state != WIFI_CONNECTED ) return; + + unsigned long time_now = millis(); + // time_delta will be correct, even if time_now overflows + unsigned long time_delta = time_now - time_last_update; + + int chase = conf->chase; + // automatically decided if CHASE or FIXED mode is used (for config AUTO) + if (chase == SH_LOC_AUTO) { + if (SH_LOC_AUTO_IS_CHASE) chase = SH_LOC_CHASE; else chase = SH_LOC_FIXED; + } + + // Use 30sec update time in chase mode, 60 min in station mode. + unsigned long update_time = (chase == SH_LOC_CHASE) ? SONDEHUB_MOBILE_STATION_UPDATE_TIME : SONDEHUB_STATION_UPDATE_TIME; + + // If it is not yet time to send another update. do nothing.... + if ( (time_delta <= update_time) ) return; + Serial.println("sondehub_station_update()"); + time_last_update = time_now; if (!client->connected()) { if (!client->connect(conf->host, 80)) { @@ -3075,7 +3106,7 @@ void sondehub_station_update(WiFiClient *client, struct st_sondehub *conf) { } w = data; - memset(w, 0, STATION_DATA_LEN); + // not necessary... memset(w, 0, STATION_DATA_LEN); sprintf(w, "{" @@ -3085,31 +3116,35 @@ void sondehub_station_update(WiFiClient *client, struct st_sondehub *conf) { "\"uploader_contact_email\": \"%s\",", version_name, version_id, conf->callsign, conf->email); w += strlen(w); - if ((conf->chase == 0) && (conf->lat[0] != '\0') && (conf->lon[0] != '\0')) { - if (conf->alt[0] != '\0') { + + // We send GPS position: (a) in CHASE mode, (b) in FIXED mode if no fixed location has been specified in config + if (chase == SH_LOC_CHASE || (chase == SH_LOC_FIXED && (isnan(conf->lat) || isnan(conf->lon)) ) ) { + if (gpsPos.valid && gpsPos.lat != 0 && gpsPos.lon != 0) { sprintf(w, - "\"uploader_position\": [%s,%s,%s]," - "\"uploader_antenna\": \"%s\"" + "\"uploader_position\": [%.6f,%.6f,%d]," + "\"uploader_antenna\": \"%s\"," + "\"mobile\": true" "}", - conf->lat, conf->lon, conf->alt, conf->antenna); - } else { - sprintf(w, - "\"uploader_position\": [%s,%s,null]," - "\"uploader_antenna\": \"%s\"" - "}", - conf->lat, conf->lon, conf->antenna); + gpsPos.lat, gpsPos.lon, gpsPos.alt, conf->antenna); } } - else if (gpsPos.valid && gpsPos.lat != 0 && gpsPos.lon != 0) { - sprintf(w, - "\"uploader_position\": [%.6f,%.6f,%d]," - "\"uploader_antenna\": \"%s\"," - "\"mobile\": true" - "}", - gpsPos.lat, gpsPos.lon, gpsPos.alt, conf->antenna); + // Otherweise, in FIXED mode we send the fixed position from config (if specified) + else if (chase == SH_LOC_FIXED) { + if ((!isnan(conf->lat)) && (!isnan(conf->lon))) { + sprintf(w, + "\"uploader_position\": [%.6f,%.6f,%s]," + "\"uploader_antenna\": \"%s\"" + "}", + conf->lat, conf->lon, conf->alt[0] ? conf->alt : "null", conf->antenna); + } } else { - return; + // otherwise (in SH_LOC_NONE mode) we dont include any position info + sprintf(w, + "\"uploader_position\": [null,null,null]," + "\"uploader_antenna\": \"%s\"" + "}", + conf->antenna); } client->println("PUT /listeners HTTP/1.1"); @@ -3127,7 +3162,7 @@ void sondehub_station_update(WiFiClient *client, struct st_sondehub *conf) { String response = client->readString(); Serial.println(response); Serial.println("Response done..."); - //client->stop();r + //client->stop(); } /* @@ -3153,7 +3188,7 @@ const char *dfmSubtypeStrSH[16] = { NULL, NULL, NULL, NULL, NULL, NULL, // in hours.... max allowed diff UTC <-> sonde time #define SONDEHUB_TIME_THRESHOLD (3) -void sondehub_send_data(WiFiClient *client, SondeInfo *s, struct st_sondehub *conf) { +void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * conf) { Serial.println("sondehub_send_data()"); Serial.printf("shState = %d\n", shState); @@ -3254,7 +3289,7 @@ void sondehub_send_data(WiFiClient *client, SondeInfo *s, struct st_sondehub *co (float)s->dir, -((float)s->rssi / 2) ); w += strlen(w); - + if (s->type != STYPE_M20) { sprintf(w, "\"sats\": %d,", (int)s->sats); w += strlen(w); @@ -3296,17 +3331,17 @@ void sondehub_send_data(WiFiClient *client, SondeInfo *s, struct st_sondehub *co w += strlen(w); } - if ((conf->chase == 0) && (conf->lat[0] != '\0') && (conf->lon[0] != '\0')) { + if ((conf->chase == 0) && (!isnan(conf->lat)) && (!isnan(conf->lon))) { if (conf->alt[0] != '\0') { sprintf(w, - "\"uploader_position\": [%s,%s,%s]," + "\"uploader_position\": [%.6f,%.6f,%s]," "\"uploader_antenna\": \"%s\"" "}", conf->lat, conf->lon, conf->alt, conf->antenna ); } else { sprintf(w, - "\"uploader_position\": [%s,%s,null]," + "\"uploader_position\": [%.6f,%.6f,null]," "\"uploader_antenna\": \"%s\"" "}", conf->lat, conf->lon, conf->antenna @@ -3347,7 +3382,7 @@ void sondehub_send_data(WiFiClient *client, SondeInfo *s, struct st_sondehub *co //Serial.println(response); } -void sondehub_finish_data(WiFiClient *client, SondeInfo *s, struct st_sondehub *conf) { +void sondehub_finish_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * conf) { // If there is an "old" pending collection of JSON data sets, send it even if no now data is received if (shState == SH_CONN_APPENDING) { time_t now; @@ -3360,7 +3395,7 @@ void sondehub_finish_data(WiFiClient *client, SondeInfo *s, struct st_sondehub * } } -void sondehub_send_header(WiFiClient *client, SondeInfo *s, struct st_sondehub *conf) { +void sondehub_send_header(WiFiClient * client, SondeInfo * s, struct st_sondehub * conf) { Serial.print("PUT /sondes/telemetry HTTP/1.1\r\n" "Host: "); Serial.println(conf->host); @@ -3374,7 +3409,7 @@ void sondehub_send_header(WiFiClient *client, SondeInfo *s, struct st_sondehub * "Content-Type: application/json\r\n" "Transfer-Encoding: chunked\r\n"); } -void sondehub_send_next(WiFiClient *client, SondeInfo *s, struct st_sondehub *conf, char *chunk, int chunklen, int first) { +void sondehub_send_next(WiFiClient * client, SondeInfo * s, struct st_sondehub * conf, char *chunk, int chunklen, int first) { // send next chunk of JSON request client->printf("%x\r\n", chunklen + 1); client->write(first ? "[" : ",", 1); @@ -3386,7 +3421,7 @@ void sondehub_send_next(WiFiClient *client, SondeInfo *s, struct st_sondehub *co Serial.write(chunk, chunklen); Serial.print("\r\n"); } -void sondehub_send_last(WiFiClient *client, SondeInfo *s, struct st_sondehub *conf) { +void sondehub_send_last(WiFiClient * client, SondeInfo * s, struct st_sondehub * conf) { // last chunk. just the closing "]" of the json request client->printf("1\r\n]\r\n0\r\n\r\n"); Serial.printf("1\r\n]\r\n0\r\n\r\n"); diff --git a/RX_FSK/version.h b/RX_FSK/version.h index 16d547d..1517fde 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,4 +1,4 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20210809"; +const char *version_id = "devel20210810"; const int SPIFFS_MAJOR=2; const int SPIFFS_MINOR=14; diff --git a/libraries/SondeLib/Display.cpp b/libraries/SondeLib/Display.cpp index 35a9caa..deaabc9 100644 --- a/libraries/SondeLib/Display.cpp +++ b/libraries/SondeLib/Display.cpp @@ -1307,6 +1307,15 @@ void Display::drawKilltimer(DispEntry *de) { #define FAKEGPS 0 extern int lastCourse; // from RX_FSK.ino + + +float calcLatLonDist(float lat1, float lon1, float lat2, float lon2) { + float x = radians(lon1-lon2) * cos( radians((lat1+lat2)/2) ); + float y = radians(lat2-lat1); + float d = sqrt(x*x+y*y)*EARTH_RADIUS; + return d; +} + void Display::calcGPS() { // base data #if 0 @@ -1338,12 +1347,7 @@ static int tmpc=0; #endif // distance if( gpsPos.valid && (sonde.si()->validPos&0x03)==0x03 && (layout->usegps&GPSUSE_DIST)) { - float lat1 = gpsPos.lat; - float lat2 = sonde.si()->lat; - float x = radians(gpsPos.lon-sonde.si()->lon) * cos( radians((lat1+lat2)/2) ); - float y = radians(lat2-lat1); - float d = sqrt(x*x+y*y)*EARTH_RADIUS; - gpsDist = (int)d; + gpsDist = (int)calcLatLonDist(gpsPos.lat, gpsPos.lon, sonde.si()->lat, sonde.si()->lon); } else { gpsDist = -1; } diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index cdfc554..d8d0df5 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -380,9 +380,11 @@ void Sonde::setConfig(const char *cfg) { } else if(strcmp(cfg, "sondehub.callsign")==0) { strncpy(config.sondehub.callsign, val, 63); } else if(strcmp(cfg, "sondehub.lat")==0) { - strncpy(config.sondehub.lat, val, 19); + config.sondehub.lat = *val==0 ? NAN : atof(val); + Serial.printf("lat is %f\n", config.sondehub.lat); } else if(strcmp(cfg, "sondehub.lon")==0) { - strncpy(config.sondehub.lon, val, 19); + config.sondehub.lon = *val==0 ? NAN : atof(val); + Serial.printf("lon is %f\n", config.sondehub.lon); } else if(strcmp(cfg, "sondehub.alt")==0) { strncpy(config.sondehub.alt, val, 19); } else if(strcmp(cfg, "sondehub.antenna")==0) { diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index 022e6dc..89f13a9 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -187,8 +187,8 @@ struct st_sondehub { int chase; char host[64]; char callsign[64]; - char lat[20]; - char lon[20]; + double lat; + double lon; char alt[20]; char antenna[64]; char email[64];