diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 29aebd6..b24998e 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -2,6 +2,7 @@ #include #include +//#include #include #include //#include @@ -11,7 +12,6 @@ #include #include #include - #include #include #include @@ -47,6 +47,9 @@ String *updateBin = &updateBinM; boolean connected = false; WiFiUDP udp; WiFiClient client; +//WiFiClient rsclient; // Radiosondy client +//WiFiClientSecure shclient; // Sondehub v2 +WiFiClient shclient; // Sondehub v2 // KISS over TCP for communicating with APRSdroid WiFiServer tncserver(14580); @@ -582,6 +585,17 @@ struct st_configitems config_list[] = { {"gps_txd", "GPS TXD pin (not really needed)", 0, &sonde.config.gps_txd}, {"mdnsname", "mDNS name", 14, &sonde.config.mdnsname}, + /* Sondehub v2 settings */ + {"", "Sondehub v2 settings", -5, NULL}, + {"sondehub.active", "Sondehub reporting active", 0, &sonde.config.sondehub.active}, + {"sondehub.host", "Sondehub host", 63, &sonde.config.sondehub.host}, + {"sondehub.callsign", "Callsign", 63, &sonde.config.sondehub.callsign}, + {"sondehub.lat", "Latitude", 19, &sonde.config.sondehub.lat}, + {"sondehub.lon", "Longitude", 19, &sonde.config.sondehub.lon}, + {"sondehub.alt", "Altitude", 19, &sonde.config.sondehub.alt}, + {"sondehub.antenna", "Antenna", 63, &sonde.config.sondehub.antenna}, + {"sondehub.email", "Sondehub email", 63, &sonde.config.sondehub.email}, + }; const static int N_CONFIG = (sizeof(config_list) / sizeof(struct st_configitems)); @@ -1036,8 +1050,10 @@ void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventT if (type == WS_EVT_CONNECT) { Serial.println("Websocket client connection received"); client->text("Hello from ESP32 Server"); + //globalClient = client; } else if (type == WS_EVT_DISCONNECT) { Serial.println("Client disconnected"); + globalClient = NULL; } } #endif @@ -1056,6 +1072,11 @@ void SetupAsyncServer() { request->send(SPIFFS, "/index.html", String(), false, processor); }); +/* + server.on("/spectrum", HTTP_GET, [](AsyncWebServerRequest *request){ + request->send(SPIFFS, "/ws.html", "text/html"); + }); +*/ server.on("/test.html", HTTP_GET, [](AsyncWebServerRequest * request) { request->send(SPIFFS, "/test.html", String(), false, processor); }); @@ -2109,14 +2130,17 @@ void loopDecoder() { tncclient.write(raw, rawlen); } } - + if (sonde.config.sondehub.active) { + sondehub_send_data(&shclient, s, &sonde.config.sondehub); + } + } // send to MQTT if enabled if (connected && mqttEnabled) { Serial.println("Sending sonde info via MQTT"); mqttclient.publishPacket(s); } - } + //} // always send data, even if not valid.... if (rdzclient.connected()) { Serial.println("Sending position via TCP as rdzJSON"); @@ -2244,6 +2268,13 @@ void loopSpectrum() { scanner.scan(); scanner.plotResult(); + +/* + if(globalClient != NULL && globalClient->status() == WS_CONNECTED){ + String randomNumber = String(random(0,20)); + globalClient->text(randomNumber); + } +*/ if (sonde.config.spectrum > 0) { int remaining = sonde.config.spectrum - (millis() - specTimer) / 1000; @@ -2287,6 +2318,9 @@ String translateEncryptionType(wifi_auth_mode_t encryptionType) { } } +enum t_wifi_state { WIFI_DISABLED, WIFI_SCAN, WIFI_CONNECT, WIFI_CONNECTED, WIFI_APMODE }; + +static t_wifi_state wifi_state = WIFI_DISABLED; void enableNetwork(bool enable) { if (enable) { @@ -2306,6 +2340,10 @@ void enableNetwork(bool enable) { mqttclient.init(sonde.config.mqtt.host, sonde.config.mqtt.port, sonde.config.mqtt.id, sonde.config.mqtt.username, sonde.config.mqtt.password, sonde.config.mqtt.prefix); } + if (sonde.config.sondehub.active && wifi_state != WIFI_APMODE) { + sondehub_station_update(&shclient, &sonde.config.sondehub); + } + connected = true; } else { MDNS.end(); @@ -2313,11 +2351,6 @@ void enableNetwork(bool enable) { } } - -enum t_wifi_state { WIFI_DISABLED, WIFI_SCAN, WIFI_CONNECT, WIFI_CONNECTED, WIFI_APMODE }; - -static t_wifi_state wifi_state = WIFI_DISABLED; - // Events used only for debug output right now void WiFiEvent(WiFiEvent_t event) { @@ -2871,3 +2904,165 @@ void loop() { } } + +// Sondehub v2 DB related codes + +/* + * Update station data to the sondehub v2 DB + */ +void sondehub_station_update(WiFiClient *client, struct st_sondehub *conf) { + char data[300]; + + Serial.println("sondehub_station_update()"); + + if (!client->connected()) { + if (!client->connect(conf->host, 80)) { + Serial.println("Connection FAILED"); + return; + } + } + + client->println("PUT /listeners HTTP/1.1"); + client->print("Host: "); + client->println(conf->host); + client->println("accept: text/plain"); + client->println("Content-Type: application/json"); + client->print("Content-Length: "); + sprintf(data, + "{" + "\"software_name\": \"%s\"," + "\"software_version\": \"%s\"," + "\"uploader_callsign\": \"%s\"," + "\"uploader_contact_email\": \"%s\"," + "\"uploader_position\": [%s,%s,%s]," + "\"uploader_antenna\": \"%s\"" + "}", + version_name, version_id, conf->callsign, conf->email, conf->lat, conf->lon, conf->alt, conf->antenna); + client->println(strlen(data)); + client->println(); + client->println(data); + Serial.println(strlen(data)); + Serial.println(data); + String response = client->readString(); + Serial.println(response); + client->stop(); +} + +/* + * Update sonde data to the sondehub v2 DB + */ +void sondehub_send_data(WiFiClient *client, SondeInfo *s, struct st_sondehub *conf) { + Serial.println("sondehub_send_data()"); + +#define MSG_SIZE 550 + char rs_msg[MSG_SIZE]; + char *w; + struct tm ts; + time_t t = s->time; + + if (String(s->ser) == "") 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 ((int)s->sats < 4) return; // If not enough sats don't send to SondeHub + + if (String(sondeTypeStr[s->type]) == "RS41" || String(sondeTypeStr[s->type]) == "RS92" || String(sondeTypeStr[s->type]) == "M10" || String(sondeTypeStr[s->type]) == "M20") { + t += 18; // convert back to GPS time from UTC time +18s + } + + ts = *gmtime(&t); + + memset(rs_msg, 0, MSG_SIZE); + w=rs_msg; + + if (((int)s->temperature != 0) && ((int)s->relativeHumidity != 0)) { + sprintf(w, + "[ {" + "\"software_name\": \"%s\"," + "\"software_version\": \"%s\"," + "\"uploader_callsign\": \"%s\"," + "\"time_received\": \"%04d-%02d-%02dT%02d:%02d:%02d.000Z\"," + "\"manufacturer\": \"%s\"," + "\"type\": \"%s\"," + "\"serial\": \"%s\"," + "\"frame\": %d," + "\"datetime\": \"%04d-%02d-%02dT%02d:%02d:%02d.000Z\"," + "\"lat\": %.6f," + "\"lon\": %.6f," + "\"alt\": %.2f," + "\"frequency\": %.3f," + "\"vel_h\": %.1f," + "\"vel_v\": %.1f," + "\"heading\": %.1f," + "\"sats\": %d," + "\"rssi\": %.1f," + "\"temp\": %.2f," + "\"humidity\": %.2f," + "\"uploader_position\": [ %s, %s, %s ]," + "\"uploader_antenna\": \"%s\"" + "}]", + version_name, version_id, conf->callsign, + ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec + s->sec, + manufacturer_string[s->type], sondeTypeStr[s->type], s->ser, s->frame, + ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec + s->sec, + (float)s->lat, (float)s->lon, (float)s->alt, (float)s->freq, (float)s->hs, (float)s->vs, + (float)s->dir, (int)s->sats, -((float)s->rssi/2), float(s->temperature), float(s->relativeHumidity), conf->lat, conf->lon, conf->alt, conf->antenna + ); + } + else { + sprintf(w, + "[ {" + "\"software_name\": \"%s\"," + "\"software_version\": \"%s\"," + "\"uploader_callsign\": \"%s\"," + "\"time_received\": \"%04d-%02d-%02dT%02d:%02d:%02d.000Z\"," + "\"manufacturer\": \"%s\"," + "\"type\": \"%s\"," + "\"serial\": \"%s\"," + "\"frame\": %d," + "\"datetime\": \"%04d-%02d-%02dT%02d:%02d:%02d.000Z\"," + "\"lat\": %.6f," + "\"lon\": %.6f," + "\"alt\": %.2f," + "\"frequency\": %.3f," + "\"vel_h\": %.1f," + "\"vel_v\": %.1f," + "\"heading\": %.1f," + "\"sats\": %d," + "\"rssi\": %.1f," + "\"uploader_position\": [ %s, %s, %s ]," + "\"uploader_antenna\": \"%s\"" + "}]", + version_name, version_id, conf->callsign, + ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec + s->sec, + manufacturer_string[s->type], sondeTypeStr[s->type], s->ser, s->frame, + ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec + s->sec, + (float)s->lat, (float)s->lon, (float)s->alt, (float)s->freq, (float)s->hs, (float)s->vs, + (float)s->dir, (int)s->sats, -((float)s->rssi/2), conf->lat, conf->lon, conf->alt, conf->antenna + ); + } + + if (!client->connected()) { + Serial.println("NO CONNECTION"); + if (!client->connect(conf->host, 80)) { + Serial.println("Connection FAILED"); + return; + } + } + + client->println("PUT /sondes/telemetry HTTP/1.1"); + client->print("Host: "); + client->println(conf->host); + client->println("accept: text/plain"); + client->println("Content-Type: application/json"); + client->print("Content-Length: "); + client->println(strlen(w)); + client->println(); + client->println(w); + Serial.println(w); + String response = client->readString(); + Serial.println(response); +} +// End of sondehub v2 related codes diff --git a/RX_FSK/RX_FSK.ino.ttgo-lora32-v1.bin b/RX_FSK/RX_FSK.ino.ttgo-lora32-v1.bin new file mode 100644 index 0000000..33463eb Binary files /dev/null and b/RX_FSK/RX_FSK.ino.ttgo-lora32-v1.bin differ diff --git a/RX_FSK/data/config.txt b/RX_FSK/data/config.txt index 3147cec..c50d637 100644 --- a/RX_FSK/data/config.txt +++ b/RX_FSK/data/config.txt @@ -91,7 +91,7 @@ ephftp=www.ngs.noaa.gov/cors/rinex/ #-------------------------------# # local use only, do not feed to public services # data not sanitized / quality checked, outliers not filtered out -axudp.active=1 +axudp.active=0 axudp.host=192.168.42.20 axudp.port=9002 axudp.symbol=/O @@ -112,12 +112,24 @@ tcp.idformat=0 #-------------------------------# # data not sanitized / quality checked, outliers not filtered out mqtt.active=0 -mqtt.id=rdz_sonde_server -mqtt.host= -mqtt.port=1883 +mqtt.id=BSG_MQTT +mqtt.ip=192.168.1.5 +mqtt.port=1884 mqtt.username= mqtt.password= mqtt.prefix=rdz_sonde_server/ #-------------------------------# +# Sondehub v2 settings +#-------------------------------# +# Sondehub v2 DB settings +sondehub.active=1 +sondehub.host=api.v2.sondehub.org +sondehub.callsign=CHANGEME_BSG_TTGO +sondehub.lat=null +sondehub.lon=null +sondehub.alt=null +sondehub.antenna= +sondehub.email= +#-------------------------------# # EOF #-------------------------------# diff --git a/RX_FSK/data/index.html b/RX_FSK/data/index.html index 1bc15ae..481e7db 100644 --- a/RX_FSK/data/index.html +++ b/RX_FSK/data/index.html @@ -1,7 +1,7 @@ - rdzTTGOsonde Server + BSGSonde Server @@ -9,7 +9,12 @@
-

