kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
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
rodzic
ac05c9edbd
commit
b297a9a7c7
|
@ -436,16 +436,16 @@ 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) && ( !isnan(sonde.config.rxlat))) {
|
||||
if ((*s->d.ser == 0) && ( !isnan(sonde.config.rxlat))) {
|
||||
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.rxlat, sonde.config.rxlon);
|
||||
} else {
|
||||
sprintf(ptr + strlen(ptr), "<iframe src=\"https://sondehub.org/%s\" style=\"border:1px solid #00A3D3;border-radius:20px;height:95vh\"></iframe>", s-> ser);
|
||||
sprintf(ptr + strlen(ptr), "<iframe src=\"https://sondehub.org/%s\" style=\"border:1px solid #00A3D3;border-radius:20px;height:95vh\"></iframe>", s->d.ser);
|
||||
}
|
||||
} else {
|
||||
if ((*s->ser == 0) && (!isnan(sonde.config.rxlat))) {
|
||||
if ((*s->d.ser == 0) && (!isnan(sonde.config.rxlat))) {
|
||||
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.rxlat, sonde.config.rxlon);
|
||||
} else {
|
||||
sprintf(ptr, "<iframe src=\"https://sondehub.org/%s\" style=\"border:1px solid #00A3D3;border-radius:20px;height:98vh;width:100%%\"></iframe>", s-> ser);
|
||||
sprintf(ptr, "<iframe src=\"https://sondehub.org/%s\" style=\"border:1px solid #00A3D3;border-radius:20px;height:98vh;width:100%%\"></iframe>", s->d.ser);
|
||||
}
|
||||
}
|
||||
HTMLBODYEND(ptr);
|
||||
|
@ -497,24 +497,24 @@ void addSondeStatus(char *ptr, int i)
|
|||
SondeInfo *s = &sonde.sondeList[i];
|
||||
strcat(ptr, "<table>");
|
||||
sprintf(ptr + strlen(ptr), "<tr><td id=\"sfreq\">%3.3f MHz, Type: %s</td><tr><td>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), "</td></tr><tr><td>QTH: %.6f,%.6f h=%.0fm</td></tr>\n", s->lat, s->lon, s->alt);
|
||||
const time_t t = s->time;
|
||||
sprintf(ptr + strlen(ptr), "</td></tr><tr><td>QTH: %.6f,%.6f h=%.0fm</td></tr>\n", s->d.lat, s->d.lon, s->d.alt);
|
||||
const time_t t = s->d.time;
|
||||
ts = *gmtime(&t);
|
||||
sprintf(ptr + strlen(ptr), "<tr><td>Frame# %u, Sats=%d, %04d-%02d-%02d %02d:%02d:%02d</td></tr>",
|
||||
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), "<tr><td>Burst-KT=%d Launch-KT=%d Countdown=%d (vor %ds)</td></tr>\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), "<tr><td><a target=\"_empty\" href=\"geo:%.6f,%.6f\">GEO-App</a> - ", s->lat, s->lon);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://radiosondy.info/sonde_archive.php?sondenumber=%s\">radiosondy.info</a> - ", s->id);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://tracker.sondehub.org/%s\">SondeHub Tracker</a> - ", s->ser);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://www.openstreetmap.org/?mlat=%.6f&mlon=%.6f&zoom=14\">OSM</a> - ", s->lat, s->lon);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://www.google.com/maps/search/?api=1&query=%.6f,%.6f\">Google</a></td></tr>", s->lat, s->lon);
|
||||
sprintf(ptr + strlen(ptr), "<tr><td><a target=\"_empty\" href=\"geo:%.6f,%.6f\">GEO-App</a> - ", s->d.lat, s->d.lon);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://radiosondy.info/sonde_archive.php?sondenumber=%s\">radiosondy.info</a> - ", s->d.id);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://tracker.sondehub.org/%s\">SondeHub Tracker</a> - ", s->d.ser);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://www.openstreetmap.org/?mlat=%.6f&mlon=%.6f&zoom=14\">OSM</a> - ", s->d.lat, s->d.lon);
|
||||
sprintf(ptr + strlen(ptr), "<a target=\"_empty\" href=\"https://www.google.com/maps/search/?api=1&query=%.6f,%.6f\">Google</a></td></tr>", s->d.lat, s->d.lon);
|
||||
|
||||
strcat(ptr, "</table><p/>\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), "<Placemark id=\"%s\"><name>%s</name><Point><altitudeMode>absolute</altitudeMode><coordinates>%.6f,%.6f,%.0f</coordinates></Point><description>%3.3f MHz, Type: %s, h=%.0fm</description></Placemark>",
|
||||
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, "<?xml version='1.0' encoding='UTF-8'?>\n"
|
||||
"<gpx version=\"1.1\" creator=\"http://rdzsonde.local\" xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
|
@ -1344,7 +1344,7 @@ const char *sendGPX(AsyncWebServerRequest * request) {
|
|||
"<author>rdzTTGOsonde</author>\n"
|
||||
"</metadata>\n"
|
||||
"<wpt lat=\"%f\" lon=\"%f\">\n <ele>%f</ele>\n <name>%s</name>\n <sym>Radio Beacon</sym><type>Sonde</type>\n"
|
||||
"</wpt></gpx>\n", index, si->id, si->lat, si->lon, si->alt, si->id);
|
||||
"</wpt></gpx>\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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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:"<null>", 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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -104,7 +104,7 @@ void ShFreqImport::cleanup() {
|
|||
for(int i=0; i<sonde.config.maxsonde; i++) {
|
||||
if( (((inuse[i/8]>>(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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Ładowanie…
Reference in New Issue