diff --git a/RX_FSK/src/json.cpp b/RX_FSK/src/json.cpp new file mode 100644 index 0000000..0675f0c --- /dev/null +++ b/RX_FSK/src/json.cpp @@ -0,0 +1,99 @@ +#include "json.h" +#include "RS41.h" + +extern const char *sondeTypeStrSH[]; +extern const char *dfmSubtypeStrSH[]; + +static char typestr[11]; + +const char *getType(SondeInfo *si) { + if( si->type == STYPE_RS41 ) { + if ( RS41::getSubtype(typestr, 11, si) == 0 ) return typestr; + } else if ( TYPE_IS_DFM(si->type) && si->d.subtype > 0 && si->d.subtype < 16 ) { + const char *t = dfmSubtypeStrSH[si->d.subtype]; + if(t) return t; + sprintf(typestr, "DFMx%X", si->d.subtype); + return typestr; + } + return sondeTypeStrSH[sonde.realType(si)]; +} + +// To be used by +// - MQTT +// - rdzJSON (for Android app) +// - Web map +int sonde2json(char *buf, int maxlen, SondeInfo *si) +{ + SondeData *s = &(si->d); + int n = snprintf(buf, maxlen, + "\"type\":\"%s\"," + "\"id\": \"%s\"," // TODO: maybe remove in the future, ser is enough, client can calculate APRS id if needed + "\"ser\": \"%s\"," + "\"frame\": %u," // raw frame, from sonde, can be 0. (TODO: add virtual frame # as in sondehub?) + "\"time\": %u," + "\"lat\": %.5f," + "\"lon\": %.5f," + "\"alt\": %.1f," + "\"vs\": %.1f," + "\"hs\": %.1f," + "\"climb\": %.1f," // used by HTML map, to be removed (-> vs) + "\"speed\": %.1f," // used by HTML map, to be removed (-> hs) + "\"dir\": %.1f," + "\"sats\": %d," + "\"freq\": %.2f," + "\"rssi\": %d," + "\"afc\": %d," + "\"launchKT\": %d," + "\"burstKT\": %d," + "\"countKT\": %d," + "\"crefKT\": %d", + getType(si), + s->id, + s->ser, + s->frame, + s->time, + s->lat, + s->lon, + s->alt, + s->vs, + s->hs, + s->vs, + s->hs, + s->dir, + s->sats, + si->freq, + si->rssi, + si->afc, + s->launchKT, + s->burstKT, + s->countKT, + s->crefKT + ); + if(n>=maxlen) return -1; + buf += n; maxlen -= n; + + // add only if available + if(s->batteryVoltage > 0) { + n = snprintf(buf, maxlen, "\"bat\": %.1f,", s->batteryVoltage); + if(n>=maxlen) return -1; + buf += n; maxlen -= n; + } + if ( !isnan( s->temperature ) ) { + n = snprintf(buf, maxlen, ",\"temp\": %.1f", s->temperature ); + if(n>=maxlen) return -1; + buf += n; maxlen -=n; + } + if ( !isnan( s->relativeHumidity) ) { + n = snprintf(buf, maxlen, ",\"humidity\": %.1f", s->relativeHumidity); + if(n>=maxlen) return -1; + buf += n; maxlen -=n; + } + if ( !isnan( s->pressure) ) { + n = snprintf(buf, maxlen, ",\"pressure\": %.1f", s->pressure ); + if(n>=maxlen) return -1; + buf += n; maxlen -=n; + } + return 0; +} + + diff --git a/RX_FSK/src/json.h b/RX_FSK/src/json.h new file mode 100644 index 0000000..608e924 --- /dev/null +++ b/RX_FSK/src/json.h @@ -0,0 +1,8 @@ +#ifndef _JSON_H +#define _JSON_H + +#include "Sonde.h" + +int sonde2json(char *buf, int maxlen, SondeInfo *si); + +#endif diff --git a/RX_FSK/src/mqtt.cpp b/RX_FSK/src/mqtt.cpp index fd40760..3e0b463 100644 --- a/RX_FSK/src/mqtt.cpp +++ b/RX_FSK/src/mqtt.cpp @@ -4,6 +4,7 @@ #include #include #include "RS41.h" +#include "json.h" TimerHandle_t mqttReconnectTimer; @@ -59,6 +60,14 @@ void MQTT::publishPacket(SondeInfo *si) mqttClient.connect(); // ensure we've got connection char payload[1024]; + payload[0] = '{'; + int n = sonde2json(payload+1, 1023, si); + if(n<0) { + // ERROR + Serial.println("publishPacket: sonde2json failed, string too long"); + } + +#if 0 snprintf(payload, 1024, "{" "\"active\": %d," "\"freq\": %.2f," @@ -134,6 +143,8 @@ void MQTT::publishPacket(SondeInfo *si) snprintf(payload, 1024, "%s%s%s%s", payload, ",\"subtype\": \"", subtype, "\"" ); } snprintf(payload, 1024, "%s%s", payload, "}" ); // terminate payload string +#endif + strcat(payload, "}"); // terminate payload string char topic[128]; snprintf(topic, 128, "%s%s", this->prefix, "packet");