automated fixed/chase mode for sondehub. also fix #130

pull/137/head
Hansi, dl9rdz 2021-08-11 00:29:29 +02:00
rodzic d07ef52d22
commit aeb3b1f333
5 zmienionych plików z 105 dodań i 64 usunięć

141
RX_FSK/RX_FSK.ino 100755 → 100644
Wyświetl plik

@ -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, "<div>NOTE: SondeHub uploading is not enabled, detected sonde will not be visable on map</div>");
if ((*s->ser == 0) && (sonde.config.sondehub.lat[0] != '\0')) {
sprintf(ptr + strlen(ptr), "<iframe src=\"https://sondehub.org/#!mc=%s,%s&mz=8\" style=\"border:1px solid #00A3D3;border-radius:20px;height:95vh\"></iframe>", sonde.config.sondehub.lat, sonde.config.sondehub.lon);
if ((*s->ser == 0) && ( !isnan(sonde.config.sondehub.lat))) {
sprintf(ptr + strlen(ptr), "<iframe src=\"https://sondehub.org/#!mc=%f,%f&mz=8\" style=\"border:1px solid #00A3D3;border-radius:20px;height:95vh\"></iframe>", sonde.config.sondehub.lat, sonde.config.sondehub.lon);
} else {
sprintf(ptr + strlen(ptr), "<iframe src=\"https://sondehub.org/%s\" style=\"border:1px solid #00A3D3;border-radius:20px;height:95vh\"></iframe>", s-> ser);
}
} else {
if ((*s->ser == 0) && (sonde.config.sondehub.lat[0] != '\0')) {
sprintf(ptr, "<iframe src=\"https://sondehub.org/#!mc=%s,%s&mz=8\" style=\"border:1px solid #00A3D3;border-radius:20px;height:98vh;width:100%%\"></iframe>", sonde.config.sondehub.lat, sonde.config.sondehub.lon);
if ((*s->ser == 0) && (!isnan(sonde.config.sondehub.lat))) {
sprintf(ptr, "<iframe src=\"https://sondehub.org/#!mc=%f,%f&mz=8\" style=\"border:1px solid #00A3D3;border-radius:20px;height:98vh;width:100%%\"></iframe>", sonde.config.sondehub.lat, sonde.config.sondehub.lon);
} else {
sprintf(ptr, "<iframe src=\"https://sondehub.org/%s\" style=\"border:1px solid #00A3D3;border-radius:20px;height:98vh;width:100%%\"></iframe>", 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), "<tr><td>%s</td><td><input name=\"CFG%d\" type=\"text\" value=\"%d\"/></td></tr>\n",
label, idx, *value);
}
void addConfigDblEntry(char *ptr, int idx, const char *label, double *value) {
sprintf(ptr + strlen(ptr), "<tr><td>%s</td><td><input name=\"CFG%d\" type=\"text\" value=\"%f\"/></td></tr>\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, "<p>Doing update, wait until reboot</p>");
} else {
sprintf(ptr+strlen(ptr), "<p>Currently installed: %s-%c%d</p>\n", version_id, SPIFFS_MAJOR+'A'-1, SPIFFS_MINOR);
sprintf(ptr + strlen(ptr), "<p>Currently installed: %s-%c%d</p>\n", version_id, SPIFFS_MAJOR + 'A' - 1, SPIFFS_MINOR);
strcat(ptr, "<p>Available master:: <iframe src=\"http://rdzsonde.mooo.com/master/update-info.html\" style=\"height:40px;width:400px\"></iframe><br>"
"Available devel: <iframe src=\"http://rdzsonde.mooo.com/devel/update-info.html\" style=\"height:40px;width:400px\"></iframe></p>");
"Available devel: <iframe src=\"http://rdzsonde.mooo.com/devel/update-info.html\" style=\"height:40px;width:400px\"></iframe></p>");
strcat(ptr, "<input type=\"submit\" name=\"master\" value=\"Master-Update\"></input><br><input type=\"submit\" name=\"devel\" value=\"Devel-Update\">");
strcat(ptr, "<br><p>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</p>");
}
@ -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");

Wyświetl plik

@ -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;

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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];