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;