diff --git a/README.md b/README.md index 49163e6..8d16990 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ It also supports feeding data to external applications using WiFi (NOT bluetooth - AXUDP (for aprsmap application by oe5dxl, among others) - KISS TNC (aprs format, mainly useful for APRSdroid app) - MQTT -- SondeHub tracker (experimental) +- SondeHub tracker +- Chasemapper UDP (experimental) Please consult the Wiki at https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/Supported-boards diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 441120f..b4374df 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -24,6 +24,9 @@ #include "src/aprs.h" #include "src/ShFreqImport.h" #include "src/RS41.h" +#if FEATURE_CHASEMAPPER +#include "src/Chasemapper.h" +#endif #if FEATURE_MQTT #include "src/mqtt.h" @@ -537,7 +540,7 @@ const char *createLiveJson() { strcpy(ptr, "{"); SondeInfo *s = &sonde.sondeList[sonde.currentSonde]; - sprintf(ptr + strlen(ptr), "\"rssi\": %d, \"sonde\": {\"vframe\": %d, \"time\": %d,\"id\": \"%s\", \"freq\": %3.3f, \"type\": \"%s\"," + 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]); @@ -738,7 +741,12 @@ struct st_configitems config_list[] = { {"tcp.port", 0, &sonde.config.tcpfeed.port}, {"tcp.idformat", -2, &sonde.config.tcpfeed.idformat}, {"tcp.highrate", 0, &sonde.config.tcpfeed.highrate}, - +#if FEATURE_CHASEMAPPER + /* Chasemapper settings */ + {"cm.active", -3, &sonde.config.cm.active}, + {"cm.host", 63, &sonde.config.cm.host}, + {"cm.port", 0, &sonde.config.cm.port}, +#endif #if FEATURE_MQTT /* MQTT */ {"mqtt.active", 0, &sonde.config.mqtt.active}, @@ -2514,6 +2522,11 @@ void loopDecoder() { Serial.print("sending: "); Serial.println(raw); tncclient.write(raw, rawlen); } +#if FEATURE_CHASEMAPPER + if (sonde.config.cm.active) { + Chasemapper::send(udp, s); + } +#endif } #if FEATURE_SONDEHUB if (sonde.config.sondehub.active) { diff --git a/RX_FSK/data/cfg.js b/RX_FSK/data/cfg.js index 4e36234..c248b0f 100644 --- a/RX_FSK/data/cfg.js +++ b/RX_FSK/data/cfg.js @@ -54,6 +54,10 @@ var cfgs = [ [ "mqtt.username", "MQTT username"], [ "mqtt.password", "MQTT password"], [ "mqtt.prefix", "MQTT prefix"], +[ "", "Chasemapper settings"], +[ "cm.active", "Chasemapper active (0=disabled, 1=active)"], +[ "cm.host", "Chasemapper UDP host"], +[ "cm.port", "Chasemapper UDP port"], [ "", "SondeHub settings"], [ "sondehub.active", "SondeHub reporting (0=disabled, 1=active)"], [ "sondehub.chase", "SondeHub location reporting (0=off, 1=fixed, 2=chase/GPS, 3=auto)"], diff --git a/RX_FSK/data/livemap.js b/RX_FSK/data/livemap.js index bc82b6a..c7fd5f2 100644 --- a/RX_FSK/data/livemap.js +++ b/RX_FSK/data/livemap.js @@ -46,11 +46,12 @@ $(document).ready(function(){ var reddot = ''; var yellowdot = ''; var greendot = ''; +var lastframe = 0; $('#map .leaflet-control-container').append(L.DomUtil.create('div', 'leaflet-top leaflet-center leaflet-header')); var header = ''; header += '
rdzTTGOSonde LiveMap
🎈 - MHz -
'; -header += '
m | m/s | km/h
'; +header += '
m | m/s | km/h | °
| -dBm
'; header += '
'; header += '

Prediction-Settings
'; @@ -74,16 +75,19 @@ headtxt = function(data,stat) { var staticon = (stat == '1')?greendot:yellowdot; statbar = staticon + statbar; if ((statbar.length) > 10*greendot.length) { statbar = statbar.substring(0,10*greendot.length); } - //if (data.lat == '0.000000') { return false; } - if (data.res == 0) { + if (data.id && data.vframe != lastframe ) { + lastframe = data.vframe; $('#sonde_id').html(data.id); $('#sonde_alt').html(data.alt); $('#sonde_climb').html(data.climb); $('#sonde_speed').html( mr(data.speed * 3.6 * 10) / 10 ); + $('#sonde_dir').html(data.dir); + $('#sonde_time').html(new Date(data.time * 1000).toISOString()); + $('#sonde_rssi').html(data.rssi / 2 ); $('#sonde_detail').show(); } else { $('#sonde_id').html(data.launchsite.trim()); - $('#sonde_detail').hide(); + // $('#sonde_detail').hide(); } $('#sonde_freq').html(data.freq); $('#sonde_type').html(data.type); @@ -159,7 +163,7 @@ headtxt = function(data,stat) { //console.log(data); if (data.id) { // data.res: 0: ok 1: no rx (timeout), 2: crc err, >2 some other error - if ((data.lat != '0.000000' && data.lon != '0.000000') && (data.res==0)) { //JSON.stringify(data) != JSON.stringify(last_data)) ) { + if ((data.lat != '0.000000' && data.lon != '0.000000') && (lastframe != 0)) { //JSON.stringify(data) != JSON.stringify(last_data)) ) { var location = [data.lat,data.lon,data.alt]; if (!marker) { map.setView(location, 14); @@ -180,10 +184,13 @@ headtxt = function(data,stat) { } dots.push(location); line.setLatLngs(dots); + } + if (data.res == 0) { storage_write(data); $('#status').html(greendot); stat = 1; - } else { + } + else { $('#status').html(yellowdot); stat = 0; } diff --git a/RX_FSK/features.h b/RX_FSK/features.h index 9c47004..60341cf 100644 --- a/RX_FSK/features.h +++ b/RX_FSK/features.h @@ -5,7 +5,7 @@ /* data feed to sondehubv2 */ /* needs about 4k4 code, 200b data, 200b stack, 200b heap */ #define FEATURE_SONDEHUB 1 - +#define FEATURE_CHASEMAPPER 1 #define FEATURE_MQTT 1 #define FEATURE_RS92 1 diff --git a/RX_FSK/src/Chasemapper.cpp b/RX_FSK/src/Chasemapper.cpp new file mode 100644 index 0000000..6c98de9 --- /dev/null +++ b/RX_FSK/src/Chasemapper.cpp @@ -0,0 +1,41 @@ +#include "Chasemapper.h" + +extern const char *sondeTypeStrSH[]; + +int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) { + char buf[1024]; + struct tm tim; + time_t t = si->time; + gmtime_r(&t, &tim); + uint8_t realtype = si->type; + if (TYPE_IS_METEO(realtype)) { + realtype = si->subtype == 1 ? STYPE_M10 : STYPE_M20; + } + sprintf(buf, "{ \"type\": \"PAYLOAD_SUMMARY\"," + "\"callsign\": \"%s\"," + "\"latitude\": %g," + "\"longitude\": %g," + "\"altitude\": %d," + "\"speed\": %d," + "\"heading\": %d," + "\"time\": \"%02d:%02d:%02d\"," + "\"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, + tim.tm_hour, tim.tm_min, tim.tm_sec, + sondeTypeStrSH[realtype], + si->freq, + si->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)); + udp.endPacket(); + return 0; +} + diff --git a/RX_FSK/src/Chasemapper.h b/RX_FSK/src/Chasemapper.h new file mode 100644 index 0000000..68d8cad --- /dev/null +++ b/RX_FSK/src/Chasemapper.h @@ -0,0 +1,13 @@ +#ifndef _CHASEMAPPER_H +#define _CHASEMAPPER_H + +#include "Sonde.h" +//#include +#include + +class Chasemapper { +public: + static int send(WiFiUDP &udb, SondeInfo *si); +}; + +#endif diff --git a/RX_FSK/src/Sonde.h b/RX_FSK/src/Sonde.h index fdf79cb..1d1e556 100644 --- a/RX_FSK/src/Sonde.h +++ b/RX_FSK/src/Sonde.h @@ -3,6 +3,7 @@ #define Sonde_h #include +#include enum DbgLevel { DEBUG_OFF=0, DEBUG_INFO=1, DEBUG_SPARSER=16, DEBUG_DISPLAY=8 }; // to be extended for configuring serial debug output extern uint8_t debug; @@ -103,7 +104,7 @@ typedef struct st_sondeinfo { 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 - int16_t launchKT, burstKT, countKT; + 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; @@ -187,6 +188,12 @@ struct st_mqtt { char prefix[64]; }; +struct st_cm { + int active; + char host[64]; + int port; +}; + struct st_sondehub { int active; int chase; @@ -260,6 +267,7 @@ typedef struct st_rdzconfig { struct st_kisstnc kisstnc; // target for KISS TNC (via TCP, mainly for APRSdroid) struct st_mqtt mqtt; struct st_sondehub sondehub; + struct st_cm cm; } RDZConfig; diff --git a/RX_FSK/version.h b/RX_FSK/version.h index ec175bc..9bd5aa5 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,4 +1,4 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20210920"; +const char *version_id = "devel20210921"; const int SPIFFS_MAJOR=2; const int SPIFFS_MINOR=16;