kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
Merge branch 'dl9rdz:devel' into devel
commit
485d742372
|
@ -24,7 +24,7 @@ for details on supported boards, and additional setup instructions.
|
|||
Manufacturer | Model | Position | Temperature | Humidity | Pressure
|
||||
-------------|-------|----------|-------------|----------|----------
|
||||
Vaisala | RS92-SGP/NGP | :heavy_check_mark: | :heavy_check_mark: | :x: | :x:
|
||||
Vaisala | RS41-SG/SGP/SGM | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :x:
|
||||
Vaisala | RS41-SG/SGP/SGM | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark:
|
||||
Graw | DFM06/09/17 | :heavy_check_mark: | :x: | :x: | :x:
|
||||
Meteomodem | M10 | :heavy_check_mark: | :x: | :x: | Not Sent
|
||||
Meteomodem | M20 | :heavy_check_mark: | :x: | :x: | Not Sent
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "features.h"
|
||||
#include "version.h"
|
||||
|
||||
|
@ -90,6 +89,8 @@ WiFiClient tncclient;
|
|||
// JSON over TCP for communicating with my kotlin andoird test stuff
|
||||
WiFiServer rdzserver(14570);
|
||||
WiFiClient rdzclient;
|
||||
// APRS over TCP for radiosondy.info etc
|
||||
AsyncClient tcpclient;
|
||||
|
||||
#if FEATURE_MQTT
|
||||
unsigned long lastMqttUptime = 0;
|
||||
|
@ -2510,7 +2511,7 @@ void loopDecoder() {
|
|||
// first check if ID and position lat+lonis ok
|
||||
|
||||
if (s->d.validID && ((s->d.validPos & 0x03) == 0x03)) {
|
||||
const char *str = aprs_senddata(s, sonde.config.call, sonde.config.udpfeed.symbol);
|
||||
char *str = aprs_senddata(s, sonde.config.call, sonde.config.udpfeed.symbol);
|
||||
if (connected) {
|
||||
char raw[201];
|
||||
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
|
||||
|
@ -2527,6 +2528,22 @@ void loopDecoder() {
|
|||
Serial.print("sending: "); Serial.println(raw);
|
||||
tncclient.write(raw, rawlen);
|
||||
}
|
||||
if(sonde.config.tcpfeed.active) {
|
||||
static unsigned long lasttcp = 0;
|
||||
static bool loginok = false;
|
||||
if( tcpclient.disconnected()) {
|
||||
tcpclient.connect(sonde.config.tcpfeed.host, sonde.config.tcpfeed.port);
|
||||
}
|
||||
else if( tcpclient.connected() ) {
|
||||
unsigned long now = millis();
|
||||
if( (now-lasttcp) > sonde.config.tcpfeed.highrate*1000L ) {
|
||||
strcat(str,"\r\n");
|
||||
Serial.print(str);
|
||||
tcpclient.write(str, strlen(str));
|
||||
lasttcp = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if FEATURE_CHASEMAPPER
|
||||
if (sonde.config.cm.active) {
|
||||
Chasemapper::send(udp, s);
|
||||
|
@ -2759,6 +2776,15 @@ void enableNetwork(bool enable) {
|
|||
MDNS.end();
|
||||
connected = false;
|
||||
}
|
||||
tcpclient.onConnect([](void *arg, AsyncClient *s) {
|
||||
Serial.write("APRS: TCP connected\n");
|
||||
char buf[128];
|
||||
snprintf(buf, 128, "user %s pass %d vers %s %s\r\n", sonde.config.call, sonde.config.passcode, version_name, version_id);
|
||||
s->write(buf, strlen(buf));
|
||||
});
|
||||
tcpclient.onData([](void *arg, AsyncClient *c, void *data, size_t len) {
|
||||
Serial.write((const uint8_t *)data, len);
|
||||
});
|
||||
Serial.println("enableNetwork done");
|
||||
}
|
||||
|
||||
|
@ -3578,7 +3604,7 @@ void sondehub_reply_handler(WiFiClient * client) {
|
|||
|
||||
// also handle periodic station updates here...
|
||||
// interval check moved to sondehub_station_update to avoid having to calculate distance in auto mode twice
|
||||
if (shState == SH_CONN_IDLE) {
|
||||
if (shState == SH_CONN_IDLE || shState == SH_DISCONNECTED ) {
|
||||
// (do not set station update while a telemetry report is being sent
|
||||
sondehub_station_update(&shclient, &sonde.config.sondehub);
|
||||
}
|
||||
|
@ -3749,6 +3775,12 @@ void sondehub_send_data(WiFiClient * client, SondeInfo * s, struct st_sondehub *
|
|||
w += strlen(w);
|
||||
}
|
||||
|
||||
// Only send pressure if provided
|
||||
if (!isnan(s->d.pressure)) {
|
||||
sprintf(w, "\"pressure\": %.2f,", s->d.pressure);
|
||||
w += strlen(w);
|
||||
}
|
||||
|
||||
// Only send burst timer if RS41 and fresh within the last 51s
|
||||
if ((realtype == STYPE_RS41) && (s->d.crefKT > 0) && (s->d.vframe - s->d.crefKT < 51)) {
|
||||
sprintf(w, "\"burst_timer\": %d,", (int)s->d.countKT);
|
||||
|
|
|
@ -69,7 +69,7 @@ var cfgs = [
|
|||
[ "sondehub.fiactive", "SondeHub frequency import active (0=disabled, 1=active)" ],
|
||||
[ "sondehub.fiinterval", "Import frequency (minutes, ≥ 5)" ],
|
||||
[ "sondehub.fimaxdist", "Import maximum distance (km, ≤ 500)" ],
|
||||
[ "sondehub.fimaxage", "Import maximum age (hours, ≤ 24)" ],
|
||||
[ "sondehub.fimaxage", "Import maximum age (hours, ≤ 48)" ],
|
||||
[ "", "Hardware configuration (requires reboot)", "https://github.com/dl9rdz/rdz_ttgo_sonde/wiki/Hardware-configuration"],
|
||||
[ "disptype", "Display type (0=OLED/SSD1306, 1=ILI9225, 2=OLED/SH1106, 3=ILI9341, 4=ILI9342)"],
|
||||
[ "oled_sda", "OLED SDA/TFT SDA"],
|
||||
|
|
|
@ -85,8 +85,8 @@ dfm.rxbw=10400
|
|||
# s1: igs.bkg.bund.de/IGS/BRDC/
|
||||
# s2: www.ngs.noaa.gov/cors/rinex/
|
||||
#-------------------------------#
|
||||
ephftp=www.ngs.noaa.gov/cors/rinex/
|
||||
#ephftp=igs.bkg.bund.de/IGS/BRDC/
|
||||
#ephftp=www.ngs.noaa.gov/cors/rinex/
|
||||
ephftp=igs.bkg.bund.de/IGS/BRDC/
|
||||
#-------------------------------#
|
||||
# axudp for sending to aprsmap
|
||||
#-------------------------------#
|
||||
|
|
|
@ -13,8 +13,8 @@ int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
|||
}
|
||||
sprintf(buf, "{ \"type\": \"PAYLOAD_SUMMARY\","
|
||||
"\"callsign\": \"%s\","
|
||||
"\"latitude\": %g,"
|
||||
"\"longitude\": %g,"
|
||||
"\"latitude\": %.5f,"
|
||||
"\"longitude\": %.5f,"
|
||||
"\"altitude\": %d,"
|
||||
"\"speed\": %d,"
|
||||
"\"heading\": %d,"
|
||||
|
@ -31,7 +31,7 @@ int Chasemapper::send(WiFiUDP &udp, SondeInfo *si) {
|
|||
sondeTypeStrSH[realtype],
|
||||
si->freq);
|
||||
if( !isnan(si->d.temperature) ) {
|
||||
sprintf(buf + strlen(buf), ", \"temp\": %g", si->d.temperature);
|
||||
sprintf(buf + strlen(buf), ", \"temp\": %.1f", si->d.temperature);
|
||||
}
|
||||
strcat(buf, "}");
|
||||
Serial.printf("Sending chasemapper json: %s\n", buf);
|
||||
|
|
|
@ -435,11 +435,15 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
|||
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;
|
||||
if(x==0 && y==0 && z==0) {
|
||||
uint8_t sats = getcard16(b, b_len, p+18UL)&255UL;
|
||||
Serial.printf("x:%g, y:%g, z:%g sats:%d\n", x, y, z, sats);
|
||||
if( sats<4 || (x==0 && y==0 && z==0) ) {
|
||||
// RS41 sometimes sends frame with all 0
|
||||
// or, if sats<4, data is simply garbage. do not use.
|
||||
if(si->validPos) si->validPos |= 0x80; // flag as old
|
||||
return;
|
||||
}
|
||||
si->sats = sats;
|
||||
wgs84r(x, y, z, &lat, &long0, &heig);
|
||||
Serial.print(" ");
|
||||
si->lat = (float)(X2C_DIVL(lat,1.7453292519943E-2));
|
||||
|
@ -471,10 +475,6 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p)
|
|||
Serial.print((float)vu);
|
||||
si->vs = vu;
|
||||
Serial.print("m/s ");
|
||||
uint8_t sats = getcard16(b, b_len, p+18UL)&255UL;
|
||||
Serial.print(sats);
|
||||
Serial.print("Sats");
|
||||
si->sats = sats;
|
||||
si->alt = heig;
|
||||
if( 0==(int)(lat*10000) && 0==(int)(long0*10000) ) {
|
||||
if(si->validPos) {
|
||||
|
@ -554,6 +554,36 @@ static float _RS41_waterVaporSaturationPressure (float Tcelsius)
|
|||
return p / 100.0f;
|
||||
}
|
||||
|
||||
#define PM(x) calibration->value.matrixP[x]
|
||||
// CALIB_P: matrixP (frames 0x25..0x2A) and type (frame 0x21)
|
||||
#define CALIB_P ((0x3Fll<<0x25)|(1ll<<0x21))
|
||||
float GetRAP( uint32_t m, uint32_t m1, uint32_t m2, int16_t ptraw) {
|
||||
struct subframeBuffer *calibration = (struct subframeBuffer *)sonde.si()->extra;
|
||||
float pt = (float)ptraw*0.01;
|
||||
float pw[6];
|
||||
pw[0] = PM(0) + pt*PM(7) + pt*pt*PM(11) + pt*pt*pt*PM(15);
|
||||
pw[1] = PM(1) + pt*PM(8) + pt*pt*PM(12) + pt*pt*pt*PM(16);
|
||||
pw[2] = PM(2) + pt*PM(9) + pt*pt*PM(13) + pt*pt*pt*PM(17);
|
||||
pw[3] = PM(3) + pt*PM(10)+ pt*pt*PM(14);
|
||||
pw[4] = PM(4);
|
||||
pw[5] = PM(5);
|
||||
float f = (float)m; //meas[9];
|
||||
float f1 = (float)m1; //meas[10];
|
||||
float f2 = (float)m2; //meas[11];
|
||||
float r = f-f1;
|
||||
if(r!=0.0) {
|
||||
r = (f2-f1) * PM(6) / r;
|
||||
float xx = 1.0;
|
||||
float p = 0.0;
|
||||
for(int i=0; i<=5; i++) {
|
||||
p += pw[i] * xx;
|
||||
xx = xx * r;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
return NAN;
|
||||
}
|
||||
|
||||
// taken from https://github.com/einergehtnochrein/ra-firmware
|
||||
float GetRATemp( uint32_t measuredCurrent, uint32_t refMin, uint32_t refMax, float calT, float taylorT[3], float polyT[6] ) {
|
||||
struct subframeBuffer *calibration = (struct subframeBuffer *)sonde.si()->extra;
|
||||
|
@ -639,7 +669,7 @@ float GetRAHumidity( uint32_t humCurrent, uint32_t humMin, uint32_t humMax, floa
|
|||
int RS41::decode41(byte *data, int maxlen)
|
||||
{
|
||||
char buf[128];
|
||||
int crcok = 0;
|
||||
int crcok = 1;
|
||||
SondeData *si = &(sonde.si()->d);
|
||||
|
||||
int32_t corr = reedsolomon41(data, 560, 131); // try short frame first
|
||||
|
@ -675,8 +705,8 @@ int RS41::decode41(byte *data, int maxlen)
|
|||
// check CRC
|
||||
if(!crcrs(data, 560, p, p+len)) {
|
||||
Serial.println("###CRC ERROR###");
|
||||
crcok = 0;
|
||||
} else {
|
||||
crcok = 1;
|
||||
switch(typ) {
|
||||
case 'y': // name
|
||||
{
|
||||
|
@ -751,11 +781,10 @@ int RS41::decode41(byte *data, int maxlen)
|
|||
uint32_t tempHumiMain = getint24(data, 560, p+18);
|
||||
uint32_t tempHumiRef1 = getint24(data, 560, p+21);
|
||||
uint32_t tempHumiRef2 = getint24(data, 560, p+24);
|
||||
#if 0
|
||||
uint32_t pressureMain = getint24(data, 560, p+27);
|
||||
uint32_t pressureRef1 = getint24(data, 560, p+30);
|
||||
uint32_t pressureRef2 = getint24(data, 560, p+33);
|
||||
#endif
|
||||
int16_t ptraw = getint16(data, 560, p+38);
|
||||
#if 0
|
||||
Serial.printf( "External temp: tempMeasMain = %ld, tempMeasRef1 = %ld, tempMeasRef2 = %ld\n", tempMeasMain, tempMeasRef1, tempMeasRef2 );
|
||||
Serial.printf( "Rel Humidity: humidityMain = %ld, humidityRef1 = %ld, humidityRef2 = %ld\n", humidityMain, humidityRef1, humidityRef2 );
|
||||
|
@ -767,6 +796,13 @@ int RS41::decode41(byte *data, int maxlen)
|
|||
bool validExternalTemperature = calibration!=NULL && (calibration->valid & 0xF8) == 0xF8;
|
||||
bool validHumidity = calibration!=NULL && (calibration->valid & 0x7FE0001FFFF8) == 0x7FE0001FFFF8;
|
||||
|
||||
bool validPressure = calibration!=NULL && (calibration->valid & CALIB_P)==CALIB_P && calibration->value.names.variant[7]=='P';
|
||||
|
||||
if ( validPressure ) {
|
||||
si->pressure = GetRAP( pressureMain, pressureRef1, pressureRef2, ptraw );
|
||||
Serial.printf("Pressure sensor = %f\n", si->pressure);
|
||||
}
|
||||
|
||||
if ( validExternalTemperature ) {
|
||||
si->temperature = GetRATemp( tempMeasMain, tempMeasRef1, tempMeasRef2,
|
||||
calibration->value.calT, calibration->value.taylorT, calibration->value.polyT );
|
||||
|
@ -791,7 +827,7 @@ int RS41::decode41(byte *data, int maxlen)
|
|||
p += len;
|
||||
Serial.println();
|
||||
}
|
||||
return crcok ? 0 : -1;
|
||||
return crcok ? 0 : RX_ERROR;
|
||||
}
|
||||
void RS41::printRaw(uint8_t *data, int len)
|
||||
{
|
||||
|
|
|
@ -90,6 +90,7 @@ void ShFreqImport::populate(char *id, float lat, float lon, float freq, const ch
|
|||
return;
|
||||
} // no more free slots
|
||||
|
||||
sonde.clearAllData(&sonde.sondeList[ppos]);
|
||||
sonde.sondeList[ppos].active = 1;
|
||||
sonde.sondeList[ppos].freq = freq;
|
||||
sonde.sondeList[ppos].type = (SondeType)stype;
|
||||
|
|
|
@ -273,6 +273,7 @@ void Sonde::checkConfig() {
|
|||
if(config.maxsonde > MAXSONDE) config.maxsonde = MAXSONDE;
|
||||
if(config.sondehub.fiinterval<5) config.sondehub.fiinterval = 5;
|
||||
if(config.sondehub.fimaxdist>500) config.sondehub.fimaxdist = 500;
|
||||
if(config.sondehub.fimaxage>48) config.sondehub.fimaxage = 48;
|
||||
if(config.sondehub.fimaxdist==0) config.sondehub.fimaxdist = 150;
|
||||
if(config.sondehub.fimaxage==0) config.sondehub.fimaxage = 2;
|
||||
}
|
||||
|
@ -675,7 +676,7 @@ void Sonde::clearAllData(SondeInfo *si) {
|
|||
memset(&(si->d), 0, sizeof(SondeData));
|
||||
// set floats to 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;
|
||||
si->d.temperature = si->d.tempRHSensor = si->d.relativeHumidity = si->d.pressure = si->d.batteryVoltage = NAN;
|
||||
}
|
||||
|
||||
void Sonde::updateDisplayPos() {
|
||||
|
|
|
@ -99,9 +99,10 @@ typedef struct st_sondedata {
|
|||
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)
|
||||
float temperature = -300.0; // platinum resistor temperature
|
||||
float tempRHSensor = -300.0; // temperature of relative humidity sensor
|
||||
float relativeHumidity = -1.0; // relative humidity
|
||||
float temperature; // platinum resistor temperature
|
||||
float tempRHSensor; // temperature of relative humidity sensor
|
||||
float relativeHumidity; // relative humidity
|
||||
float pressure;
|
||||
float batteryVoltage = -1;
|
||||
} SondeData;
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ char *aprs_senddata(SondeInfo *si, const char *usercall, const char *sym) {
|
|||
i=strlen(b);
|
||||
snprintf(b+i, APRS_MAXLEN-i, "!w%c%c!", 33+dao91(s->lat), 33+dao91(s->lon));
|
||||
|
||||
strcat(b, "&");
|
||||
// ??? strcat(b, "&");
|
||||
char comm[100];
|
||||
snprintf(comm, 100, "Clb=%.1fm/s %.3fMHz Type=%s", s->vs, si->freq, sondeTypeStr[si->type]);
|
||||
strcat(b, comm);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const char *version_name = "rdzTTGOsonde";
|
||||
const char *version_id = "devel20210922";
|
||||
const char *version_id = "devel20210923";
|
||||
const int SPIFFS_MAJOR=2;
|
||||
const int SPIFFS_MINOR=16;
|
||||
|
|
Ładowanie…
Reference in New Issue