kopia lustrzana https://github.com/rs1729/RS
(test->master) rs41 aux: xdata decoding for ID=0x01 and ID=0x05, no O3-P calculation
rodzic
6ac06d552b
commit
716496dd7b
|
@ -60,6 +60,7 @@ typedef struct {
|
|||
i8_t sat; // GPS sat data
|
||||
i8_t ptu; // PTU: temperature humidity (pressure)
|
||||
i8_t dwp; // PTU derived: dew point
|
||||
i8_t aux; // decode xdata
|
||||
i8_t inv;
|
||||
i8_t aut;
|
||||
i8_t jsn; // JSON output (auto_rx)
|
||||
|
@ -1063,12 +1064,217 @@ static int get_GPS3(gpx_t *gpx, int ofs) {
|
|||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int hex2uint(char *str, int nibs) {
|
||||
int i;
|
||||
int erg = 0;
|
||||
int h = 0;
|
||||
|
||||
if (nibs > 7) return -2;
|
||||
|
||||
for (i = 0; i < nibs; i++) { // MSB i.e. most significant nibble first
|
||||
if (str[i] >= '0' && str[i] <= '9') h = str[i]-'0';
|
||||
else if (str[i] >= 'a' && str[i] <= 'f') h = str[i]-'a'+0xA;
|
||||
else if (str[i] >= 'A' && str[i] <= 'F') h = str[i]-'A'+0xA;
|
||||
else return -1;
|
||||
erg = (erg << 4) | (h & 0xF);
|
||||
}
|
||||
return erg;
|
||||
}
|
||||
|
||||
static int prn_aux_IDx01(char *xdata) {
|
||||
// V7 ECC (Electrochemical Concentration Cell) Ozonesonde
|
||||
// https://gml.noaa.gov/aftp/user/jordan/iMet%20Radiosonde%20Protocol.pdf
|
||||
// https://harbor.weber.edu/Hardware/Ozonesonde/ECC_Ozonesonde-1.pdf
|
||||
// ID=0x01: ECC Ozonesonde
|
||||
// N=2*8 nibs (1byte = 2nibs) (MSB)
|
||||
// 0 2 u8 Instrument_type = 0x01 (ID)
|
||||
// 2 2 u8 Instrument_number
|
||||
// 4 4 u16 Icell, uA (I = n/1000)
|
||||
// 8 4 i16 Tpump, C (T = n/100)
|
||||
// 12 2 u8 Ipump, mA
|
||||
// 14 2 u8 Vbat, (V = n/10)
|
||||
//
|
||||
int val;
|
||||
i16_t Tpump;
|
||||
ui16_t Icell;
|
||||
ui8_t InstrNum, Ipump, Vbat;
|
||||
char *px = xdata;
|
||||
int N = 2*8;
|
||||
|
||||
if (*px) {
|
||||
|
||||
if (strncmp(px, "01", 2) != 0) {
|
||||
px = strstr(xdata, "#01");
|
||||
if (px == NULL) return -1;
|
||||
else px += 1;
|
||||
}
|
||||
if (strlen(px) < N) return -1;
|
||||
|
||||
fprintf(stdout, " ID=0x01 ECC ");
|
||||
val = hex2uint(px+ 2, 2); if (val < 0) return -1;
|
||||
InstrNum = val & 0xFF;
|
||||
val = hex2uint(px+ 4, 4); if (val < 0) return -1;
|
||||
Icell = val & 0xFFFF; // u16
|
||||
val = hex2uint(px+ 8, 4); if (val < 0) return -1;
|
||||
Tpump = val & 0xFFFF; // i16
|
||||
val = hex2uint(px+12, 2); if (val < 0) return -1;
|
||||
Ipump = val & 0xFF; // u8
|
||||
val = hex2uint(px+14, 2); if (val < 0) return -1;
|
||||
Vbat = val & 0xFF; // u8
|
||||
fprintf(stdout, " No.%d ", InstrNum);
|
||||
fprintf(stdout, " Icell:%.3fuA ", Icell/1000.0);
|
||||
fprintf(stdout, " Tpump:%.2fC ", Tpump/100.0);
|
||||
fprintf(stdout, " Ipump:%dmA ", Ipump);
|
||||
fprintf(stdout, " Vbat:%.1fV ", Vbat/10.0);
|
||||
}
|
||||
else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prn_aux_IDx05(char *xdata) {
|
||||
// OIF411
|
||||
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide M211486EN
|
||||
//
|
||||
// ID=0x05: OIF411
|
||||
// pos nibs (MSB)
|
||||
// 0 2 u8 Instrument_type = 0x05 (ID)
|
||||
// 2 2 u8 Instrument_number
|
||||
// Measurement Data, N=2*10
|
||||
// 4 4 i16 Tpump, C (T = n/100)
|
||||
// 8 5 u20 Icell, uA (I = n/10000)
|
||||
// 13 2 u8 Vbat, (V = n/10)
|
||||
// 15 3 u12 Ipump, mA
|
||||
// 18 2 u8 Vext, (V = n/10)
|
||||
// ID Data, N=2*10+1
|
||||
// 4 8 char OIF411 Serial
|
||||
// 12 4 u16 Diagnostics Word
|
||||
// 16 2?4 u16? SW version (n/100)
|
||||
// 20 1 char I
|
||||
//
|
||||
char *px = xdata;
|
||||
int N = 2*10;
|
||||
int val;
|
||||
ui8_t InstrNum;
|
||||
|
||||
if (*px) {
|
||||
|
||||
if (strncmp(px, "05", 2) != 0) {
|
||||
px = strstr(xdata, "#05");
|
||||
if (px == NULL) return -1;
|
||||
else px += 1;
|
||||
}
|
||||
if (strlen(px) < N) return -1;
|
||||
|
||||
fprintf(stdout, " ID=0x05 OIF411 ");
|
||||
val = hex2uint(px+ 2, 2); if (val < 0) return -1;
|
||||
InstrNum = val & 0xFF;
|
||||
fprintf(stdout, " No.%d ", InstrNum);
|
||||
|
||||
if (px[N] == 'I') {
|
||||
ui16_t dw;
|
||||
ui16_t sw;
|
||||
char sn[9];
|
||||
// 5.2 ID Data
|
||||
//
|
||||
N += 1;
|
||||
strncpy(sn, px+4, 8); sn[8] = '\0';
|
||||
val = hex2uint(px+12, 4); if (val < 0) return -1;
|
||||
dw = val & 0xFFFF; // i16
|
||||
val = hex2uint(px+16, 4); if (val < 0) return -1;
|
||||
sw = val & 0xFFFF; // u8
|
||||
fprintf(stdout, " SN:%s ", sn);
|
||||
fprintf(stdout, " DW:%04X ", dw);
|
||||
fprintf(stdout, " SW:%.2f ", sw/100.0);
|
||||
// Diagnostics Word dw
|
||||
// 0000 = "Default value, no diagnostics bits active"
|
||||
// 0004 = "Ozone pump temperature below -5C"
|
||||
// 0400 = "Ozone pump battery voltage (+VBatt) is not connected to OIF411"
|
||||
// 0404 = 0004 | 0400
|
||||
}
|
||||
else {
|
||||
ui32_t Icell;
|
||||
ui16_t Ipump;
|
||||
i16_t Tpump;
|
||||
ui8_t InstrNum, Vbat, Vext;
|
||||
// 5.1 Measurement Data
|
||||
//
|
||||
val = hex2uint(px+ 4, 4); if (val < 0) return -1;
|
||||
Tpump = val & 0xFFFF; // i16
|
||||
val = hex2uint(px+ 8, 5); if (val < 0) return -1;
|
||||
Icell = val & 0xFFFFF; // u20
|
||||
val = hex2uint(px+13, 2); if (val < 0) return -1;
|
||||
Vbat = val & 0xFF; // u8
|
||||
val = hex2uint(px+15, 3); if (val < 0) return -1;
|
||||
Ipump = val & 0xFFF; // u12
|
||||
val = hex2uint(px+18, 2); if (val < 0) return -1;
|
||||
Vext = val & 0xFF; // u8
|
||||
fprintf(stdout, " Tpump:%.2fC ", Tpump/100.0);
|
||||
fprintf(stdout, " Icell:%.4fuA ", Icell/10000.0);
|
||||
fprintf(stdout, " Vbat:%.1fV ", Vbat/10.0);
|
||||
fprintf(stdout, " Ipump:%dmA ", Ipump);
|
||||
fprintf(stdout, " Vext:%.1fV ", Vext/10.0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prn_aux_IDx08(char *xdata) {
|
||||
// CFH Cryogenic Frost Point Hygrometer
|
||||
// ID=0x08: CFH
|
||||
// N=2*12 nibs
|
||||
// 0 2 u8 Instrument_type = 0x08 (ID)
|
||||
// 2 2 u8 Instrument_number
|
||||
// 4 6 Tmir, Mirror Temperature
|
||||
// 10 6 Vopt, Optics Voltage
|
||||
// 16 4 Topt, Optics Temperature
|
||||
// 20 4 Vbat, CFH Battery
|
||||
//
|
||||
char *px = xdata;
|
||||
int N = 2*12;
|
||||
int val;
|
||||
ui8_t InstrNum;
|
||||
|
||||
if (*px) {
|
||||
|
||||
if (strncmp(px, "08", 2) != 0) {
|
||||
px = strstr(xdata, "#08");
|
||||
if (px == NULL) return -1;
|
||||
else px += 1;
|
||||
}
|
||||
if (strlen(px) < N) return -1;
|
||||
|
||||
fprintf(stdout, " ID=0x08 CFH ");
|
||||
val = hex2uint(px+ 2, 2); if (val < 0) return -1;
|
||||
InstrNum = val & 0xFF;
|
||||
fprintf(stdout, " No.%d ", InstrNum);
|
||||
fprintf(stdout, " Tmir:0x%.6s ", px+4);
|
||||
fprintf(stdout, " Vopt:0x%.6s ", px+10);
|
||||
fprintf(stdout, " Topt:0x%.4s ", px+16);
|
||||
fprintf(stdout, " Vbat:0x%.4s ", px+20);
|
||||
|
||||
}
|
||||
else {
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_Aux(gpx_t *gpx, int out, int pos) {
|
||||
//
|
||||
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide
|
||||
// "Ozone Sounding with Vaisala Radiosonde RS41" user's guide M211486EN
|
||||
//
|
||||
int auxlen, auxcrc, count7E, pos7E;
|
||||
int i, n;
|
||||
char *paux;
|
||||
|
||||
n = 0;
|
||||
count7E = 0;
|
||||
|
@ -1113,6 +1319,34 @@ static int get_Aux(gpx_t *gpx, int out, int pos) {
|
|||
}
|
||||
gpx->xdata[n] = '\0';
|
||||
|
||||
// decode OIF411 xdata
|
||||
paux = gpx->xdata;
|
||||
if (out && gpx->option.aux && *paux)
|
||||
{
|
||||
int val;
|
||||
ui8_t ID;
|
||||
for (i = 0; i < count7E; i++) {
|
||||
if (paux > gpx->xdata) {
|
||||
//while (paux < (gpx->xdata)+n && *paux != '#') paux++;
|
||||
while (*paux && *paux != '#') paux++;
|
||||
paux++;
|
||||
}
|
||||
if (strlen(paux) > 2) {
|
||||
val = hex2uint(paux, 2);
|
||||
if (val < 0) { paux += 2; continue; }
|
||||
ID = val & 0xFF;
|
||||
switch (ID) {
|
||||
case 0x01: fprintf(stdout, "\n"); prn_aux_IDx01(paux); break;
|
||||
case 0x05: fprintf(stdout, "\n"); prn_aux_IDx05(paux); break;
|
||||
case 0x08: fprintf(stdout, "\n"); prn_aux_IDx08(paux); break;
|
||||
}
|
||||
paux++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
if ( !gpx->option.jsn ) fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
i = check_CRC(gpx, pos, pck_ZERO); // 0x76xx: 00-padding block
|
||||
if (i) gpx->crc |= crc_ZERO;
|
||||
|
||||
|
@ -2095,9 +2329,10 @@ int main(int argc, char *argv[]) {
|
|||
else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) {
|
||||
gpx.option.vbs = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; }
|
||||
else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; } // xdata
|
||||
else if (strcmp(*argv, "-vv") == 0) { gpx.option.vbs = 3; }
|
||||
//else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; }
|
||||
else if (strcmp(*argv, "--aux") == 0) { gpx.option.aux = 1; }
|
||||
else if (strcmp(*argv, "--crc") == 0) { gpx.option.crc = 1; }
|
||||
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
|
||||
gpx.option.raw = 1;
|
||||
|
@ -2221,6 +2456,8 @@ int main(int argc, char *argv[]) {
|
|||
rs_init_RS255(&gpx.RS); // RS, GF
|
||||
}
|
||||
|
||||
if (gpx.option.aux) gpx.option.vbs = 2;
|
||||
|
||||
// init gpx
|
||||
memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue