From 032d8452c658240ac5a921842fbe6898683b196c Mon Sep 17 00:00:00 2001 From: "Hansi, dl9rdz" Date: Wed, 22 Sep 2021 10:02:40 +0200 Subject: [PATCH 1/4] clear all decoded data on ID change, don't leave anything old behind --- RX_FSK/src/RS41.cpp | 13 +++++++------ RX_FSK/src/Sonde.cpp | 8 ++++++++ RX_FSK/src/Sonde.h | 40 ++++++++++++++++++++++++++-------------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/RX_FSK/src/RS41.cpp b/RX_FSK/src/RS41.cpp index c73ec7a..232f2a2 100644 --- a/RX_FSK/src/RS41.cpp +++ b/RX_FSK/src/RS41.cpp @@ -680,6 +680,12 @@ int RS41::decode41(byte *data, int maxlen) switch(typ) { case 'y': // name { + if(strncmp(si->id, (const char *)(data+p+2), 8)) { + // ID changed, i.e. new sonde on same frequency. clear calibration and all other data + sonde.clearAllData(si); + struct subframeBuffer *sub = (struct subframeBuffer *)si->extra; + if(sub) { sub->valid = 0; } + } Serial.print("#"); uint16_t fnr = data[p]+(data[p+1]<<8); Serial.print(fnr); @@ -687,13 +693,8 @@ int RS41::decode41(byte *data, int maxlen) Serial.print("; RS41 ID "); snprintf(buf, 10, "%.8s ", data+p+2); Serial.print(buf); - sonde.si()->batteryVoltage = data[p+10] / 10.0f; + si->batteryVoltage = data[p+10] / 10.0f; si->type=STYPE_RS41; - if(strncmp(si->id, (const char *)(data+p+2), 8)) { - // ID changed, i.e. new sonde on same frequency. clear calibration data - struct subframeBuffer *sub = (struct subframeBuffer *)si->extra; - if(sub) { sub->valid = 0; } - } strncpy(si->id, (const char *)(data+p+2), 8); si->id[8]=0; strncpy(si->ser, (const char *)(data+p+2), 8); diff --git a/RX_FSK/src/Sonde.cpp b/RX_FSK/src/Sonde.cpp index 56e0cfe..64a4c83 100644 --- a/RX_FSK/src/Sonde.cpp +++ b/RX_FSK/src/Sonde.cpp @@ -667,6 +667,14 @@ uint8_t Sonde::updateState(uint8_t event) { return 0xFF; } +void Sonde::clearAllData(SondeInfo *si) { + // set everything to 0 + memset(si->id, 0, offsetof(SondeInfo, extra)-offsetof(SondeInfo, id)); + // set floats to NaN + si->lat = si->lon = si->alt = si->vs = si->hs = si->dir = NAN; + si->temperature = si->temRHSensor = si->relativeHumidity = si->batteryVoltage = NAN; +} + void Sonde::updateDisplayPos() { disp.updateDisplayPos(); } diff --git a/RX_FSK/src/Sonde.h b/RX_FSK/src/Sonde.h index 1d1e556..7e5384f 100644 --- a/RX_FSK/src/Sonde.h +++ b/RX_FSK/src/Sonde.h @@ -14,7 +14,13 @@ extern uint8_t debug; // RX_TIMEOUT: no header detected // RX_ERROR: header detected, but data not decoded (crc error, etc.) -// RX_OK: header and data ok +// RX_PARTIAL: header detected, some data ok, some with errors +// For RS41: Some blocks with CRC error, some blocks ok in a single frame +// For DFM: In +- 1s, some but not all DAT-subframes 1,2,3,4,5,6,7,8 received +// For RS92 ??? unclear +// For M10/M20 its always all or nothing, no PARTIAL data +// For MP3H its alway all or nothing, no PARTIAL data +// RX_OK: header and all data ok enum RxResult { RX_OK, RX_TIMEOUT, RX_ERROR, RX_UNKNOWN, RX_NOPOS }; #define RX_UPDATERSSI 0xFFFE @@ -69,17 +75,32 @@ extern const char *manufacturer_string[NSondeTypes]; #define TYPE_IS_METEO(t) ( (t)==STYPE_M10 || (t)==STYPE_M20 ) typedef struct st_sondeinfo { + // First part: static configuration, not decoded data. // receiver configuration bool active; SondeType type; - int8_t subtype; /* 0 for none/unknown, hex type for dfm, 1/2 for M10/M20 */ float freq; + char launchsite[18]; + + // Second part: internal decoder state. no need to clear this on new sonde + // RSSI from receiver + int rssi; // signal strength + int32_t afc; // afc correction value + // statistics + uint8_t rxStat[20]; + uint32_t rxStart; // millis() timestamp of continuous rx start + uint32_t norxStart; // millis() timestamp of continuous no rx start + uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display + int8_t lastState; // -1: disabled; 0: norx; 1: rx + + // Third part: decoded data. Clear if reception of a new sonde has started // decoded ID - char typestr[5]; // decoded type (use type if *typestr==0) + // id must be the start of decoded data, extra indicates the end. char id[10]; char ser[12]; bool validID; - char launchsite[18]; + char typestr[5]; // decoded type (use type if *typestr==0) + int8_t subtype; /* 0 for none/unknown, hex type for dfm, 1/2 for M10/M20 */ // decoded position float lat; // latitude float lon; // longitude @@ -94,24 +115,15 @@ typedef struct st_sondeinfo { uint32_t frame; uint32_t vframe; // vframe==frame if frame is unique/continous, otherweise vframe is derived from gps time bool validTime; - // RSSI from receiver - int rssi; // signal strength - int32_t afc; // afc correction value - // statistics - uint8_t rxStat[20]; - uint32_t rxStart; // millis() timestamp of continuous rx start - uint32_t norxStart; // millis() timestamp of continuous no rx start - uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display - int8_t lastState; // -1: disabled; 0: norx; 1: rx // shut down timers, currently only for RS41; -1=disabled uint16_t launchKT, burstKT, countKT; uint16_t crefKT; // frame number in which countKT was last sent // sonde specific extra data, NULL if unused or not yet initialized, currently used for RS41 subframe data (calibration) - void *extra; float temperature = -300.0; // platinum resistor temperature float tempRHSensor = -300.0; // temperature of relative humidity sensor float relativeHumidity = -1.0; // relative humidity float batteryVoltage = -1; + void *extra; } SondeInfo; // rxStat: 3=undef[empty] 1=timeout[.] 2=errro[E] 0=ok[|] 4=no valid position[°] From 8ffaa8be63b305c3712a59eaab4ee963793dadbe Mon Sep 17 00:00:00 2001 From: "Hansi, dl9rdz" Date: Wed, 22 Sep 2021 10:03:22 +0200 Subject: [PATCH 2/4] temp, hum with 1 decimal digit for sondehub --- RX_FSK/RX_FSK.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 5dd29fa..90c8163 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -3718,13 +3718,13 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * // Only send temp if provided if ((int)s->temperature != 0) { - sprintf(w, "\"temp\": %.3f,", float(s->temperature)); + sprintf(w, "\"temp\": %.1f,", float(s->temperature)); w += strlen(w); } // Only send humidity if provided if ((int)s->relativeHumidity != 0) { - sprintf(w, "\"humidity\": %.3f,", float(s->relativeHumidity)); + sprintf(w, "\"humidity\": %.1f,", float(s->relativeHumidity)); w += strlen(w); } From ac05c9edbddd66dd404d277e5e0854d91674bd0e Mon Sep 17 00:00:00 2001 From: "Hansi, dl9rdz" Date: Wed, 22 Sep 2021 10:39:34 +0200 Subject: [PATCH 3/4] never remove currentSonde by ShImport --- RX_FSK/src/ShFreqImport.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RX_FSK/src/ShFreqImport.cpp b/RX_FSK/src/ShFreqImport.cpp index 87b12b0..9e45ff7 100644 --- a/RX_FSK/src/ShFreqImport.cpp +++ b/RX_FSK/src/ShFreqImport.cpp @@ -65,7 +65,7 @@ void ShFreqImport::populate(char *id, float lat, float lon, float freq, const ch // update label if its a dynamic SH entry int i; for(i=0; i>(i&7))&1) == 0) && *sonde.sondeList[i].launchsite=='@' ) { + // Don't remove the currently active entry + if(i==currentSonde) continue; Serial.printf("removing #%d\n", i); sonde.sondeList[i].launchsite[0] = 0; sonde.sondeList[i].active = 0; From b297a9a7c7addd27d8d366acec60bd72e28e9306 Mon Sep 17 00:00:00 2001 From: "Hansi, dl9rdz" Date: Wed, 22 Sep 2021 11:28:29 +0200 Subject: [PATCH 4/4] some internal reorg that should not break anything but make it easier later to decouple decoding from updating global data, solving part of issue 186 --- RX_FSK/RX_FSK.ino | 136 ++++++++++++++++++------------------ RX_FSK/src/Chasemapper.cpp | 18 ++--- RX_FSK/src/DFM.cpp | 24 ++++--- RX_FSK/src/Display.cpp | 60 ++++++++-------- RX_FSK/src/M10M20.cpp | 19 ++--- RX_FSK/src/MP3H.cpp | 15 ++-- RX_FSK/src/RS41.cpp | 14 ++-- RX_FSK/src/RS92.cpp | 2 +- RX_FSK/src/ShFreqImport.cpp | 2 +- RX_FSK/src/Sonde.cpp | 9 +-- RX_FSK/src/Sonde.h | 48 +++++++------ RX_FSK/src/aprs.cpp | 7 +- RX_FSK/src/mqtt.cpp | 23 +++--- 13 files changed, 197 insertions(+), 180 deletions(-) diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 90c8163..e55559f 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -436,16 +436,16 @@ 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) && ( !isnan(sonde.config.rxlat))) { + if ((*s->d.ser == 0) && ( !isnan(sonde.config.rxlat))) { sprintf(ptr + strlen(ptr), "", sonde.config.rxlat, sonde.config.rxlon); } else { - sprintf(ptr + strlen(ptr), "", s-> ser); + sprintf(ptr + strlen(ptr), "", s->d.ser); } } else { - if ((*s->ser == 0) && (!isnan(sonde.config.rxlat))) { + if ((*s->d.ser == 0) && (!isnan(sonde.config.rxlat))) { sprintf(ptr, "", sonde.config.rxlat, sonde.config.rxlon); } else { - sprintf(ptr, "", s-> ser); + sprintf(ptr, "", s->d.ser); } } HTMLBODYEND(ptr); @@ -497,24 +497,24 @@ void addSondeStatus(char *ptr, int i) SondeInfo *s = &sonde.sondeList[i]; strcat(ptr, ""); sprintf(ptr + strlen(ptr), "\n", s->lat, s->lon, s->alt); - const time_t t = s->time; + sprintf(ptr + strlen(ptr), "\n", s->d.lat, s->d.lon, s->d.alt); + const time_t t = s->d.time; ts = *gmtime(&t); sprintf(ptr + strlen(ptr), "", - s->frame, s->sats, ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec); + s->d.frame, s->d.sats, ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec); if (s->type == STYPE_RS41) { sprintf(ptr + strlen(ptr), "\n", - s->burstKT, s->launchKT, s->countKT, ((uint16_t)s->frame - s->crefKT)); + s->d.burstKT, s->d.launchKT, s->d.countKT, ((uint16_t)s->d.frame - s->d.crefKT)); } - sprintf(ptr + strlen(ptr), "", s->lat, s->lon); + sprintf(ptr + strlen(ptr), "", s->d.lat, s->d.lon); strcat(ptr, "
%3.3f MHz, Type: %s
ID: %s", s->freq, sondeTypeLongStr[s->type], - s->validID ? s->id : ""); - if (s->validID && (TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type) || s->type == STYPE_MP3H) ) { - sprintf(ptr + strlen(ptr), " (ser: %s)", s->ser); + s->d.validID ? s->d.id : ""); + if (s->d.validID && (TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type) || s->type == STYPE_MP3H) ) { + sprintf(ptr + strlen(ptr), " (ser: %s)", s->d.ser); } - sprintf(ptr + strlen(ptr), "
QTH: %.6f,%.6f h=%.0fm
QTH: %.6f,%.6f h=%.0fm
Frame# %u, Sats=%d, %04d-%02d-%02d %02d:%02d:%02d
Burst-KT=%d Launch-KT=%d Countdown=%d (vor %ds)
GEO-App - ", s->lat, s->lon); - sprintf(ptr + strlen(ptr), "radiosondy.info - ", s->id); - sprintf(ptr + strlen(ptr), "SondeHub Tracker - ", s->ser); - sprintf(ptr + strlen(ptr), "OSM - ", s->lat, s->lon); - sprintf(ptr + strlen(ptr), "Google
GEO-App - ", s->d.lat, s->d.lon); + sprintf(ptr + strlen(ptr), "radiosondy.info - ", s->d.id); + sprintf(ptr + strlen(ptr), "SondeHub Tracker - ", s->d.ser); + sprintf(ptr + strlen(ptr), "OSM - ", s->d.lat, s->d.lon); + sprintf(ptr + strlen(ptr), "Google

\n"); } @@ -542,7 +542,7 @@ const char *createLiveJson() { SondeInfo *s = &sonde.sondeList[sonde.currentSonde]; sprintf(ptr + strlen(ptr), "\"sonde\": {\"rssi\": %d, \"vframe\": %d, \"time\": %d,\"id\": \"%s\", \"freq\": %3.3f, \"type\": \"%s\"," "\"lat\": %.6f, \"lon\": %.6f, \"alt\": %.0f, \"speed\": %.1f, \"dir\": %.0f, \"climb\": %.1f, \"launchsite\": \"%s\", \"res\": %d }", - s->rssi, s->vframe, s->time, s->id, s->freq, sondeTypeStr[s->type], s->lat, s->lon, s->alt, s->hs, s->dir, s->vs, s->launchsite, s->rxStat[0]); + s->rssi, s->d.vframe, s->d.time, s->d.id, s->freq, sondeTypeStr[s->type], s->d.lat, s->d.lon, s->d.alt, s->d.hs, s->d.dir, s->d.vs, s->launchsite, s->rxStat[0]); if (gpsPos.valid) { #if 0 @@ -1295,15 +1295,15 @@ void addSondeStatusKML(char *ptr, int i) { SondeInfo *s = &sonde.sondeList[i]; - if (!s->validID) + if (!s->d.validID) { return; } sprintf(ptr + strlen(ptr), "%sabsolute%.6f,%.6f,%.0f%3.3f MHz, Type: %s, h=%.0fm", - s->id, s->id, - s->lon, s->lat, s->alt, - s->freq, sondeTypeStr[s->type], s->alt); + s->d.id, s->d.id, + s->d.lon, s->d.lat, s->d.alt, + s->freq, sondeTypeStr[s->type], s->d.alt); } const char *createKMLDynamic() { @@ -1333,8 +1333,8 @@ const char *sendGPX(AsyncWebServerRequest * request) { return "ERROR"; } SondeInfo *si = &sonde.sondeList[index]; - strcpy(si->id, "test"); - si->lat = 48; si->lon = 11; si->alt = 500; + strcpy(si->d.id, "test"); + si->d.lat = 48; si->d.lon = 11; si->d.alt = 500; snprintf(ptr, 10240, "\n" "rdzTTGOsonde\n" "\n" "\n %f\n %s\n Radio BeaconSonde\n" - "\n", index, si->id, si->lat, si->lon, si->alt, si->id); + "\n", index, si->d.id, si->d.lat, si->d.lon, si->d.alt, si->d.id); Serial.println(message); return message; } @@ -2504,7 +2504,7 @@ void loopDecoder() { //Send a packet with position information // first check if ID and position lat+lonis ok - if (s->validID && ((s->validPos & 0x03) == 0x03)) { + if (s->d.validID && ((s->d.validPos & 0x03) == 0x03)) { const char *str = aprs_senddata(s, sonde.config.call, sonde.config.udpfeed.symbol); if (connected) { char raw[201]; @@ -2551,7 +2551,7 @@ void loopDecoder() { Serial.println("Sending position via TCP as rdzJSON"); char raw[1024]; char gps[128]; - const char *typestr = s->typestr; + const char *typestr = s->d.typestr; if (*typestr == 0) typestr = sondeTypeStr[s->type]; // TODO: only if GPS is valid... if (gpsPos.valid) { @@ -2597,27 +2597,27 @@ void loopDecoder() { typestr, (int)s->active, s->freq, - s->id, - s->ser, - (int)s->validID, + s->d.id, + s->d.ser, + (int)s->d.validID, s->launchsite, - s->lat, - s->lon, - s->alt, - s->vs, - s->hs, - s->dir, - s->sats, - s->validPos, - s->time, - s->frame, - (int)s->validTime, + s->d.lat, + s->d.lon, + s->d.alt, + s->d.vs, + s->d.hs, + s->d.dir, + s->d.sats, + s->d.validPos, + s->d.time, + s->d.frame, + (int)s->d.validTime, s->rssi, s->afc, - s->launchKT, - s->burstKT, - s->countKT, - s->crefKT, + s->d.launchKT, + s->d.burstKT, + s->d.countKT, + s->d.crefKT, gps ); //Serial.println("Writing rdzclient..."); @@ -3603,12 +3603,12 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * uint8_t realtype = s->type; // config setting M10 and M20 will both decode both types, so use the real type that was decoded if (TYPE_IS_METEO(realtype)) { - realtype = s->subtype == 1 ? STYPE_M10 : STYPE_M20; + realtype = s->d.subtype == 1 ? STYPE_M10 : STYPE_M20; } - // For DFM, s->time is data from subframe DAT8 (gps date/hh/mm), and sec is from DAT1 (gps sec/usec) + // For DFM, s->d.time is data from subframe DAT8 (gps date/hh/mm), and sec is from DAT1 (gps sec/usec) // For all others, sec should always be 0 and time the exact time in seconds - time_t t = s->time; + time_t t = s->d.time; int chase = conf->chase; // automatically decided if CHASE or FIXED mode is used (for config AUTO) @@ -3627,11 +3627,11 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * } // Check if current sonde data is valid. If not, don't do anything.... - if (*s->ser == 0) return; // Don't send anything without serial number - if (((int)s->lat == 0) && ((int)s->lon == 0)) return; // Sometimes these values are zeroes. Don't send those to the sondehub - if ((int)s->alt > 50000) return; // If alt is too high don't send to SondeHub + if (*s->d.ser == 0) return; // Don't send anything without serial number + if (((int)s->d.lat == 0) && ((int)s->d.lon == 0)) return; // Sometimes these values are zeroes. Don't send those to the sondehub + if ((int)s->d.alt > 50000) return; // If alt is too high don't send to SondeHub // M20 data does not include #sat information - if ( realtype != STYPE_M20 && (int)s->sats < 4) return; // If not enough sats don't send to SondeHub + if ( realtype != STYPE_M20 && (int)s->d.sats < 4) return; // If not enough sats don't send to SondeHub // If not connected to sondehub, try reconnecting. // TODO: do this outside of main loop @@ -3651,8 +3651,8 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * return; } - if ( abs(now - (time_t)s->time) > (3600 * SONDEHUB_TIME_THRESHOLD) ) { - Serial.printf("Sonde time %d too far from current UTC time %ld", s->time, now); + if ( abs(now - (time_t)s->d.time) > (3600 * SONDEHUB_TIME_THRESHOLD) ) { + Serial.printf("Sonde time %d too far from current UTC time %ld", s->d.time, now); return; } @@ -3688,25 +3688,25 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * "\"type\": \"%s\",", version_name, version_id, conf->callsign, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, - manufacturer_string[realtype], s->ser, + manufacturer_string[realtype], s->d.ser, ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, - (float)s->lat, (float)s->lon, (float)s->alt, (float)s->freq, (float)s->hs, (float)s->vs, - (float)s->dir, -((float)s->rssi / 2), s->vframe, sondeTypeStrSH[realtype] + (float)s->d.lat, (float)s->d.lon, (float)s->d.alt, (float)s->freq, (float)s->d.hs, (float)s->d.vs, + (float)s->d.dir, -((float)s->rssi / 2), s->d.vframe, sondeTypeStrSH[realtype] ); w += strlen(w); // Only send sats if not M20 if (realtype != STYPE_M20) { - sprintf(w, "\"sats\": %d,", (int)s->sats); + sprintf(w, "\"sats\": %d,", (int)s->d.sats); w += strlen(w); } /* if there is a subtype (DFM only) */ - if ( TYPE_IS_DFM(s->type) && s->subtype > 0 && s->subtype < 16 ) { - const char *t = dfmSubtypeStrSH[s->subtype]; + if ( TYPE_IS_DFM(s->type) && s->d.subtype > 0 && s->d.subtype < 16 ) { + const char *t = dfmSubtypeStrSH[s->d.subtype]; // as in https://github.com/projecthorus/radiosonde_auto_rx/blob/e680221f69a568e1fdb24e76db679233f32cb027/auto_rx/autorx/sonde_specific.py#L84 if (t) sprintf(w, "\"subtype\": \"%s\",", t); - else sprintf(w, "\"subtype\": \"DFMx%X\",", s->subtype); // Unknown subtype + else sprintf(w, "\"subtype\": \"DFMx%X\",", s->d.subtype); // Unknown subtype w += strlen(w); } else if ( s->type == STYPE_RS41 ) { char buf[11]; @@ -3717,26 +3717,26 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub * } // Only send temp if provided - if ((int)s->temperature != 0) { - sprintf(w, "\"temp\": %.1f,", float(s->temperature)); + if ((int)s->d.temperature != 0) { + sprintf(w, "\"temp\": %.1f,", float(s->d.temperature)); w += strlen(w); } // Only send humidity if provided - if ((int)s->relativeHumidity != 0) { - sprintf(w, "\"humidity\": %.1f,", float(s->relativeHumidity)); + if ((int)s->d.relativeHumidity != 0) { + sprintf(w, "\"humidity\": %.1f,", float(s->d.relativeHumidity)); w += strlen(w); } // Only send burst timer if RS41 and fresh within the last 51s - if ((realtype == STYPE_RS41) && (s->crefKT > 0) && (s->vframe - s->crefKT < 51)) { - sprintf(w, "\"burst_timer\": %d,", (int)s->countKT); + if ((realtype == STYPE_RS41) && (s->d.crefKT > 0) && (s->d.vframe - s->d.crefKT < 51)) { + sprintf(w, "\"burst_timer\": %d,", (int)s->d.countKT); w += strlen(w); } // Only send battery if provided - if (s->batteryVoltage > 0) { - sprintf(w, "\"batt\": %.2f,", s->batteryVoltage); + if (s->d.batteryVoltage > 0) { + sprintf(w, "\"batt\": %.2f,", s->d.batteryVoltage); w += strlen(w); } diff --git a/RX_FSK/src/Chasemapper.cpp b/RX_FSK/src/Chasemapper.cpp index 6c98de9..6d8366e 100644 --- a/RX_FSK/src/Chasemapper.cpp +++ b/RX_FSK/src/Chasemapper.cpp @@ -5,11 +5,11 @@ extern const char *sondeTypeStrSH[]; int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) { char buf[1024]; struct tm tim; - time_t t = si->time; + time_t t = si->d.time; gmtime_r(&t, &tim); uint8_t realtype = si->type; if (TYPE_IS_METEO(realtype)) { - realtype = si->subtype == 1 ? STYPE_M10 : STYPE_M20; + realtype = si->d.subtype == 1 ? STYPE_M10 : STYPE_M20; } sprintf(buf, "{ \"type\": \"PAYLOAD_SUMMARY\"," "\"callsign\": \"%s\"," @@ -22,16 +22,16 @@ int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) { "\"model\": \"%s\"," "\"freq\": \"%.3f MHz\"," "\"temp\": %g }", - si->ser, - si->lat, - si->lon, - (int)si->alt, - (int)(si->hs * 1.9438445), // m/s into knots - (int)si->dir, + si->d.ser, + si->d.lat, + si->d.lon, + (int)si->d.alt, + (int)(si->d.hs * 1.9438445), // m/s into knots + (int)si->d.dir, tim.tm_hour, tim.tm_min, tim.tm_sec, sondeTypeStrSH[realtype], si->freq, - si->temperature); + si->d.temperature); Serial.printf("Sending chasemapper json: %s\n", buf); udp.beginPacket(sonde.config.cm.host, sonde.config.cm.port); udp.write((const uint8_t *)buf, strlen(buf)); diff --git a/RX_FSK/src/DFM.cpp b/RX_FSK/src/DFM.cpp index 12fcc46..613781a 100644 --- a/RX_FSK/src/DFM.cpp +++ b/RX_FSK/src/DFM.cpp @@ -209,6 +209,7 @@ void DFM::finddfname(uint8_t *b) uint32_t i; uint8_t ix; uint16_t d; + SondeData *sd = &(sonde.si()->d); st = b[0]; /* frame start byte */ ix = b[3]; /* hi/lo part of ser; (LSB due to our bitsToBytes...) */ @@ -242,10 +243,10 @@ void DFM::finddfname(uint8_t *b) chkid >>= 4; } if(i==6) { - snprintf(sonde.si()->id, 10, "D%x ", id); - sonde.si()->validID = true; - sonde.si()->subtype = (st>>4)&0x0F; - strncpy(sonde.si()->typestr, typestr[ (st>>4)&0x0F ], 5); + snprintf(sd->id, 10, "D%x ", id); + sd->validID = true; + sd->subtype = (st>>4)&0x0F; + strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5); return; } dfmstate.lastfrcnt = 0; @@ -291,12 +292,12 @@ void DFM::finddfname(uint8_t *b) dfmstate.idcnt1 = dfmstate.cnt[2*i+1]; dfmstate.nameregok = i; // generate id..... - snprintf(sonde.si()->id, 10, "D%d", ((dfmstate.dat[2*i]<<16)|dfmstate.dat[2*i+1])%100000000); + snprintf(sd->id, 10, "D%d", ((dfmstate.dat[2*i]<<16)|dfmstate.dat[2*i+1])%100000000); Serial.print("\nNEW AUTOID:"); - Serial.println(sonde.si()->id); - sonde.si()->validID = true; - sonde.si()->subtype = (st>>4)&0x0F; - strncpy(sonde.si()->typestr, typestr[ (st>>4)&0x0F ], 5); + Serial.println(sd->id); + sd->validID = true; + sd->subtype = (st>>4)&0x0F; + strncpy(sd->typestr, typestr[ (st>>4)&0x0F ], 5); } if(dfmstate.nameregok==i) { Serial.print(" ID OK"); @@ -327,7 +328,7 @@ void DFM::decodeCFG(uint8_t *cfg) // new ID finddfname(cfg); // new aprs ID (dxlaprs, autorx) is now "D" + serial (8 digits) by consensus - memcpy(sonde.si()->ser, sonde.si()->id+1, 9); + memcpy(sonde.si()->d.ser, sonde.si()->d.id+1, 9); } static int bitCount(int x) { @@ -342,7 +343,8 @@ uint16_t MON[]={0,0,31,59,90,120,151,181,212,243,273,304,334}; void DFM::decodeDAT(uint8_t *dat) { - SondeInfo *si = sonde.si(); + // TODO: Here we need to work on a shadow copy of SondeData in order to prevent concurrent changes while using data in main loop + SondeData *si = &(sonde.si()->d); Serial.print(" DAT["); Serial.print(dat[6]); Serial.print("]: "); // We can have a 8 and 0 subframe in a single frame. So do the reset only for dat>0 if( !(dat[6]==0 && dfmstate.lastdat==8) ) { // if we have DAT8 + DAT0, don't reset before returing the 8 frame... diff --git a/RX_FSK/src/Display.cpp b/RX_FSK/src/Display.cpp index 54d51ac..3fa56ce 100644 --- a/RX_FSK/src/Display.cpp +++ b/RX_FSK/src/Display.cpp @@ -1125,41 +1125,41 @@ void Display::drawString(DispEntry *de, const char *str) { void Display::drawLat(DispEntry *de) { rdis->setFont(de->fmt); - if(!sonde.si()->validPos) { + if(!sonde.si()->d.validPos) { drawString(de," "); return; } - snprintf(buf, 16, "%2.5f", sonde.si()->lat); + snprintf(buf, 16, "%2.5f", sonde.si()->d.lat); drawString(de,buf); } void Display::drawLon(DispEntry *de) { rdis->setFont(de->fmt); - if(!sonde.si()->validPos) { + if(!sonde.si()->d.validPos) { drawString(de," "); return; } - snprintf(buf, 16, "%2.5f", sonde.si()->lon); + snprintf(buf, 16, "%2.5f", sonde.si()->d.lon); drawString(de,buf); } void Display::drawAlt(DispEntry *de) { rdis->setFont(de->fmt); - if(!sonde.si()->validPos) { + if(!sonde.si()->d.validPos) { drawString(de," "); return; } - float alt = sonde.si()->alt; + float alt = sonde.si()->d.alt; //testing only.... alt += 30000-454; snprintf(buf, 16, alt>=1000?" %5.0fm":" %3.1fm", alt); drawString(de,buf+strlen(buf)-6); } void Display::drawHS(DispEntry *de) { rdis->setFont(de->fmt); - if(!sonde.si()->validPos) { + if(!sonde.si()->d.validPos) { drawString(de," "); return; } boolean is_ms = (de->extra && de->extra[0]=='m')?true:false; // m/s or km/h - float hs = sonde.si()->hs; + float hs = sonde.si()->d.hs; if(!is_ms) hs = hs * 3.6; boolean has_extra = (de->extra && de->extra[1]!=0)? true: false; snprintf(buf, 16, hs>99?" %3.0f":" %2.1f", hs); @@ -1169,11 +1169,11 @@ void Display::drawHS(DispEntry *de) { } void Display::drawVS(DispEntry *de) { rdis->setFont(de->fmt); - if(!sonde.si()->validPos) { + if(!sonde.si()->d.validPos) { drawString(de," "); return; } - snprintf(buf, 16, " %+2.1f", sonde.si()->vs); + snprintf(buf, 16, " %+2.1f", sonde.si()->d.vs); DebugPrintf(DEBUG_DISPLAY, "drawVS: extra is %s width=%d\n", de->extra?de->extra:"", de->width); if(de->extra) { strcat(buf, de->extra); } drawString(de, buf+strlen(buf)-5- (de->extra?strlen(de->extra):0) ); @@ -1181,29 +1181,29 @@ void Display::drawVS(DispEntry *de) { } void Display::drawID(DispEntry *de) { rdis->setFont(de->fmt); - if(!sonde.si()->validID) { + if(!sonde.si()->d.validID) { drawString(de, "nnnnnnnn "); return; } if(de->extra && de->extra[0]=='n') { // real serial number, as printed on sonde, can be up to 11 digits long - drawString(de, sonde.si()->ser); + drawString(de, sonde.si()->d.ser); } else if (de->extra && de->extra[0]=='s') { // short ID, max 8 digits (no initial "D" for DFM, "M" instead of "ME" for M10) if( TYPE_IS_DFM(sonde.si()->type) ) { - drawString(de, sonde.si()->id+1); + drawString(de, sonde.si()->d.id+1); } else if (TYPE_IS_METEO(sonde.si()->type)) { char sid[9]; sid[0]='M'; - memcpy(sid+1, sonde.si()->id+2, 8); + memcpy(sid+1, sonde.si()->d.id+2, 8); sid[8] = 0; drawString(de, sid); } else { - drawString(de, sonde.si()->id); + drawString(de, sonde.si()->d.id); } } else { // dxlAPRS sonde number, max 9 digits, as used on aprs.fi and radiosondy.info - drawString(de, sonde.si()->id); + drawString(de, sonde.si()->d.id); } } void Display::drawRSSI(DispEntry *de) { @@ -1230,7 +1230,7 @@ void Display::drawQS(DispEntry *de) { void Display::drawType(DispEntry *de) { rdis->setFont(de->fmt); - const char *typestr = sonde.si()->typestr; + const char *typestr = sonde.si()->d.typestr; if(*typestr==0) typestr = sondeTypeStr[sonde.si()->type]; drawString(de, typestr); } @@ -1289,9 +1289,9 @@ void Display::drawKilltimer(DispEntry *de) { rdis->setFont(de->fmt); uint16_t value=0; switch(de->extra[0]) { - case 'l': value = sonde.si()->launchKT; break; - case 'b': value = sonde.si()->burstKT; break; - case 'c': value = sonde.si()->countKT; break; + case 'l': value = sonde.si()->d.launchKT; break; + case 'b': value = sonde.si()->d.burstKT; break; + case 'c': value = sonde.si()->d.countKT; break; } // format: 4=h:mm; 6=h:mm:ss; s=sssss uint16_t h=value/3600; @@ -1362,17 +1362,17 @@ static int tmpc=0; #endif #endif // distance - if( gpsPos.valid && (sonde.si()->validPos&0x03)==0x03 && (layout->usegps&GPSUSE_DIST)) { - gpsDist = (int)calcLatLonDist(gpsPos.lat, gpsPos.lon, sonde.si()->lat, sonde.si()->lon); + if( gpsPos.valid && (sonde.si()->d.validPos&0x03)==0x03 && (layout->usegps&GPSUSE_DIST)) { + gpsDist = (int)calcLatLonDist(gpsPos.lat, gpsPos.lon, sonde.si()->d.lat, sonde.si()->d.lon); } else { gpsDist = -1; } // bearing - if( gpsPos.valid && (sonde.si()->validPos&0x03)==0x03 && (layout->usegps&GPSUSE_BEARING)) { + if( gpsPos.valid && (sonde.si()->d.validPos&0x03)==0x03 && (layout->usegps&GPSUSE_BEARING)) { float lat1 = radians(gpsPos.lat); - float lat2 = radians(sonde.si()->lat); + float lat2 = radians(sonde.si()->d.lat); float lon1 = radians(gpsPos.lon); - float lon2 = radians(sonde.si()->lon); + float lon2 = radians(sonde.si()->d.lon); float y = sin(lon2-lon1)*cos(lat2); float x = cos(lat1)*sin(lat2) - sin(lat1)*cos(lat2)*cos(lon2-lon1); float dir = atan2(y, x)/PI*180; @@ -1425,7 +1425,7 @@ void Display::drawGPS(DispEntry *de) { { // distance // equirectangular approximation is good enough - if( (sonde.si()->validPos&0x03)!=0x03 ) { + if( (sonde.si()->d.validPos&0x03)!=0x03 ) { snprintf(buf, 16, "no pos "); if(de->extra && *de->extra=='5') buf[5]=0; } else if(!gpsPos.valid) { @@ -1448,7 +1448,7 @@ void Display::drawGPS(DispEntry *de) { break; case 'I': // dIrection - if( (!gpsPos.valid) || ((sonde.si()->validPos&0x03)!=0x03 ) ) { + if( (!gpsPos.valid) || ((sonde.si()->d.validPos&0x03)!=0x03 ) ) { drawString(de, "---"); break; } @@ -1460,7 +1460,7 @@ void Display::drawGPS(DispEntry *de) { break; case 'B': // relative bearing - if( (!gpsPos.valid) || ((sonde.si()->validPos&0x03)!=0x03 ) ) { + if( (!gpsPos.valid) || ((sonde.si()->d.validPos&0x03)!=0x03 ) ) { drawString(de, "---"); break; } @@ -1491,9 +1491,9 @@ void Display::drawGPS(DispEntry *de) { int angN, angA, angB; // angle of north, array, bullet int validA, validB; // 0: no, 1: yes, -1: old if(circinfo->arr=='C') { angA=gpsPos.course; validA=disp.gpsCourseOld?-1:1; } - else { angA=disp.gpsDir; validA=sonde.si()->validPos?(rxgood?1:-1):0; } + else { angA=disp.gpsDir; validA=sonde.si()->d.validPos?(rxgood?1:-1):0; } if(circinfo->bul=='C') { angB=gpsPos.course; validB=disp.gpsCourseOld?-1:1; } - else { angB=disp.gpsDir; validB=sonde.si()->validPos?(rxgood?1:-1):0; } + else { angB=disp.gpsDir; validB=sonde.si()->d.validPos?(rxgood?1:-1):0; } if(circinfo->top=='N') { angN = 0; } else { diff --git a/RX_FSK/src/M10M20.cpp b/RX_FSK/src/M10M20.cpp index 09e5ef3..5874ec2 100644 --- a/RX_FSK/src/M10M20.cpp +++ b/RX_FSK/src/M10M20.cpp @@ -280,7 +280,9 @@ int M10M20::decodeframeM10(uint8_t *data) { if(data[1]==0x9F && data[2]==0x20) { Serial.println("Decoding..."); - SondeInfo *si = sonde.si(); + //SondeInfo *si = sonde.si(); + SondeData *si = &(sonde.si()->d); + // Its a M10 // getid... char ids[12]; @@ -295,7 +297,7 @@ int M10M20::decodeframeM10(uint8_t *data) { ids[7] = hex(id/16); ids[8] = hex(id); ids[9] = 0; - strncpy(sonde.si()->id, ids, 10); + strncpy(si->id, ids, 10); ids[0] = hex(data[95]/16); ids[1] = dez((data[95]&0x0f)/10); ids[2] = dez((data[95]&0x0f)); @@ -396,15 +398,15 @@ void M10M20::processM10data(uint8_t dt) // 45 20 7x => M20 if(rxp==2 && dataptr[0]==0x45 && dataptr[1]==0x20) { isM20 = true; } if(isM20) { - memcpy(sonde.si()->typestr, "M20 ", 5); - sonde.si()->subtype = 2; + memcpy(sonde.si()->d.typestr, "M20 ", 5); + sonde.si()->d.subtype = 2; if(rxp>=M20_FRAMELEN) { rxsearching = true; haveNewFrame = decodeframeM20(dataptr); } } else { - memcpy(sonde.si()->typestr, "M10 ", 5); - sonde.si()->subtype = 1; + memcpy(sonde.si()->d.typestr, "M10 ", 5); + sonde.si()->d.subtype = 1; if(rxp>=M10_FRAMELEN) { rxsearching = true; haveNewFrame = decodeframeM10(dataptr); @@ -472,7 +474,8 @@ int M10M20::decodeframeM20(uint8_t *data) { int repl = 0; bool crcok = false; bool crcbok = false; - SondeInfo *si = sonde.si(); + //SondeInfo *si = sonde.si(); + SondeData *si = &(sonde.si()->d); // error correction, inspired by oe5dxl's sondeudp // check first block uint8_t s[200]; @@ -569,7 +572,7 @@ int M10M20::decodeframeM20(uint8_t *data) { uint32_t tow = getint24(data+15); uint16_t week = getint16(data+26); si->time = (tow+week*604800+315964800)-18; - si->vframe = sonde.si()->time - 315964800; + si->vframe =si->time - 315964800; si->validTime = true; } diff --git a/RX_FSK/src/MP3H.cpp b/RX_FSK/src/MP3H.cpp index 1c6e0aa..ae8831e 100644 --- a/RX_FSK/src/MP3H.cpp +++ b/RX_FSK/src/MP3H.cpp @@ -199,7 +199,8 @@ extern double atang2(double x, double y); void calcgps(uint8_t *buf) { - SondeInfo *si = sonde.si(); + //SondeInfo *si = sonde.si(); + SondeData *si =&(sonde.si()->d); double wx = i4(buf+pos_GPSecefX) * 0.01; double wy = i4(buf+pos_GPSecefY) * 0.01; double wz = i4(buf+pos_GPSecefZ) * 0.01; @@ -237,7 +238,8 @@ static uint32_t getgpstime(uint8_t *buf) { } // unix time stamp from date and time info in frame. static void getmp3htime(uint8_t *buf) { - SondeInfo *si = sonde.si(); + //SondeInfo *si = sonde.si(); + SondeData *si =&(sonde.si()->d); // gpsdate from CFG frame 15 (0 if not yet received) uint32_t gpsdate = mp3hstate.gpsdate; @@ -285,7 +287,8 @@ int MP3H::decodeframeMP3H(uint8_t *data) { } // data is a frame with correct CRC - SondeInfo *si = sonde.si(); + //SondeInfo *si = sonde.si(); + SondeData *si =&(sonde.si()->d); uint8_t cnt = data[pos_CNT1] & 0x0F; uint32_t cfg = u4(data+pos_CFG); if(cnt==15) { @@ -307,7 +310,7 @@ int MP3H::decodeframeMP3H(uint8_t *data) { // get id if((mp3hstate.idok&3) == 3) { //... - si->type = STYPE_MP3H; + //si->type = STYPE_MP3H; uint32_t n = mp3hstate.id1*100000 + mp3hstate.id2; si->id[0] = 'M'; si->id[1] = 'R'; @@ -504,13 +507,13 @@ int MP3H::receive() { if(haveNewFrame != 1) { Serial.printf("hNF: %d (ERROR)\n", haveNewFrame); retval = RX_ERROR; - } else if (sonde.si()->time == lastFrame) { // same frame number as seen before => skip + } else if (sonde.si()->d.time == lastFrame) { // same frame number as seen before => skip Serial.printf("Skipping frame with frame# %d\n", lastFrame); // nothing, wait for next, "new" frame } else { // good and new frame, return it. Serial.println("Good frame"); haveNewFrame = 0; - lastFrame = sonde.si()->time; + lastFrame = sonde.si()->d.time; return RX_OK; } haveNewFrame = 0; diff --git a/RX_FSK/src/RS41.cpp b/RX_FSK/src/RS41.cpp index 232f2a2..06e8bc6 100644 --- a/RX_FSK/src/RS41.cpp +++ b/RX_FSK/src/RS41.cpp @@ -431,7 +431,7 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p) double z; double y; double x; - SondeInfo *si = sonde.si(); + SondeData *si = &(sonde.si()->d); x = (double)getint32(b, b_len, p)*0.01; y = (double)getint32(b, b_len, p+4UL)*0.01; z = (double)getint32(b, b_len, p+8UL)*0.01; @@ -594,7 +594,7 @@ float GetRAHumidity( uint32_t humCurrent, uint32_t humMin, uint32_t humMax, floa float Cp = ( C / calibration->value.calibU[0] - 1.0f) * calibration->value.calibU[1]; /* Compensation for low temperature and pressure at altitude */ - float estimatedPressure = 1013.25f * expf(-1.18575919e-4f * sonde.si()->alt ); + float estimatedPressure = 1013.25f * expf(-1.18575919e-4f * sonde.si()->d.alt ); float Tp = (sensorTemp - 20.0f) / 180.0f; float sum = 0; @@ -640,7 +640,7 @@ int RS41::decode41(byte *data, int maxlen) { char buf[128]; int crcok = 0; - SondeInfo *si = sonde.si(); + SondeData *si = &(sonde.si()->d); int32_t corr = reedsolomon41(data, 560, 131); // try short frame first if(corr<0) { @@ -682,8 +682,8 @@ int RS41::decode41(byte *data, int maxlen) { if(strncmp(si->id, (const char *)(data+p+2), 8)) { // ID changed, i.e. new sonde on same frequency. clear calibration and all other data - sonde.clearAllData(si); - struct subframeBuffer *sub = (struct subframeBuffer *)si->extra; + sonde.clearAllData(sonde.si()); + struct subframeBuffer *sub = (struct subframeBuffer *)sonde.si()->extra; if(sub) { sub->valid = 0; } } Serial.print("#"); @@ -694,7 +694,7 @@ int RS41::decode41(byte *data, int maxlen) snprintf(buf, 10, "%.8s ", data+p+2); Serial.print(buf); si->batteryVoltage = data[p+10] / 10.0f; - si->type=STYPE_RS41; + // not needed, if we end up here, the type has to be RS41.... si->type=STYPE_RS41; strncpy(si->id, (const char *)(data+p+2), 8); si->id[8]=0; strncpy(si->ser, (const char *)(data+p+2), 8); @@ -762,7 +762,7 @@ int RS41::decode41(byte *data, int maxlen) Serial.printf( "Humid sensor: tempHumiMain = %ld, tempHumiRef1 = %ld, tempHumiRef2 = %ld\n", tempHumiMain, tempHumiRef1, tempHumiRef2 ); Serial.printf( "Pressure sens: pressureMain = %ld, pressureRef1 = %ld, pressureRef2 = %ld\n", pressureMain, pressureRef1, pressureRef2 ); #endif - struct subframeBuffer *calibration = (struct subframeBuffer *)si->extra; + struct subframeBuffer *calibration = (struct subframeBuffer *)(sonde.si()->extra); // check for bits 3 through 20 set and 37 through 46 bool validExternalTemperature = calibration!=NULL && (calibration->valid & 0xF8) == 0xF8; bool validHumidity = calibration!=NULL && (calibration->valid & 0x7FE0001FFFF8) == 0x7FE0001FFFF8; diff --git a/RX_FSK/src/RS92.cpp b/RX_FSK/src/RS92.cpp index fbef505..fd1a175 100644 --- a/RX_FSK/src/RS92.cpp +++ b/RX_FSK/src/RS92.cpp @@ -552,7 +552,7 @@ int RS92::waitRXcomplete() { Serial.printf("decoding frame %d\n", lastFrame); print_frame(lastFrame==1?data1:data2, 240); - SondeInfo *si = sonde.sondeList+rxtask.receiveSonde; + SondeData *si = &( (sonde.sondeList+rxtask.receiveSonde)->d ); si->lat = gpx.lat; si->lon = gpx.lon; si->alt = gpx.alt; diff --git a/RX_FSK/src/ShFreqImport.cpp b/RX_FSK/src/ShFreqImport.cpp index 9e45ff7..3bd7aa9 100644 --- a/RX_FSK/src/ShFreqImport.cpp +++ b/RX_FSK/src/ShFreqImport.cpp @@ -104,7 +104,7 @@ void ShFreqImport::cleanup() { for(int i=0; i>(i&7))&1) == 0) && *sonde.sondeList[i].launchsite=='@' ) { // Don't remove the currently active entry - if(i==currentSonde) continue; + if(i==sonde.currentSonde) continue; Serial.printf("removing #%d\n", i); sonde.sondeList[i].launchsite[0] = 0; sonde.sondeList[i].active = 0; diff --git a/RX_FSK/src/Sonde.cpp b/RX_FSK/src/Sonde.cpp index 64a4c83..0598ba5 100644 --- a/RX_FSK/src/Sonde.cpp +++ b/RX_FSK/src/Sonde.cpp @@ -362,9 +362,10 @@ void Sonde::addSonde(float frequency, SondeType type, int active, char *launchsi if(sondeList[nSonde].extra) free(sondeList[nSonde].extra); memset(&sondeList[nSonde], 0, sizeof(SondeInfo)); sondeList[nSonde].type = type; - sondeList[nSonde].typestr[0] = 0; + sondeList[nSonde].d.typestr[0] = 0; sondeList[nSonde].freq = frequency; memcpy(sondeList[nSonde].rxStat, "\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3", 18); // unknown/undefined + clearAllData(sondeList+nSonde); } sondeList[nSonde].active = active; strncpy(sondeList[nSonde].launchsite, launchsite, 17); @@ -669,10 +670,10 @@ uint8_t Sonde::updateState(uint8_t event) { void Sonde::clearAllData(SondeInfo *si) { // set everything to 0 - memset(si->id, 0, offsetof(SondeInfo, extra)-offsetof(SondeInfo, id)); + memset(&(si->d), 0, sizeof(SondeData)); // set floats to NaN - si->lat = si->lon = si->alt = si->vs = si->hs = si->dir = NAN; - si->temperature = si->temRHSensor = si->relativeHumidity = si->batteryVoltage = NAN; + si->d.lat = si->d.lon = si->d.alt = si->d.vs = si->d.hs = si->d.dir = NAN; + si->d.temperature = si->d.tempRHSensor = si->d.relativeHumidity = si->d.batteryVoltage = NAN; } void Sonde::updateDisplayPos() { diff --git a/RX_FSK/src/Sonde.h b/RX_FSK/src/Sonde.h index 7e5384f..01db603 100644 --- a/RX_FSK/src/Sonde.h +++ b/RX_FSK/src/Sonde.h @@ -74,28 +74,8 @@ extern const char *manufacturer_string[NSondeTypes]; #define TYPE_IS_DFM(t) ( (t)==STYPE_DFM ) #define TYPE_IS_METEO(t) ( (t)==STYPE_M10 || (t)==STYPE_M20 ) -typedef struct st_sondeinfo { - // First part: static configuration, not decoded data. - // receiver configuration - bool active; - SondeType type; - float freq; - char launchsite[18]; - - // Second part: internal decoder state. no need to clear this on new sonde - // RSSI from receiver - int rssi; // signal strength - int32_t afc; // afc correction value - // statistics - uint8_t rxStat[20]; - uint32_t rxStart; // millis() timestamp of continuous rx start - uint32_t norxStart; // millis() timestamp of continuous no rx start - uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display - int8_t lastState; // -1: disabled; 0: norx; 1: rx - - // Third part: decoded data. Clear if reception of a new sonde has started +typedef struct st_sondedata { // decoded ID - // id must be the start of decoded data, extra indicates the end. char id[10]; char ser[12]; bool validID; @@ -123,6 +103,31 @@ typedef struct st_sondeinfo { float tempRHSensor = -300.0; // temperature of relative humidity sensor float relativeHumidity = -1.0; // relative humidity float batteryVoltage = -1; +} SondeData; + +typedef struct st_sondeinfo { + // First part: static configuration, not decoded data. + // receiver configuration + bool active; + SondeType type; + float freq; + char launchsite[18]; + + // Second part: internal decoder state. no need to clear this on new sonde + // RSSI from receiver + int rssi; // signal strength + int32_t afc; // afc correction value + // statistics + uint8_t rxStat[20]; + uint32_t rxStart; // millis() timestamp of continuous rx start + uint32_t norxStart; // millis() timestamp of continuous no rx start + uint32_t viewStart; // millis() timestamp of viewinf this sonde with current display + int8_t lastState; // -1: disabled; 0: norx; 1: rx + + // Third part: decoded data. Clear if reception of a new sonde has started + SondeData d; + + // Decoder-specific data, dynamically allocated (for RS41: calibration data) void *extra; } SondeInfo; // rxStat: 3=undef[empty] 1=timeout[.] 2=errro[E] 0=ok[|] 4=no valid position[°] @@ -331,6 +336,7 @@ public: uint16_t waitRXcomplete(); SondeInfo *si(); + void clearAllData(SondeInfo *si); uint8_t timeoutEvent(SondeInfo *si); uint8_t updateState(uint8_t event); diff --git a/RX_FSK/src/aprs.cpp b/RX_FSK/src/aprs.cpp index 207047c..f827b78 100644 --- a/RX_FSK/src/aprs.cpp +++ b/RX_FSK/src/aprs.cpp @@ -258,8 +258,9 @@ static uint32_t dao91(double x) char b[201]; //char raw[201]; -char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) { +char *aprs_senddata(SondeInfo *si, const char *usercall, const char *sym) { // float lat, float lon, float alt, float speed, float dir, float climb, const char *type, const char *objname, const char *usercall, const char *sym, const char *comm) + SondeData *s = &(si->d); *b=0; aprsstr_append(b, usercall); aprsstr_append(b, ">"); @@ -299,9 +300,9 @@ char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) { strcat(b, "&"); char comm[100]; - snprintf(comm, 100, "Clb=%.1fm/s %.3fMHz Type=%s", s->vs, s->freq, sondeTypeStr[s->type]); + snprintf(comm, 100, "Clb=%.1fm/s %.3fMHz Type=%s", s->vs, si->freq, sondeTypeStr[si->type]); strcat(b, comm); - if( TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type) ) { + if( TYPE_IS_DFM(si->type) || TYPE_IS_METEO(si->type) ) { snprintf(comm, 100, " ser=%s", s->ser); strcat(b, comm); } diff --git a/RX_FSK/src/mqtt.cpp b/RX_FSK/src/mqtt.cpp index f43119c..435fd9e 100644 --- a/RX_FSK/src/mqtt.cpp +++ b/RX_FSK/src/mqtt.cpp @@ -51,8 +51,9 @@ void MQTT::publishUptime() mqttClient.publish(topic, 1, 1, payload); } -void MQTT::publishPacket(SondeInfo *s) +void MQTT::publishPacket(SondeInfo *si) { + SondeData *s = &(si->d); mqttClient.connect(); // ensure we've got connection char payload[1024]; @@ -86,12 +87,12 @@ void MQTT::publishPacket(SondeInfo *s) "\"countKT\": %d," "\"crefKT\": %d" "}", - (int)s->active, - s->freq, + (int)si->active, + si->freq, s->id, s->ser, (int)s->validID, - s->launchsite, + si->launchsite, s->lat, s->lon, s->alt, @@ -103,13 +104,13 @@ void MQTT::publishPacket(SondeInfo *s) s->time, s->frame, (int)s->validTime, - s->rssi, - s->afc, - s->rxStat, - s->rxStart, - s->norxStart, - s->viewStart, - s->lastState, + si->rssi, + si->afc, + si->rxStat, + si->rxStart, + si->norxStart, + si->viewStart, + si->lastState, s->launchKT, s->burstKT, s->countKT,