RDZSonde Server

+

BSGSonde Server

+
diff --git a/RX_FSK/data/networks.txt b/RX_FSK/data/networks.txt index a40d1dc..a536f0f 100644 --- a/RX_FSK/data/networks.txt +++ b/RX_FSK/data/networks.txt @@ -1,4 +1,2 @@ -RDZsonde -RDZsonde -DinoGast -Schokolade +oh3bsg +oh3bsg diff --git a/RX_FSK/data/qrg.txt b/RX_FSK/data/qrg.txt index 43f2bb2..cfe3f59 100644 --- a/RX_FSK/data/qrg.txt +++ b/RX_FSK/data/qrg.txt @@ -1,23 +1,16 @@ # Frequency in Mhz (format nnn.nnn) # Type (4=RS41, 6=DFM normal, DFM-06, 9=DFM inverted, DFM-09) # -402.300 4 + Greifswald -402.500 4 - Schleswig -402.700 4 + HH-Sasel -403.000 4 - DeBilt -404.100 4 + Norderney -404.300 4 - Schleswig_2 -404.500 4 - Meppen -404.700 4 - Greifswald_2 -405.100 4 - Lindenberg -405.700 4 + Bergen -405.900 4 + Bergen_2 -405.100 4 + Meppen_2 -405.300 4 - Essen -403.330 9 - TrUebPl -403.450 9 - TrUebPl -403.470 9 - TrUebPl -403.850 9 - TrUebPl -403.870 9 - TrUebPl -403.890 9 - TrUebPl +403.000 4 + Jokioinen +405.300 4 + Sundsvall +404.000 4 + Tallinn +401.000 4 + Niinisalo +401.800 4 + Vaisala +402.000 4 + Vaisala +402.700 4 + Vaisala +402.400 4 + Vaisala +403.500 4 + Katajaluoto +402.500 4 + Katajaluoto +404.000 4 + Tallinn +405.300 4 + Sundsvall # end diff --git a/RX_FSK/data/ws.html b/RX_FSK/data/ws.html new file mode 100644 index 0000000..a094a3c --- /dev/null +++ b/RX_FSK/data/ws.html @@ -0,0 +1,23 @@ + + + + + + + +
+

