/* Generated by XDS Modula-2 to ANSI C v4.20 translator */ #define X2C_int32 #define X2C_index32 #ifndef loraprotocols_H_ #include "loraprotocols.h" #endif #define loraprotocols_C_ #include #ifndef osi_H_ #include "osi.h" #endif #include #ifndef udp_H_ #include "udp.h" #endif #ifndef aprsstr_H_ #include "aprsstr.h" #endif #include /* monitor lora frames and try to decode known content protocols */ #define loraprotocols_LF "\012" static char hex(uint32_t n, char cap) { n = n&15UL; if (n<=9UL) return (char)(n+48UL); if (cap) return (char)(n+55UL); return (char)(n+87UL); } /* end hex() */ static void HexStr(uint32_t x, uint32_t digits, uint32_t len, char cap, char s[], uint32_t s_len) { uint32_t i; if (digits>s_len-1) digits = s_len-1; i = digits; while (i0UL) { --digits; s[digits] = hex(x, cap); x = x/16UL; } } /* end HexStr() */ static void WrHex(uint32_t x, uint32_t digits, uint32_t len) { char s[256]; HexStr(x, digits, len, 0, s, 256ul); osi_WrStr(s, 256ul); } /* end WrHex() */ static void WrHexCap(uint32_t x, uint32_t digits, uint32_t len) { char s[256]; HexStr(x, digits, len, 1, s, 256ul); osi_WrStr(s, 256ul); } /* end WrHexCap() */ static void ChHex(char c, char s[], uint32_t s_len) { if ((uint8_t)c>='\177' || (uint8_t)c<' ') { s[0UL] = '['; s[1UL] = hex((uint32_t)(uint8_t)c/16UL, 0); s[2UL] = hex((uint32_t)(uint8_t)c, 0); s[3UL] = ']'; s[4UL] = 0; } else { s[0UL] = c; s[1UL] = 0; } } /* end ChHex() */ static void WrChHex(char c) { char s[11]; ChHex(c, s, 11ul); osi_WrStr(s, 11ul); } /* end WrChHex() */ static char cleantext(char mon[], uint32_t mon_len, char text[], uint32_t text_len, uint32_t len) /* remove heading junk */ { uint32_t j; uint32_t i; i = 0UL; while (((i'Z')) && ((uint8_t) mon[i]<'0' || (uint8_t)mon[i]>'9')) ++i; if (i<=3UL && len>2UL) { j = 0UL; while (j0UL && (uint8_t)text[j-1UL]<'\034') text[j-1UL] = 0; } else return 0; return 1; } /* end cleantext() */ static void app(uint32_t * i, uint32_t * p, char b[501], char c, int32_t v) { char s[51]; b[*p] = c; ++*p; aprsstr_IntToStr(v, 0UL, s, 51ul); *i = 0UL; while (s[*i]) { b[*p] = s[*i]; ++*p; ++*i; } b[*p] = ' '; ++*p; } /* end app() */ static void sendaxudp2(uint32_t ipnum, uint32_t udpport, char udp2, char mon[], uint32_t mon_len, uint32_t dlen, int32_t txd, float level, float snrr, int32_t afc, int32_t qual, char longcall, char dcdon) { char data[501]; char b[501]; int32_t lev; int32_t snr; int32_t datalen; int32_t ret; uint32_t i; uint32_t p; X2C_PCOPY((void **)&mon,mon_len); snr = (int32_t)X2C_TRUNCI(snrr+0.5f,X2C_min_longint,X2C_max_longint); if (snr>127L) snr = 127L; else if (snr<-127L) snr = -127L; lev = (int32_t)X2C_TRUNCI(level+0.5f,X2C_min_longint,X2C_max_longint); if (lev>127L) lev = 127L; else if (lev<-255L) lev = -255L; if (!longcall) { if (cleantext(mon, mon_len, mon, mon_len, dlen)) aprsstr_mon2raw(mon, mon_len, data, 501ul, &datalen); else { if (loraprotocols_verb) { osi_WrStrLn("axudp encode: too much junk in data (-y for prefilter aprs)", 60ul); } datalen = 0L; } if (datalen==0L) longcall = 1; } if (longcall) { datalen = (int32_t)aprsstr_Length(mon, mon_len); i = 0UL; do { data[i] = mon[i]; ++i; } while (!(i>500UL || (int32_t)i>=datalen)); } if (datalen>2L) { p = 0UL; if (udp2) { if (!longcall) datalen -= 2L; b[0U] = '\001'; b[1U] = (char)(48UL+(uint32_t)dcdon*2UL); p = 2UL; app(&i, &p, b, 'T', txd); app(&i, &p, b, 'V', lev); app(&i, &p, b, 'S', snr); app(&i, &p, b, 'A', afc); app(&i, &p, b, 'Q', qual); if (longcall) app(&i, &p, b, 'X', 2L); b[p] = 0; /* end of axudp2 header */ ++p; } i = 0UL; do { b[p] = data[i]; ++p; ++i; } while ((int32_t)i=2UL) s[2UL] = b64(b/64UL); if (n==3UL) s[3UL] = b64(b); } /* end enc64() */ static uint32_t _cnst[10] = {64UL,48UL,32UL,24UL,16UL,12UL,8UL,4UL,2UL,1UL}; static void sendjson(loraprotocols_pJDESTS udps, uint32_t id, const char text[], uint32_t text_len, uint32_t dlen, char hascrc, char crc, char invert, uint32_t sf, uint32_t cr, uint32_t txd, uint32_t frametime, float level, float n, float peakn, float snr, float dre, int32_t df, int32_t qual, int32_t fecc) { char h[1000]; char s[1000]; int32_t ret; uint32_t b; uint32_t i; strncpy(s,"{",1000u); aprsstr_Append(s, 1000ul, "\"net\":", 7ul); aprsstr_IntToStr((int32_t)id, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"crc\":", 8ul); aprsstr_IntToStr((int32_t)((uint32_t)hascrc+(uint32_t)crc)-1L, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"invers\":", 11ul); aprsstr_IntToStr((int32_t)(uint32_t)invert, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"bw\":", 7ul); aprsstr_FixToStr(X2C_DIVR(5.E+5f,(float)_cnst[loraprotocols_bwnum]), 2UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"sf\":", 7ul); aprsstr_IntToStr((int32_t)sf, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"cr\":", 7ul); aprsstr_IntToStr((int32_t)cr, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"preamb\":", 11ul); aprsstr_IntToStr((int32_t)txd, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"duration\":", 13ul); aprsstr_IntToStr((int32_t)frametime, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"level\":", 10ul); aprsstr_FixToStr(level, 2UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"afc\":", 8ul); aprsstr_IntToStr(df, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"dre\":", 8ul); aprsstr_FixToStr(dre, 2UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"eye\":", 8ul); aprsstr_IntToStr(qual, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"nfloor\":", 11ul); aprsstr_FixToStr(n, 2UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"pknfloor\":", 13ul); aprsstr_FixToStr(peakn, 2UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"snr\":", 8ul); aprsstr_FixToStr(snr, 2UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); aprsstr_Append(s, 1000ul, ",\"fec\":", 8ul); aprsstr_IntToStr(fecc, 1UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); if (loraprotocols_jmhz!=0.0f) { aprsstr_Append(s, 1000ul, ",\"rxmhz\":", 10ul); aprsstr_FixToStr(loraprotocols_jmhz+0.00005f, 4UL, h, 1000ul); aprsstr_Append(s, 1000ul, h, 1000ul); } aprsstr_Append(s, 1000ul, ",\"ver\":\"lorarx\"", 16ul); aprsstr_Append(s, 1000ul, ",\"payload\":\"", 13ul); b = 0UL; i = 0UL; while (i=0L) { osi_WrBin(loraprotocols_jsonfd, (char *)s, 1000u/1u, aprsstr_Length(s, 1000ul)); } else osi_WrStrLn("cannot write json-file", 23ul); } while (udps) { if (udps->judpport) { ret = udpsend(loraprotocols_udpsock, s, (int32_t)aprsstr_Length(s, 1000ul), udps->judpport, udps->jipnum); } udps = udps->next; } } /* end sendjson() */ extern void loraprotocols_senddcd(int32_t sf, char inv, char on) { char h[100]; char s[100]; int32_t ret; loraprotocols_pJDESTS jd; jd = loraprotocols_jdests0; while (jd) { if (jd->judpport) { if (inv) sf = -sf; strncpy(s,"{",100u); aprsstr_Append(s, 100ul, "\"dcd\":", 7ul); aprsstr_IntToStr((int32_t)(uint32_t)on, 1UL, h, 100ul); aprsstr_Append(s, 100ul, h, 100ul); aprsstr_Append(s, 100ul, ",\"sf\":", 7ul); aprsstr_IntToStr(sf, 1UL, h, 100ul); aprsstr_Append(s, 100ul, h, 100ul); aprsstr_Append(s, 100ul, "}\012", 3ul); ret = udpsend(loraprotocols_udpsock, s, (int32_t)aprsstr_Length(s, 100ul), jd->judpport, jd->jipnum); } jd = jd->next; } } /* end senddcd() */ static void WCh(char c) { if (c!='\015') { if ((uint8_t)c<' ' || (uint8_t)c>='\177') osi_WrStr(".", 2ul); else osi_WrStr((char *) &c, 1u/1u); } } /* end WCh() */ static void ShowCall(char f[], uint32_t f_len, uint32_t pos0) { uint32_t e; uint32_t i; uint32_t tmp; char tmp0; e = pos0; tmp = pos0+5UL; i = pos0; if (i<=tmp) for (;; i++) { if (f[i]!='@') e = i; if (i==tmp) break; } /* end for */ tmp = e; i = pos0; if (i<=tmp) for (;; i++) { WCh((char)((uint32_t)(uint8_t)f[i]>>1)); if (i==tmp) break; } /* end for */ i = (uint32_t)(uint8_t)f[pos0+6UL]>>1&15UL; if (i) { osi_WrStr("-", 2ul); if (i>=10UL) osi_WrStr((char *)(tmp0 = (char)(i/10UL+48UL),&tmp0), 1u/1u); osi_WrStr((char *)(tmp0 = (char)(i%10UL+48UL),&tmp0), 1u/1u); } } /* end ShowCall() */ static uint32_t loraprotocols_UA = 0x63UL; static uint32_t loraprotocols_DM = 0xFUL; static uint32_t loraprotocols_SABM = 0x2FUL; static uint32_t loraprotocols_DISC = 0x43UL; static uint32_t loraprotocols_FRMR = 0x87UL; static uint32_t loraprotocols_UI = 0x3UL; static uint32_t loraprotocols_RR = 0x1UL; static uint32_t loraprotocols_REJ = 0x9UL; static uint32_t loraprotocols_RNR = 0x5UL; static void Showctl(uint32_t com, uint32_t cmd) { uint32_t cm; char PF[4]; char tmp; osi_WrStr(" ctl ", 6ul); cm = (uint32_t)cmd&~0x10UL; if ((cm&0xFUL)==0x1UL) { osi_WrStr("RR", 3ul); osi_WrStr((char *)(tmp = (char)(48UL+(cmd>>5)),&tmp), 1u/1u); } else if ((cm&0xFUL)==0x5UL) { osi_WrStr("RNR", 4ul); osi_WrStr((char *)(tmp = (char)(48UL+(cmd>>5)),&tmp), 1u/1u); } else if ((cm&0xFUL)==0x9UL) { osi_WrStr("REJ", 4ul); osi_WrStr((char *)(tmp = (char)(48UL+(cmd>>5)),&tmp), 1u/1u); } else if ((cm&0x1UL)==0UL) { osi_WrStr("I", 2ul); osi_WrStr((char *)(tmp = (char)(48UL+(cmd>>5)),&tmp), 1u/1u); osi_WrStr((char *)(tmp = (char)(48UL+(cmd>>1&7UL)),&tmp), 1u/1u); } else if (cm==0x3UL) osi_WrStr("UI", 3ul); else if (cm==0xFUL) osi_WrStr("DM", 3ul); else if (cm==0x2FUL) osi_WrStr("SABM", 5ul); else if (cm==0x43UL) osi_WrStr("DISC", 5ul); else if (cm==0x63UL) osi_WrStr("UA", 3ul); else if (cm==0x87UL) osi_WrStr("FRMR", 5ul); else WrHexCap(cmd, 2UL, 0UL); strncpy(PF,"v^-+",4u); if (com==0UL || com==3UL) osi_WrStr("v1", 3ul); else osi_WrStr((char *) &PF[(com&1UL)+2UL*(uint32_t)((0x10UL & (uint32_t)cmd)!=0)], 1u/1u); } /* end Showctl() */ static void ShowFrame(char f[], uint32_t f_len, uint32_t len, char port) { uint32_t i; char d; char v; X2C_PCOPY((void **)&f,f_len); osi_WrStr((char *) &port, 1u/1u); i = 0UL; while (!((uint32_t)(uint8_t)f[i]&1)) { ++i; if (i>len) { osi_WrStrLn(" no ax.25 (no address end mark)", 32ul); goto label; } } /* no address end mark found */ if (i%7UL!=6UL) { osi_WrStrLn(" no ax.25 (address field size not multiples of 7)", 50ul); goto label; } /* address end not modulo 7 error */ osi_WrStr(":fm ", 5ul); ShowCall(f, f_len, 7UL); osi_WrStr(" to ", 5ul); ShowCall(f, f_len, 0UL); i = 14UL; v = 1; while (i+6UL=128UL && (((uint32_t)(uint8_t)f[i+6UL]&1) || (uint32_t)(uint8_t) f[i+13UL]<128UL)) osi_WrStr("*", 2ul); i += 7UL; } Showctl((uint32_t)((0x80U & (uint8_t)(uint8_t)f[6UL])!=0)+2UL*(uint32_t)((0x80U & (uint8_t)(uint8_t) f[13UL])!=0), (uint32_t)(uint8_t)f[i]); ++i; if (i0UL) { if (*join) { if (loraprotocols_verb) osi_WrStrLn("ax25 part 2", 12ul); if (rawlen+2UL<=raw_len-1) { aprsstr_AppCRC(raw, raw_len, (int32_t)rawlen); if (raw[rawlen]==axpart[253UL] && raw[rawlen+1UL]==axpart[254UL]) { /* join hash fits */ for (i = 0UL; i<=252UL; i++) { fb[i] = axpart[i]; } /* end for */ tmp = rawlen-1UL; i = 0UL; if (i<=tmp) for (;; i++) { fb[i+253UL] = raw[i]; if (i==tmp) break; } /* end for */ *fblen = rawlen+253UL; } else if (loraprotocols_verb) osi_WrStrLn("ax25 chain hash missmatch", 26ul); } } *join = 0; if (*fblen==0UL) { i = 0UL; while (i=13UL) && i<=69UL) { /* is pr, not 2 to 10 shift up calls */ if (rawlen==255UL) { tmp = axpart_len-1; i = 0UL; if (i<=tmp) for (;; i++) { axpart[i] = raw[i]; if (i==tmp) break; } /* end for */ *join = 1; if (loraprotocols_verb) osi_WrStrLn("ax25 part 1", 12ul); } else { tmp = rawlen-1UL; i = 0UL; if (i<=tmp) for (;; i++) { fb[i] = raw[i]; if (i==tmp) break; } /* end for */ *fblen = rawlen; } } } } if (*fblen>=2UL) { if (loraprotocols_verb) { osi_WrStr("AX25:", 6ul); ShowFrame(fb, fb_len, *fblen-2UL, port); } } X2C_PFREE(raw); } /* end decodepr() */ #define loraprotocols_KNOTS 1.851984 #define loraprotocols_FEET 3.2808398950131 #define loraprotocols_WKNOTS 1.609 /* wx knots */ static char num(uint32_t n) { return (char)(n%10UL+48UL); } /* end num() */ static uint32_t dao91(double x) /* radix91(xx/1.1) of dddmm.mmxx */ { double a; a = fabs(x); return (((uint32_t)X2C_TRUNCC((a-(double)(uint32_t)X2C_TRUNCC(a,0UL,X2C_max_longcard))*6.E+5,0UL, X2C_max_longcard)%100UL)*20UL+11UL)/22UL; } /* end dao91() */ static void encodeaprs(uint32_t ipnum, uint32_t udpport, char udp2, char tocall[], uint32_t tocall_len, const char mycall[], uint32_t mycall_len, const char comment0[], uint32_t comment_len, const char sym[], uint32_t sym_len, const double lat, const double long0, float speed, float course, float alt, float clb0, float snrr, float gust, float temp, float hum, float baro, int32_t fecc, char dcd, uint32_t txd, float level, int32_t afc, uint32_t qual) { char h[501]; char b[501]; uint32_t n; uint32_t i; double a; float v; char sig; X2C_PCOPY((void **)&tocall,tocall_len); b[0] = 0; aprsstr_Append(b, 501ul, mycall, mycall_len); aprsstr_Append(b, 501ul, ">", 2ul); aprsstr_Append(b, 501ul, tocall, tocall_len); aprsstr_Append(b, 501ul, ":!", 3ul); i = aprsstr_Length(b, 501ul); a = fabs(lat); n = osi_realcard((float)a); b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; n = osi_realcard((float)((a-(double)n)*6000.0)); b[i] = num(n/1000UL); ++i; b[i] = num(n/100UL); ++i; b[i] = '.'; ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; if (lat>=0.0) b[i] = 'N'; else b[i] = 'S'; ++i; b[i] = sym[0UL]; ++i; a = fabs(long0); n = osi_realcard((float)a); b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; n = osi_realcard((float)((a-(double)n)*6000.0)); b[i] = num(n/1000UL); ++i; b[i] = num(n/100UL); ++i; b[i] = '.'; ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; if (long0>=0.0) b[i] = 'E'; else b[i] = 'W'; ++i; b[i] = sym[1UL]; ++i; if (speed>0.0f || gust<1000.0f) { n = osi_realcard(course+1.5f); b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; b[i] = '/'; ++i; if (sym[0UL]=='/' && sym[1UL]=='_') n = osi_realcard(speed*6.2150403977626E-1f+0.5f); else n = osi_realcard(speed*5.3996146834962E-1f+0.5f); b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; if (gust<1000.0f) { n = osi_realcard(gust*6.2150403977626E-1f+0.5f); b[i] = 'g'; ++i; b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; } } if ((float)fabs(temp)<1000.0f) { v = temp*1.8f+32.0f; sig = v<0.0f; n = osi_realcard((float)fabs(v)+0.5f); b[i] = 't'; ++i; if (sig) b[i] = '-'; else b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; } if (hum<=100.0f) { b[i] = 'h'; ++i; n = osi_realcard(hum+0.5f); if (n==100UL) n = 0UL; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; } if (baro<10000.0f) { b[i] = 'b'; ++i; n = osi_realcard(baro*10.0f+0.5f); b[i] = num(n/10000UL); ++i; b[i] = num(n/1000UL); ++i; b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; } if (alt>0.5f) { b[i] = '/'; ++i; b[i] = 'A'; ++i; b[i] = '='; ++i; n = osi_realcard((float)fabs(alt*3.2808398950131f+0.5f)); if (alt>=0.0f) b[i] = num(n/100000UL); else b[i] = '-'; ++i; b[i] = num(n/10000UL); ++i; b[i] = num(n/1000UL); ++i; b[i] = num(n/100UL); ++i; b[i] = num(n/10UL); ++i; b[i] = num(n); ++i; } b[i] = '!'; /* DAO */ ++i; b[i] = 'w'; ++i; b[i] = (char)(33UL+dao91(lat)); ++i; b[i] = (char)(33UL+dao91(long0)); ++i; b[i] = '!'; ++i; b[i] = 0; if ((float)fabs(clb0)<1000.0f) { aprsstr_Append(b, 501ul, "Clb=", 5ul); aprsstr_FixToStr(clb0, 2UL, h, 501ul); aprsstr_Append(b, 501ul, h, 501ul); aprsstr_Append(b, 501ul, "m/s ", 5ul); } aprsstr_Append(b, 501ul, comment0, comment_len); sendaxudp2(ipnum, udpport, udp2, b, 501ul, aprsstr_Length(b, 501ul), (int32_t)txd, level, snrr, afc, (int32_t)qual, 1, dcd); X2C_PFREE(tocall); } /* end encodeaprs() */ static void decodemeshcore(uint32_t ipnum, uint32_t udpport, char udp2, char raw[], uint32_t raw_len, uint32_t dlen, uint32_t fecbits, uint32_t txd, float level, float snrr, int32_t qual, int32_t afc) { uint32_t pl; uint32_t hl; uint32_t j; uint32_t i; uint32_t app0; uint32_t ph; uint32_t pt; uint32_t pr; double long0; double lat; char sym[301]; char ms[301]; char nt[301]; char pp[301]; char ps[301]; char pn[301]; char h[301]; char s[301]; char trace; uint32_t tmp; X2C_PCOPY((void **)&raw,raw_len); /* 0e00d29c136d Meshcore:DIRECT/ACK Path: 26 02 1d f2 78 db 4a620000000000729272 Meshcore:DIRECT/TRACE Path:1d f2 26 02 f7 fb f1 17 b1b4000000000072a972 Meshcore:DIRECT/TRACE Path:f7 fb 26 02 31 f4 dc 78 744f000000000072a973a972 26 02 34 16 cc dd f1bd00000000000ec00e Meshcore:DIRECT/TRACE Path:34 16 Meshcore:DIRECT/TRACE Path:31 f4 26 02 3a00 f60d8d26000000000072b002b072 26 03 3a00e2 f60d8d26000000000072b002b072 i 26 04 3a00e2e6 f60d8d26000000000072b002b072 */ strncpy(ps,"Meshcore:",301u); pr = (uint32_t)(uint8_t)raw[0UL]; i = 1UL; trace = 0; switch (pr&3UL) { case 0UL: i = 5UL; aprsstr_Append(ps, 301ul, "TRANSPORT_FLOOD", 16ul); break; case 1UL: aprsstr_Append(ps, 301ul, "FLOOD", 6ul); break; case 2UL: aprsstr_Append(ps, 301ul, "DIRECT", 7ul); break; default:; i = 5UL; aprsstr_Append(ps, 301ul, "TRANSPORT_DIRECT", 17ul); break; } /* end switch */ aprsstr_Append(ps, 301ul, "/", 2ul); pt = pr/4UL&15UL; switch (pt) { case 0UL: aprsstr_Append(ps, 301ul, "REQ", 4ul); break; case 1UL: aprsstr_Append(ps, 301ul, "RESPONSE", 9ul); break; case 2UL: aprsstr_Append(ps, 301ul, "TXT_MSG", 8ul); break; case 3UL: aprsstr_Append(ps, 301ul, "ACK", 4ul); break; case 4UL: aprsstr_Append(ps, 301ul, "ADVERT", 7ul); break; case 5UL: aprsstr_Append(ps, 301ul, "GRP_TXT", 8ul); break; case 6UL: aprsstr_Append(ps, 301ul, "GRP_DATA", 9ul); break; case 7UL: aprsstr_Append(ps, 301ul, "ANON_REQ", 9ul); break; case 8UL: aprsstr_Append(ps, 301ul, "PATH", 5ul); break; case 9UL: aprsstr_Append(ps, 301ul, "TRACE", 6ul); trace = (pr&3UL)==2UL; break; case 10UL: aprsstr_Append(ps, 301ul, "MULTIPART", 10ul); break; case 11UL: aprsstr_Append(ps, 301ul, "CONTROL", 8ul); break; case 15UL: aprsstr_Append(ps, 301ul, "RAW_CUSTOM", 11ul); break; default:; aprsstr_Append(ps, 301ul, "UNDEF", 6ul); break; } /* end switch */ if (i==5UL) { aprsstr_Append(ps, 301ul, " TRANS:", 8ul); i = 1UL; while (i<5UL) { HexStr((uint32_t)(uint8_t)raw[i], 2UL, 2UL, 1, h, 301ul); aprsstr_Append(ps, 301ul, h, 301ul); ++i; } } pl = (uint32_t)(uint8_t)raw[i]; ++i; if (trace) aprsstr_Append(ps, 301ul, " Trace[", 8ul); else aprsstr_Append(ps, 301ul, " Path[", 7ul); j = 0UL; hl = pl; while (hl>0UL && i0UL) aprsstr_Append(ps, 301ul, ",", 2ul); HexStr((uint32_t)(uint8_t)raw[i], 2UL, 2UL, 1, h, 301ul); aprsstr_Append(ps, 301ul, h, 301ul); } ++j; ++i; --hl; } aprsstr_Append(ps, 301ul, "]", 2ul); pp[0] = 0; pn[0] = 0; nt[0] = 0; if (pt==4UL) { /* advert */ ph = i; aprsstr_Append(ps, 301ul, " Hash:", 7ul); HexStr((uint32_t)(uint8_t)raw[i], 2UL, 2UL, 1, h, 301ul); aprsstr_Append(ps, 301ul, h, 301ul); i += 32UL; aprsstr_Append(ps, 301ul, " Time:", 7ul); aprsstr_DateToStr((uint32_t)(uint8_t)raw[i]+(uint32_t)(uint8_t)raw[i+1UL]*256UL+(uint32_t)(uint8_t) raw[i+2UL]*65536UL+(uint32_t)(uint8_t)raw[i+3UL]*16777216UL, h, 301ul); aprsstr_Append(ps, 301ul, h, 301ul); i += 68UL; app0 = (uint32_t)(uint8_t)raw[i]; ++i; aprsstr_Append(ps, 301ul, " App:", 6ul); HexStr(app0, 2UL, 2UL, 1, h, 301ul); aprsstr_Append(ps, 301ul, h, 301ul); lat = 0.0; long0 = 0.0; if (i+8UL90.0 || fabs(long0)>180.0) { lat = 0.0; long0 = 0.0; } } if (app0>=128UL) { /* bit 7 = has name */ strncpy(pn," [",301u); j = i; while (j0UL) { mtype = (uint32_t)(uint8_t)text[0UL]/32UL; /* MHDR */ switch (mtype) { case 0UL: osi_WrStr("Join-request", 13ul); break; case 1UL: osi_WrStr("Join-accept", 12ul); break; case 2UL: osi_WrStr("Unconfirmed Data Up", 20ul); break; case 3UL: osi_WrStr("Unconfirmed Data Down", 22ul); break; case 4UL: osi_WrStr("Confirmed Data Up", 18ul); break; case 5UL: osi_WrStr("Confirmed Data Down", 20ul); break; case 6UL: osi_WrStr("Rejoin-request", 15ul); break; default:; osi_WrStr("Proprietary", 12ul); break; } /* end switch */ osi_WrStr(" RFU:", 6ul); osic_WrINT32((uint32_t)(uint8_t)text[0UL]/4UL&7UL, 1UL); osi_WrStr(" Major:", 8ul); osic_WrINT32((uint32_t)(uint8_t)text[0UL]&3UL, 1UL); if (mtype==0UL && textlen>=18UL) { WH(" AppEUI:", 9ul, text, text_len, 1UL, 8UL); WH(" DevEUI:", 9ul, text, text_len, 9UL, 16UL); WH(" DevNonce:", 11ul, text, text_len, 17UL, 18UL); } else if (mtype==1UL && textlen>=12UL) { WH(" DevNonce:", 11ul, text, text_len, 1UL, 3UL); WH(" NetID:", 8ul, text, text_len, 4UL, 6UL); WH(" DevAddr:", 10ul, text, text_len, 7UL, 10UL); WH(" DLSettings:", 13ul, text, text_len, 11UL, 11UL); WH(" RxDelay:", 10ul, text, text_len, 12UL, 12UL); if (textlen>34UL) WH(" CFList:", 9ul, text, text_len, 13UL, 28UL); } else if (mtype>=2UL && mtype<=5UL) { /* data frame */ fctl = (uint32_t)(uint8_t)text[5UL]; WH(" DevAddr:", 10ul, text, text_len, 1UL, 4UL); osi_WrStr(" ADR:", 6ul); osic_WrINT32(fctl/128UL, 1UL); if ((mtype&1)) osi_WrStr(" RFU:", 6ul); else osi_WrStr(" ADRACKReq:", 12ul); osic_WrINT32(fctl/64UL&1UL, 1UL); osi_WrStr(" ACK:", 6ul); osic_WrINT32(fctl/32UL&1UL, 1UL); if ((mtype&1)) osi_WrStr(" FPending:", 11ul); else osi_WrStr(" ClassB:", 9ul); osic_WrINT32(fctl/16UL&1UL, 1UL); osi_WrStr(" FOptsLen:", 11ul); osic_WrINT32(fctl&15UL, 1UL); osi_WrStr(" FCnt:", 7ul); osic_WrINT32((uint32_t)(uint8_t)text[6UL]+(uint32_t)(uint8_t)text[7UL]*256UL, 1UL); p = 0UL; if ((fctl&15UL)>0UL) { osi_WrStr(" FOpts:", 8ul); while (p<(fctl&15UL) && p+8UL=6UL) { osi_WrStr(" FPort:", 8ul); osic_WrINT32((uint32_t)(uint8_t)text[p+8UL], 1UL); if (p+9UL<=textlen-5UL) WH(" Payload:", 10ul, text, text_len, p+9UL, textlen-5UL); WH(" MIC:", 6ul, text, text_len, textlen-4UL, textlen-1UL); } } osi_WrStrLn("", 1ul); } } /* end decodelorawan() */ static void WH0(const char title[], uint32_t title_len, const char text[], uint32_t text_len, uint32_t from, uint32_t too, char revers) { uint32_t j; uint32_t i; osi_WrStr(title, title_len); i = from; while (i<=too) { j = i; if (revers) j = (too-i)+from; if (j<=text_len-1) WrHex((uint32_t)(uint8_t)text[j], 2UL, 0UL); ++i; } } /* end WH() */ static void decodemeshtastic(const char text[], uint32_t text_len, uint32_t textlen) { uint32_t i; if (textlen>=15UL && loraprotocols_verb) { WH0("Meshtastic: Dest:", 18ul, text, text_len, 0UL, 3UL, 1); WH0(" SRC:", 6ul, text, text_len, 4UL, 7UL, 1); WH0(" MID:", 6ul, text, text_len, 8UL, 11UL, 1); i = (uint32_t)(uint8_t)text[12UL]; osi_WrStr(" HopLim:", 9ul); osic_WrINT32(i&7UL, 1UL); osi_WrStr(" HopStart:", 11ul); osic_WrINT32(i/32UL, 1UL); if ((i/8UL&1)) osi_WrStr(" WantAck", 9ul); if ((i/16UL&1)) osi_WrStr(" viaMQTT", 9ul); WH0(" Hash:", 7ul, text, text_len, 13UL, 13UL, 0); WH0(" NextHop:", 10ul, text, text_len, 14UL, 14UL, 0); WH0(" RelayNode:", 12ul, text, text_len, 15UL, 15UL, 0); WH0(" Msg:[", 7ul, text, text_len, 16UL, textlen-1UL, 0); osi_WrStrLn("]", 2ul); } } /* end decodemeshtastic() */ struct FANETPR; struct FANETPR { float lat; float long0; float speed; float clb0; float gust; float temp; float hum; float baro; uint32_t alt; uint32_t dir; char scall[9]; char s[251]; }; static void wcsv(struct FANETPR * fp, uint32_t n, const char s[], uint32_t s_len) { uint32_t i; i = 0UL; while (n>0UL) { if (i>=s_len-1) return; if (s[i]==',') --n; ++i; } while (i<=s_len-1 && s[i]!=',') { aprsstr_Append(fp->s, 251ul, (char *) &s[i], 1u/1u); ++i; } } /* end wcsv() */ static void spd(uint32_t i, float scale, float * v) { if (i>=128UL) i = (i&127UL)*5UL; *v = (float)i*scale; } /* end spd() */ static void clb(char text[], uint32_t text_len, uint32_t p, float * v) { uint32_t i; int32_t ii; i = (uint32_t)(uint8_t)text[p]; ii = (int32_t)(i&127UL); if (ii>=64L) ii = 64L-ii; if (i>=128UL) ii = ii*5L; *v = (float)ii*0.1f; } /* end clb() */ static void latlong(char text[], uint32_t text_len, uint32_t p, float scale, float * d) { int32_t ii; ii = (int32_t)((uint32_t)(uint8_t)text[p+2UL]*65536UL+(uint32_t)(uint8_t)text[p+1UL]*256UL+(uint32_t) (uint8_t)text[p]); if (ii>=8388608L) ii = 8388608L-ii; *d = (float)ii*scale; } /* end latlong() */ static void pos(char text[], uint32_t text_len, uint32_t * p, float * lat, float * long0) { latlong(text, text_len, *p, 1.0728923030706E-5f, lat); /* lat */ *p += 3UL; latlong(text, text_len, *p, 2.1457846061412E-5f, long0); /* long */ *p += 3UL; } /* end pos() */ static void apppos(float lat, float long0, char s[], uint32_t s_len) { char h[100]; if (lat!=0.0f && long0!=0.0f) { aprsstr_FixToStr(lat, 6UL, h, 100ul); aprsstr_Append(s, s_len, h, 100ul); aprsstr_Append(s, s_len, ",", 2ul); aprsstr_FixToStr(long0, 6UL, h, 100ul); aprsstr_Append(s, s_len, h, 100ul); aprsstr_Append(s, s_len, " ", 2ul); } } /* end apppos() */ static void manufact(struct FANETPR * fp, uint32_t b) { char s[100]; s[0] = 0; if (b==1UL) strncpy(s,"Skytraxx",100u); else if (b==3UL) strncpy(s,"BitBroker.eu",100u); else if (b==4UL) strncpy(s,"AirWhere",100u); else if (b==5UL) strncpy(s,"Windline",100u); else if (b==6UL) strncpy(s,"Burnair.ch",100u); else if (b==7UL) strncpy(s,"SoftRF",100u); else if (b==8UL) strncpy(s,"GXAircom",100u); else if (b==9UL) strncpy(s,"Airtribune",100u); else if (b==16UL) strncpy(s,"alfapilot",100u); else if (b==17UL) { /*ELSIF b=011H THEN s:="FANET+ (incl FLARM. Currently Skytraxx, Naviter, and Skybean)"; */ strncpy(s,"FANET+",100u); } else if (b==10UL) strncpy(s,"FLARM",100u); else if (b==32UL) strncpy(s,"XC Tracer",100u); else if (b==224UL) strncpy(s,"OGN Tracker",100u); else if (b==228UL) strncpy(s,"4aviation",100u); else if (b==250UL) strncpy(s,"Various",100u); else if (b==251UL) { /*ELSIF b=0FBH THEN s:="Espressif based base stations, address is last 2bytes of MAC"; */ strncpy(s,"Espressif based base station",100u); } else if (b==252UL) strncpy(s,"Unregistered Devices",100u); else if (b==253UL) strncpy(s,"Unregistered Devices",100u); else if (b==254UL) strncpy(s,"[Multicast]",100u); aprsstr_Append(fp->s, 251ul, "fw:[", 5ul); aprsstr_Append(fp->s, 251ul, s, 100ul); aprsstr_Append(fp->s, 251ul, "] ", 3ul); } /* end manufact() */ static void srcdest(char text[], uint32_t text_len, uint32_t b, char s[], uint32_t s_len) { char h[10]; s[0UL] = 0; aprsstr_Append(s, s_len, "FNT", 4ul); HexStr((uint32_t)(uint8_t)text[b]*65536UL+(uint32_t)(uint8_t)text[b+1UL]+(uint32_t)(uint8_t) text[b+2UL]*256UL, 6UL, 7UL, 1, h, 10ul); aprsstr_Append(s, s_len, h, 10ul); } /* end srcdest() */ static void alt25(struct FANETPR * fp, char text[], uint32_t text_len, uint32_t p) { int32_t ii; char h[10]; ii = (int32_t)(uint32_t)(uint8_t)text[p]; if (ii>=128L) ii = 128L-ii; ii = (ii+109L)*125L; aprsstr_Append(fp->s, 251ul, "alt:", 5ul); aprsstr_IntToStr(ii, 1UL, h, 10ul); aprsstr_Append(fp->s, 251ul, h, 10ul); aprsstr_Append(fp->s, 251ul, "m ", 3ul); } /* end alt25() */ #define loraprotocols_ATY "Other,Paraglider,Hangglider,Balloon,Glider,Powered Aircraft,Helicopter,UAV" #define loraprotocols_GNDVEHICLES "Other,Walking,Vehicle,Bike,Boot,Need a ride,Landed well,Need technical support,Need m\ edical help,Distress call,Distress call automatically" #define loraprotocols_LANDM "Text,Line,Arrow,Area,Area Filled,Circle,Circle Filled,3D Line,3D Area,3D Cylinder" #define loraprotocols_LANDLAYER "Info,Warning,Keep out,Touch down,No airspace warn zone" #define loraprotocols_prATY "///g/g/O/g/\'/X/n" #define loraprotocols_prGNDVEHICLES "///[/>/b/s/e\\o/\'/a\\!\\!" static void decodefanet(const char text[], uint32_t text_len, uint32_t textlen, uint32_t ipnum, uint32_t udpport, char udp2, int32_t txd, float level, float snrr, int32_t afc, int32_t qual, int32_t fecc, int32_t cr, char dcd) { struct FANETPR fp; uint32_t i; uint32_t p; int32_t ii; uint32_t ss; uint8_t s; uint8_t typ; char unicast; char signature; char exth; char h[100]; float long0; float lat; char sym[2]; strncpy(sym,"//",2u); memset((char *) &fp,(char)0,sizeof(struct FANETPR)); aprsstr_FixToStr(snrr, 2UL, h, 100ul); aprsstr_Append(fp.s, 251ul, "snr:", 5ul); aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, "dB ", 4ul); if (fecc>0L) { aprsstr_IntToStr(fecc, 1UL, h, 100ul); aprsstr_Append(fp.s, 251ul, "fec:", 5ul); aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, " ", 2ul); } aprsstr_IntToStr(cr, 1UL, h, 100ul); aprsstr_Append(fp.s, 251ul, "cr:", 4ul); aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, " ", 2ul); if (loraprotocols_jmhz!=0.0f) { aprsstr_FixToStr(loraprotocols_jmhz, 4UL, h, 100ul); aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, "MHz ", 5ul); } fp.gust = 10000.0f; fp.clb0 = 10000.0f; fp.dir = 10000UL; fp.temp = 10000.0f; fp.hum = 10000.0f; fp.baro = 1.E+5f; typ = (uint8_t)(uint8_t)text[0UL]; exth = (0x80U & typ)!=0; if (exth) aprsstr_Append(fp.s, 251ul, "Ext Header ", 12ul); if ((0x40U & typ)) aprsstr_Append(fp.s, 251ul, "Forward ", 9ul); srcdest(text, text_len, 1UL, fp.scall, 9ul); manufact(&fp, (uint32_t)(uint8_t)text[1UL]); p = 4UL; if (exth) { s = (uint8_t)(uint8_t)text[p]; aprsstr_Append(fp.s, 251ul, "ACK ", 5ul); if ((s&0xC0U)==0U) aprsstr_Append(fp.s, 251ul, "none ", 6ul); else if ((s&0xC0U)==0x40U) aprsstr_Append(fp.s, 251ul, "requested ", 11ul); else if ((s&0xC0U)==0x80U) aprsstr_Append(fp.s, 251ul, "requested via forward ", 23ul); else aprsstr_Append(fp.s, 251ul, "unknown ", 9ul); unicast = (0x20U & s)!=0; if (unicast) aprsstr_Append(fp.s, 251ul, "unicast ", 9ul); else aprsstr_Append(fp.s, 251ul, "broadcast ", 11ul); signature = (0x10U & s)!=0; if ((0x8U & s)) aprsstr_Append(fp.s, 251ul, "geobased fwd ", 14ul); ++p; if (unicast) { aprsstr_Append(fp.s, 251ul, "Dst:", 5ul); srcdest(text, text_len, p, h, 100ul); aprsstr_Append(fp.s, 251ul, h, 100ul); manufact(&fp, p); p += 3UL; } if (signature) { aprsstr_Append(fp.s, 251ul, "Signature:", 11ul); HexStr((uint32_t)(uint8_t)text[p+3UL]*16777216UL+(uint32_t)(uint8_t)text[p+2UL]*65536UL+(uint32_t) (uint8_t)text[p+1UL]*256UL+(uint32_t)(uint8_t)text[p], 8UL, 9UL, 0, h, 100ul); aprsstr_Append(fp.s, 251ul, h, 100ul); p += 4UL; } } typ = typ&0x3FU; if (typ==0U) aprsstr_Append(fp.s, 251ul, "no payload ", 12ul); else if (typ==0x1U) { /* tracking */ aprsstr_Append(fp.s, 251ul, "tracking:", 10ul); pos(text, text_len, &p, &fp.lat, &fp.long0); ss = (uint32_t)((uint32_t)(uint8_t)text[p+1UL]*256UL+(uint32_t)(uint8_t)text[p]); p += 2UL; if ((0x8000UL & ss)) aprsstr_Append(fp.s, 251ul, "Online Tracking ", 17ul); i = (uint32_t)(X2C_LSH(ss,32,-12)&0x7UL); wcsv(&fp, i, "Other,Paraglider,Hangglider,Balloon,Glider,Powered Aircraft,Helicopter,UAV", 75ul); if (i*2UL>=0UL) { sym[0U] = "///g/g/O/g/\'/X/n"[i*2UL]; sym[1U] = "///g/g/O/g/\'/X/n"[i*2UL+1UL]; } aprsstr_Append(fp.s, 251ul, " ", 2ul); i = (uint32_t)(ss&0x7FFUL); if ((0x800UL & ss)) i = i*4UL; fp.alt = i; spd((uint32_t)(uint8_t)text[p], 0.5f, &fp.speed); /* speed */ ++p; clb(text, text_len, p, &fp.clb0); ++p; fp.dir = ((uint32_t)(uint8_t)text[p]*360UL)/256UL; ++p; if (p=64L) ii = -ii; if (i>=128UL) ii = ii*4L; aprsstr_FixToStr((float)ii*0.25f, 2UL, h, 100ul); /* turn rate */ aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, "deg/s ", 7ul); } if (p=64L) ii = -ii; if (i>=128UL) ii = ii*4L; aprsstr_Append(fp.s, 251ul, "QNE:", 5ul); aprsstr_FixToStr((float)ii, 2UL, h, 100ul); /* QNE */ aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, " ", 2ul); } } else if (typ==0x2U) { /* text */ aprsstr_Append(fp.s, 251ul, "Message:", 9ul); while (p=0UL) { sym[0U] = "///[/>/b/s/e\\o/\'/a\\!\\!"[i*2UL]; sym[1U] = "///[/>/b/s/e\\o/\'/a\\!\\!"[i*2UL+1UL]; } } else if (typ==0x6U) { /* remote config */ aprsstr_Append(fp.s, 251ul, "Remote configuration:", 22ul); i = (uint32_t)(uint8_t)text[p]; ++p; if (i==0UL) { aprsstr_Append(fp.s, 251ul, "Acknowledge configuration ", 27ul); HexStr((uint32_t)(uint8_t)text[p], 2UL, 3UL, 0, h, 100ul); aprsstr_Append(fp.s, 251ul, h, 100ul); ++p; } else if (i==1UL) { aprsstr_Append(fp.s, 251ul, "Request ", 9ul); HexStr((uint32_t)(uint8_t)text[p], 2UL, 3UL, 0, h, 100ul); aprsstr_Append(fp.s, 251ul, h, 100ul); ++p; } else if (i==2UL) { pos(text, text_len, &p, &lat, &long0); alt25(&fp, text, text_len, p); ++p; aprsstr_IntToStr((int32_t)(((uint32_t)(uint8_t)text[p]*360UL)/256UL), 1UL, h, 100ul); /* heading */ aprsstr_Append(fp.s, 251ul, h, 100ul); aprsstr_Append(fp.s, 251ul, "deg ", 5ul); ++p; } else if (i>=4UL && i<=8UL) { aprsstr_Append(fp.s, 251ul, "Geofence ", 10ul); alt25(&fp, text, text_len, p); ++p; } else if (i>=9UL && i<=33UL) { /*- */ aprsstr_Append(fp.s, 251ul, "Broadcast Reply ", 17ul); } } else if (typ==0x5U) { /*- */ /* remote config */ aprsstr_Append(fp.s, 251ul, "Landmarks ", 11ul); s = (uint8_t)(uint32_t)(uint8_t)text[p]; ++p; wcsv(&fp, (uint32_t)(s&0xFU), "Text,Line,Arrow,Area,Area Filled,Circle,Circle Filled,3D Line,3D Area,3D Cylinder\ ", 82ul); aprsstr_Append(fp.s, 251ul, " ", 2ul); s = (uint8_t)(uint32_t)(uint8_t)text[p]; ++p; wcsv(&fp, (uint32_t)(s&0xFU), "Info,Warning,Keep out,Touch down,No airspace warn zone", 55ul); aprsstr_Append(fp.s, 251ul, " ", 2ul); if ((0x10U & s)) ++p; } /*- */ /*- */ i = aprsstr_Length(fp.s, 251ul); while (i>0UL && fp.s[i-1UL]==' ') --i; if (i<=250UL) fp.s[i] = 0; if ((fp.lat!=0.0f || fp.long0!=0.0f) && udpport) { encodeaprs(ipnum, udpport, udp2, "FANET", 6ul, fp.scall, 9ul, fp.s, 251ul, sym, 2ul, (double)fp.lat, (double)fp.long0, fp.speed, (float)fp.dir, (float)fp.alt, fp.clb0, snrr, fp.gust, fp.temp, fp.hum, fp.baro, fecc, dcd, (uint32_t)txd, level, afc, (uint32_t)qual); } if (loraprotocols_verb) { osi_WrStr("Fanet:", 7ul); osi_WrStr(fp.scall, 9ul); osi_WrStr(" ", 2ul); h[0] = 0; apppos(fp.lat, fp.long0, h, 100ul); osi_WrStr(h, 100ul); if (fp.alt) { osic_WrINT32(fp.alt, 1UL); osi_WrStr("m ", 3ul); } if (fp.speed!=0.0f) { osic_WrFixed(fp.speed, 1L, 1UL); osi_WrStr("km/h ", 6ul); } if (fp.dir<=360UL) { osic_WrINT32(fp.dir, 1UL); osi_WrStr("deg ", 5ul); } if ((float)fabs(fp.clb0)<1000.0f) { osi_WrStr("Clb:", 5ul); osic_WrFixed(fp.clb0, 1L, 1UL); osi_WrStr("m/s ", 5ul); } osi_WrStrLn(fp.s, 251ul); } } /* end decodefanet() */ static char hasjunk(const char h[], uint32_t h_len) { return (h[0UL]=='<' && h[1UL]=='\377') && h[2UL]=='\001'; } /* end hasjunk() */ extern void loraprotocols_sendframe(char text[], uint32_t text_len, uint32_t textlen, struct loraprotocols_FPAR fpar, char axpart[], uint32_t axpart_len, char notchlist[], uint32_t notchlist_len, char finf[], uint32_t finf_len, uint32_t ipnum, uint32_t ipnumraw, uint32_t udpport, uint32_t udprawport, char udp2) { uint32_t axlen; uint32_t i; int32_t ret; char s[512]; struct loraprotocols_FPAR * anonym; uint32_t tmp; X2C_PCOPY((void **)&text,text_len); X2C_PCOPY((void **)&axpart,axpart_len); { /* with */ struct loraprotocols_FPAR * anonym = &fpar; if (loraprotocols_verb && (!loraprotocols_quietcrc || anonym->hascrc && anonym->crc)) { aprsstr_TimeToStr(osic_time()%86400UL, s, 512ul); osi_WrStr(s, 512ul); osi_WrStr(" ", 2ul); osic_WrINT32(anonym->cfgsf, 1UL); if (anonym->invers) osi_WrStr("-", 2ul); else osi_WrStr(":", 2ul); osic_WrINT32(anonym->label, 1UL); osi_WrStr(":", 2ul); if (anonym->illid==0UL) { osi_WrStr("id:", 4ul); WrHexCap(anonym->idfound, 2UL, 0UL); } else { osi_WrStr(" ill-id:", 9ul); WrHexCap(anonym->illid*256UL+anonym->idfound, 4UL, 0UL); } osi_WrStr(" cr:", 5ul); osic_WrINT32(anonym->cr, 1UL); osi_WrStr(" len:", 6ul); osic_WrINT32(textlen, 1UL); if (anonym->dcdlost) osi_WrStr(" dcd-lost", 10ul); osi_WrStr(" crc:", 6ul); if (anonym->hascrc) { if (anonym->crc) osi_WrStr("ok", 3ul); else osi_WrStr("err", 4ul); } else osi_WrStr("no", 3ul); osi_WrStr(" lev:", 6ul); osic_WrFixed(anonym->level, 1L, 1UL); osi_WrStr("(", 2ul); osic_WrFixed(anonym->minlev, 1L, 1UL); osi_WrStr("/", 2ul); osic_WrFixed(anonym->maxlev, 1L, 1UL); osi_WrStr(")dB snr:", 9ul); osic_WrFixed(anonym->snr, 1L, 1UL); osi_WrStr("dB nf:", 7ul); osic_WrFixed(anonym->nf, 1L, 1UL); osi_WrStr("(", 2ul); osic_WrFixed(anonym->minnf, 1L, 1UL); osi_WrStr("/", 2ul); osic_WrFixed(anonym->maxnf, 1L, 1UL); osi_WrStr(")dB txd:", 9ul); osic_WrINT32(anonym->txd, 1UL); osi_WrStr(" t:", 4ul); osic_WrINT32(anonym->frametime, 1UL); osi_WrStr(" q:", 4ul); osic_WrINT32(anonym->qual, 1UL); osi_WrStr("%", 2ul); if (anonym->fasecorrs) { osi_WrStr(" fc:", 5ul); osic_WrINT32(anonym->fasecorrs, 1UL); } if (anonym->fecbits>0UL) { osi_WrStr(" fec:", 6ul); osic_WrINT32(anonym->fecbits, 1UL); } osi_WrStr(" afc:", 6ul); osic_WrINT32((uint32_t)anonym->truedf, 1UL); osi_WrStr("Hz", 3ul); osi_WrStr(" dre:", 6ul); osic_WrFixed(anonym->drift, 1L, 1UL); osi_WrStr("ppm", 4ul); if (loraprotocols_jmhz!=0.0f) { osi_WrStr(" ", 2ul); osic_WrFixed(loraprotocols_jmhz, 3L, 1UL); osi_WrStr("MHz", 4ul); } osi_WrStr(notchlist, notchlist_len); osi_WrStrLn("", 1ul); osi_WrStr("[", 2ul); osi_WrStr(finf, finf_len); osi_WrStr("]", 2ul); if (textlen>0UL) { tmp = textlen-1UL; i = 0UL; if (i<=tmp) for (;; i++) { if (loraprotocols_allwaysascii) { WrChHex(text[i]); } else WrHex((uint32_t)(uint8_t)text[i], 2UL, 0UL); if (i==tmp) break; } /* end for */ } osi_WrStrLn("", 1ul); } if (((anonym->synfilter&255UL)/16UL==0UL || anonym->idfound/16UL==(anonym->synfilter&255UL)/16UL) && ((anonym->synfilter&15UL)==0UL || (anonym->idfound&15UL)==(anonym->synfilter&15UL))) { if ((!anonym->ax25long && udprawport) && (!anonym->udpcrcok || (anonym->hascrc && anonym->crc) && !anonym->dcdlost)) { ret = udpsend(loraprotocols_udpsock, text, (int32_t)textlen, udprawport, ipnumraw); } } else if (loraprotocols_verb && (!loraprotocols_quietcrc || anonym->hascrc && anonym->crc)) { osi_WrStr("frame deleted, wrong sync word ", 32ul); WrHexCap(anonym->idfound, 2UL, 0UL); osi_WrStrLn("", 1ul); } if (loraprotocols_jdests0 || loraprotocols_jpipename[0UL]) { sendjson(loraprotocols_jdests0, anonym->idfound, text, text_len, textlen, anonym->hascrc, anonym->crc, anonym->invers, anonym->cfgsf, anonym->cr, anonym->txd, anonym->frametime, anonym->level, anonym->nf, anonym->maxnf, anonym->snr, anonym->drift, anonym->truedf, (int32_t)anonym->qual, (int32_t)anonym->fecbits); } if ((anonym->hascrc && anonym->crc) && textlen>0UL) { if (anonym->idfound==52UL) decodelorawan(text, text_len, textlen); if ((anonym->idfound&255UL)==18UL) { decodepr(text, text_len, textlen, '0', &anonym->axjoin, axpart, axpart_len, s, 512ul, &axlen); /* PR */ if ((anonym->ax25long && axlen>0UL) && udprawport) { ret = udpsend(loraprotocols_udpsock, s, (int32_t)axlen, udprawport, ipnumraw); } else if ((udpport && !anonym->dcdlost) && (!anonym->needsjunk || hasjunk(text, text_len))) { sendaxudp2(ipnum, udpport, udp2, text, text_len, textlen, (int32_t)anonym->txd, anonym->level, anonym->snr, anonym->truedf, (int32_t)anonym->qual, 0, anonym->dcd); } if (!hasjunk(text, text_len)) { decodemeshcore(ipnum, udpport, udp2, text, text_len, textlen, anonym->fecbits, anonym->txd, anonym->level, anonym->snr, (int32_t)anonym->qual, anonym->truedf); /* else might be aprs */ } } if ((anonym->idfound&255UL)==43UL) { decodemeshtastic(text, text_len, textlen); /* MESHTASTIC */ } if (anonym->idfound==241UL) { decodefanet(text, text_len, textlen, ipnum, udpport, udp2, (int32_t)anonym->txd, anonym->level, anonym->snr, anonym->truedf, (int32_t)anonym->qual, (int32_t)anonym->fecbits, (int32_t)anonym->cr, anonym->dcd); /* FANET */ } } if ((loraprotocols_newline && loraprotocols_verb) && (!loraprotocols_quietcrc || anonym->hascrc && anonym->crc)) { osi_WrStrLn("", 1ul); } } X2C_PFREE(text); X2C_PFREE(axpart); } /* end sendframe() */ extern void loraprotocols_BEGIN(void) { static int loraprotocols_init = 0; if (loraprotocols_init) return; loraprotocols_init = 1; aprsstr_BEGIN(); osi_BEGIN(); loraprotocols_allwaysascii = 0; loraprotocols_jsonfd = -1L; } uint32_t loraprotocols_BWTAB[10] = {64UL,48UL,32UL,24UL,16UL,12UL,8UL,4UL,2UL,1UL}; uint32_t loraprotocols_bwnum; int32_t loraprotocols_jsonfd; int32_t loraprotocols_udpsock; char loraprotocols_jpipename[1024]; char loraprotocols_hamview; char loraprotocols_allwaysascii; char loraprotocols_verb; char loraprotocols_verb2; char loraprotocols_newline; char loraprotocols_quietcrc; float loraprotocols_jmhz; loraprotocols_pJDESTS loraprotocols_jdests0;