Not connected

+
+ + diff --git a/RX_FSK/version.h b/RX_FSK/version.h index 4b4aaca..57f4358 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,4 +1,4 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20210509"; +const char *version_id = "sondehub"; const int SPIFFS_MAJOR=2; const int SPIFFS_MINOR=11; diff --git a/libraries/SondeLib/DFM.cpp b/libraries/SondeLib/DFM.cpp index bf9d204..551caeb 100644 --- a/libraries/SondeLib/DFM.cpp +++ b/libraries/SondeLib/DFM.cpp @@ -4,7 +4,7 @@ #include "SX1278FSK.h" #include "Sonde.h" -#define DFM_DEBUG 1 +#define DFM_DEBUG 0 #if DFM_DEBUG #define DFM_DBG(x) x diff --git a/libraries/SondeLib/RS41.cpp b/libraries/SondeLib/RS41.cpp index 4a06a34..4f5894c 100644 --- a/libraries/SondeLib/RS41.cpp +++ b/libraries/SondeLib/RS41.cpp @@ -5,7 +5,7 @@ #include "rsc.h" #include "Sonde.h" -#define RS41_DEBUG 0 +#define RS41_DEBUG 1 #if RS41_DEBUG #define RS41_DBG(x) x diff --git a/libraries/SondeLib/Scanner.h b/libraries/SondeLib/Scanner.h index b8fcd3f..034b770 100644 --- a/libraries/SondeLib/Scanner.h +++ b/libraries/SondeLib/Scanner.h @@ -9,7 +9,6 @@ #ifndef inttypes_h #include #endif - class Scanner { private: diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index 5ac161e..aba6785 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -20,6 +20,9 @@ const char *evstring[]={"NONE", "KEY1S", "KEY1D", "KEY1M", "KEY1L", "KEY2S", "KE const char *RXstr[]={"RX_OK", "RX_TIMEOUT", "RX_ERROR", "RX_UNKNOWN"}; +// Dependency to enum SondeType +const char *manufacturer_string[]={"Graw", "Graw", "Vaisala", "Vaisala", "Meteomodem", "Meteomodem", "Graw", "???"}; + int fingerprintValue[]={ 17, 31, 64, 4, 55, 48, 23, 128+23, 119, 128+119, -1 }; const char *fingerprintText[]={ "TTGO T-Beam (new version 1.0), I2C not working after powerup, assuming 0.9\" OLED@21,22", @@ -371,7 +374,22 @@ void Sonde::setConfig(const char *cfg) { strncpy(config.mqtt.password, val, 63); } else if(strcmp(cfg,"mqtt.prefix")==0) { strncpy(config.mqtt.prefix, val, 63); - + } else if(strcmp(cfg, "sondehub.active")==0) { + config.sondehub.active = atoi(val); + } else if(strcmp(cfg, "sondehub.host")==0) { + strncpy(config.sondehub.host, val, 63); + } else if(strcmp(cfg, "sondehub.callsign")==0) { + strncpy(config.sondehub.callsign, val, 63); + } else if(strcmp(cfg, "sondehub.lat")==0) { + strncpy(config.sondehub.lat, val, 19); + } else if(strcmp(cfg, "sondehub.lon")==0) { + strncpy(config.sondehub.lon, val, 19); + } else if(strcmp(cfg, "sondehub.alt")==0) { + strncpy(config.sondehub.alt, val, 19); + } else if(strcmp(cfg, "sondehub.antenna")==0) { + strncpy(config.sondehub.antenna, val, 63); + } else if(strcmp(cfg, "sondehub.email")==0) { + strncpy(config.sondehub.email, val, 63); } else { Serial.printf("Invalid config option '%s'=%s \n", cfg, val); } diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index 8a6a42b..e20e4df 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -58,6 +58,7 @@ enum SondeType { STYPE_DFM, STYPE_DFM09_OLD, STYPE_RS41, STYPE_RS92, STYPE_M10, extern const char *sondeTypeStr[NSondeTypes]; extern const char *sondeTypeLongStr[NSondeTypes]; extern const char sondeTypeChar[NSondeTypes]; +extern const char *manufacturer_string[NSondeTypes]; #define TYPE_IS_DFM(t) ( (t)==STYPE_DFM || (t)==STYPE_DFM09_OLD || (t)==STYPE_DFM06_OLD ) #define TYPE_IS_METEO(t) ( (t)==STYPE_M10 || (t)==STYPE_M20 ) @@ -180,6 +181,17 @@ struct st_mqtt { char prefix[64]; }; +struct st_sondehub { + int active; + char host[64]; + char callsign[64]; + char lat[20]; + char lon[20]; + char alt[20]; + char antenna[64]; + char email[64]; +}; + typedef struct st_rdzconfig { // hardware configuration int button_pin; // PIN port number menu button (+128 for touch mode) @@ -229,6 +241,7 @@ typedef struct st_rdzconfig { struct st_feedinfo tcpfeed; // target for APRS-IS TCP connections struct st_kisstnc kisstnc; // target for KISS TNC (via TCP, mainly for APRSdroid) struct st_mqtt mqtt; + struct st_sondehub sondehub; } RDZConfig; diff --git a/libraries/SondeLib/aprs.cpp b/libraries/SondeLib/aprs.cpp index cbd2211..9647b34 100644 --- a/libraries/SondeLib/aprs.cpp +++ b/libraries/SondeLib/aprs.cpp @@ -279,7 +279,8 @@ char *aprs_senddata(SondeInfo *s, const char *usercall, const char *sym) { *b=0; aprsstr_append(b, usercall); aprsstr_append(b, ">"); - const char *destcall="APZRDZ"; +// const char *destcall="APZRDZ"; + const char *destcall="APRARX,SONDEGATE,TCPIP,qAR,oh3bsg"; aprsstr_append(b, destcall); // uncompressed aprsstr_append(b, ":;"); diff --git a/platformio.ini b/platformio.ini index cef25c6..c9941b0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,11 +26,12 @@ lib_deps_external = https://github.com/dx168b/async-mqtt-client [env:ttgo-lora32] -;platform = espressif32 platform = https://github.com/platformio/platform-espressif32.git board = ttgo-lora32-v1 framework = arduino monitor_speed = 115200 -lib_deps = - ${extra.lib_deps_builtin} - ${extra.lib_deps_external} +lib_deps = + ${extra.lib_deps_builtin} + ${extra.lib_deps_external} + paulstoffregen/Time@^1.6.0 +lib_ignore = Time