kopia lustrzana https://github.com/sp9skp/spdxl
6926 wiersze
206 KiB
C
6926 wiersze
206 KiB
C
/*
|
|
* dxlAPRS toolchain
|
|
*
|
|
* Copyright (C) Christian Rabler <oe5dxl@oevsv.at>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
|
|
#define X2C_int32
|
|
#define X2C_index32
|
|
#ifndef aprsdecode_H_
|
|
#include "aprsdecode.h"
|
|
#endif
|
|
#define aprsdecode_C_
|
|
#ifndef aprspos_H_
|
|
#include "aprspos.h"
|
|
#endif
|
|
#ifndef xosi_H_
|
|
#include "xosi.h"
|
|
#endif
|
|
#ifndef osi_H_
|
|
#include "osi.h"
|
|
#endif
|
|
#include <osic.h>
|
|
#ifndef tcp_H_
|
|
#include "tcp.h"
|
|
#endif
|
|
#ifndef udp_H_
|
|
#include "udp.h"
|
|
#endif
|
|
#ifndef aprsstr_H_
|
|
#include "aprsstr.h"
|
|
#endif
|
|
#ifndef useri_H_
|
|
#include "useri.h"
|
|
#endif
|
|
#ifndef aprstext_H_
|
|
#include "aprstext.h"
|
|
#endif
|
|
|
|
aprsdecode_SET256 aprsdecode_SYMTABLE = {0x00000000UL,0x03FF8000UL,
|
|
0x17FFFFFEUL,0x07FFFFFEUL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL,0x00000000UL};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t aprsdecode_systime;
|
|
uint32_t aprsdecode_realtime;
|
|
uint32_t aprsdecode_lastlooped;
|
|
uint32_t aprsdecode_rxidle;
|
|
char aprsdecode_quit;
|
|
char aprsdecode_verb;
|
|
|
|
|
|
struct aprsdecode__D0 aprsdecode_click;
|
|
struct aprspos_POSITION aprsdecode_mappos;
|
|
int32_t aprsdecode_inittilex;
|
|
int32_t aprsdecode_inittiley;
|
|
int32_t aprsdecode_initxsize;
|
|
int32_t aprsdecode_initysize;
|
|
int32_t aprsdecode_parmzoom;
|
|
int32_t aprsdecode_initzoom;
|
|
float aprsdecode_finezoom;
|
|
float aprsdecode_parmfinezoom;
|
|
char aprsdecode_mapdir[1025];
|
|
aprsdecode_pMOUNTAIN aprsdecode_mountains;
|
|
|
|
|
|
struct aprsdecode__D1 aprsdecode_lums;
|
|
|
|
|
|
struct aprsdecode__D2 aprsdecode_tracenew;
|
|
aprsdecode_pTXMESSAGE aprsdecode_txmessages;
|
|
aprsdecode_pMSGFIFO aprsdecode_msgfifo0;
|
|
float aprsdecode_spikesens;
|
|
float aprsdecode_maxhop;
|
|
aprsdecode_pOPHIST aprsdecode_ophist2;
|
|
aprsdecode_pOPHIST aprsdecode_ophist0;
|
|
|
|
|
|
struct aprsdecode__D3 aprsdecode_gateways[10];
|
|
aprsdecode_pTCPSOCK aprsdecode_tcpsocks;
|
|
struct aprsdecode_UDPSOCK aprsdecode_udpsocks0[4];
|
|
uint32_t aprsdecode_lasttcptx;
|
|
uint32_t aprsdecode_lastanyudprx;
|
|
uint32_t aprsdecode_lastpurge;
|
|
uint32_t aprsdecode_lasttcprx;
|
|
aprsdecode_FRAMEBUF aprsdecode_testbeaconbuf;
|
|
struct xosi_PROCESSHANDLE aprsdecode_serialpid;
|
|
struct xosi_PROCESSHANDLE aprsdecode_serialpid2;
|
|
struct xosi_PROCESSHANDLE aprsdecode_maploadpid;
|
|
/* connect to aprs-is gateway and decode data for archive and map by OE5DXL */
|
|
/*FROM Storage IMPORT ALLOCATE, DEALLOCATE; */
|
|
/*FROM TimeConv IMPORT time; */
|
|
#define aprsdecode_CALLLEN 7
|
|
|
|
#define aprsdecode_HASHSIZE 65536
|
|
|
|
#define aprsdecode_GATECONNDELAY 30
|
|
|
|
#define aprsdecode_WATCH 180
|
|
|
|
#define aprsdecode_QMAXTIME 15
|
|
|
|
#define aprsdecode_MIDMOD 62
|
|
|
|
#define aprsdecode_HOLDT 0x0FFFFFFFF
|
|
|
|
#define aprsdecode_BEEPINVERVALL 5
|
|
/* min time between beeps */
|
|
|
|
#define aprsdecode_TICKEROFFTIME 60
|
|
/* switch off window headline ticker after no data*/
|
|
|
|
#define aprsdecode_cUSERMESSAGE ":"
|
|
|
|
#define aprsdecode_cTHIRDPARTY "}"
|
|
|
|
#define aprsdecode_DUPHASHSIZE 65536
|
|
|
|
#define aprsdecode_PINGTIMEOUT 10
|
|
/* ping-pong ping timeout */
|
|
|
|
#define aprsdecode_PINGINTERVALL 20
|
|
/* ping-pong ping intervall */
|
|
|
|
#define aprsdecode_DIRIN ">"
|
|
|
|
#define aprsdecode_DIROUT "<"
|
|
|
|
#define aprsdecode_DIRHAVIT "-"
|
|
|
|
#define aprsdecode_DIRJUNC "#"
|
|
|
|
#define aprsdecode_cMSGACK "{"
|
|
|
|
typedef uint32_t CHSET[4];
|
|
|
|
|
|
struct BEACON {
|
|
uint32_t bintervall;
|
|
aprsdecode_FILENAME bfile;
|
|
uint32_t btime;
|
|
};
|
|
|
|
typedef char TICKERCALL[31];
|
|
|
|
struct UDPSET;
|
|
|
|
|
|
struct UDPSET {
|
|
int32_t txd;
|
|
int32_t level;
|
|
int32_t quali;
|
|
};
|
|
|
|
static char sentemptymsg;
|
|
|
|
static uint32_t uptime;
|
|
|
|
static aprsdecode_FILENAME logframename;
|
|
/* netbeaconintervall, */
|
|
|
|
static uint32_t beaconrandomstart;
|
|
|
|
static uint32_t nextbeep;
|
|
|
|
static uint32_t rfbecondone;
|
|
|
|
static uint32_t lastmsgtx;
|
|
|
|
static uint32_t qwatchtime;
|
|
|
|
static uint32_t connecttime;
|
|
|
|
static uint32_t cycleservers;
|
|
|
|
static uint32_t qas;
|
|
|
|
static uint32_t qasc;
|
|
|
|
static int32_t logframes;
|
|
/* passwd : ARRAY[0..5] OF CHAR; */
|
|
|
|
static uint32_t trygate;
|
|
/* actudp : pUDPSOCK; */
|
|
|
|
static aprsdecode_MONCALL ungate[7];
|
|
|
|
static uint32_t timehash[65536];
|
|
|
|
static uint32_t rfbeacont;
|
|
|
|
static uint32_t dupetime;
|
|
|
|
static uint32_t msgmid;
|
|
|
|
static TICKERCALL frameticker[20];
|
|
|
|
/* calls in ticker headline */
|
|
static uint32_t tickertime;
|
|
|
|
static float maxspeed;
|
|
|
|
static uint16_t crctable12[256];
|
|
|
|
|
|
static void Err(const char text[], uint32_t text_len)
|
|
{
|
|
osi_WrStr("aprsmap: ", 10ul);
|
|
osi_WrStr(text, text_len);
|
|
osi_WrStrLn(" error abort", 13ul);
|
|
X2C_ABORT();
|
|
} /* end Err() */
|
|
|
|
|
|
extern uint32_t aprsdecode_trunc(float r)
|
|
{
|
|
if (r<=0.0f) return 0UL;
|
|
else if (r>=2.E+9f) return 2000000000UL;
|
|
else return (uint32_t)X2C_TRUNCC(r,0UL,X2C_max_longcard);
|
|
return 0;
|
|
} /* end trunc() */
|
|
|
|
|
|
extern float aprsdecode_floor(float r)
|
|
{
|
|
float f;
|
|
f = (float)osi_realint(r);
|
|
if (f>r) f = f-1.0f;
|
|
return f;
|
|
} /* end floor() */
|
|
|
|
|
|
static float sqr(float x)
|
|
{
|
|
return x*x;
|
|
} /* end sqr() */
|
|
|
|
|
|
extern void aprsdecode_posinval(struct aprspos_POSITION * pos)
|
|
{
|
|
pos->long0 = 0.0f;
|
|
pos->lat = 0.0f;
|
|
} /* end posinval() */
|
|
|
|
|
|
static char Watchclock(uint32_t * t, uint32_t intervall)
|
|
{
|
|
uint32_t tn;
|
|
if (intervall>0UL || *t==0UL) {
|
|
/* send once */
|
|
tn = aprsdecode_realtime;
|
|
if (*t<=tn) {
|
|
*t += intervall;
|
|
if (*t<=tn) *t = tn+intervall;
|
|
return 1;
|
|
}
|
|
if (*t>tn+intervall) *t = tn+intervall;
|
|
}
|
|
return 0;
|
|
} /* end Watchclock() */
|
|
|
|
|
|
extern void aprsdecode_beeplim(int32_t lev, uint32_t hz, uint32_t ms)
|
|
/* beep with minimum quiet time */
|
|
{
|
|
if (aprsdecode_realtime>=nextbeep) {
|
|
xosi_beep(lev, hz, ms);
|
|
nextbeep = aprsdecode_realtime+5UL;
|
|
}
|
|
} /* end beeplim() */
|
|
|
|
|
|
static void filepath(char s[], uint32_t s_len)
|
|
/* get path out of path + filename */
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
i = 0UL;
|
|
j = 0UL;
|
|
while (i<s_len-1 && s[i]) {
|
|
if (s[i]=='/' || s[i]=='/') j = i;
|
|
++i;
|
|
}
|
|
s[j] = 0;
|
|
} /* end filepath() */
|
|
|
|
|
|
static void alfanum(char s[], uint32_t s_len)
|
|
/* clean received call to filename */
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char c;
|
|
i = 0UL;
|
|
j = 0UL;
|
|
while (i<s_len-1 && s[i]) {
|
|
c = X2C_CAP(s[i]);
|
|
if ((((((((uint8_t)c>='A' && (uint8_t)c<='Z' || (uint8_t)
|
|
c>='0' && (uint8_t)c<='9') || c=='-') || c=='+') || c=='_')
|
|
|| c=='(') || c==')') || c=='=') {
|
|
s[j] = c;
|
|
++j;
|
|
}
|
|
++i;
|
|
}
|
|
if (j<=s_len-1) s[j] = 0;
|
|
} /* end alfanum() */
|
|
|
|
|
|
static int32_t GetNum(char h[], uint32_t h_len, uint32_t * p,
|
|
uint32_t * n)
|
|
{
|
|
char ok0;
|
|
int32_t GetNum_ret;
|
|
X2C_PCOPY((void **)&h,h_len);
|
|
h[h_len-1] = 0;
|
|
*n = 0UL;
|
|
ok0 = 0;
|
|
while ((uint8_t)h[*p]>='0' && (uint8_t)h[*p]<='9') {
|
|
ok0 = 1;
|
|
*n = ( *n*10UL+(uint32_t)(uint8_t)h[*p])-48UL;
|
|
++*p;
|
|
}
|
|
if (!ok0) {
|
|
GetNum_ret = -1L;
|
|
goto label;
|
|
}
|
|
GetNum_ret = 0L;
|
|
label:;
|
|
X2C_PFREE(h);
|
|
return GetNum_ret;
|
|
} /* end GetNum() */
|
|
|
|
|
|
static void parms(void)
|
|
{
|
|
char h[4096];
|
|
char err;
|
|
char lasth;
|
|
uint32_t n;
|
|
uint32_t i;
|
|
uint32_t gatecnt;
|
|
int32_t ii;
|
|
err = 0;
|
|
aprsdecode_verb = 0;
|
|
gatecnt = 0UL;
|
|
for (;;) {
|
|
osi_NextArg(h, 4096ul);
|
|
if (h[0U]==0) break;
|
|
if ((h[0U]=='-' && h[1U]) && h[2U]==0) {
|
|
lasth = h[1U];
|
|
if (lasth=='x') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n>=30UL) {
|
|
aprsdecode_initxsize = (int32_t)n;
|
|
}
|
|
else Err("-x xsize", 9ul);
|
|
}
|
|
else if (lasth=='y') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n>=20UL) {
|
|
aprsdecode_initysize = (int32_t)n;
|
|
}
|
|
else Err("-y xsize", 9ul);
|
|
}
|
|
else if (lasth=='z') {
|
|
osi_NextArg(h, 4096ul);
|
|
if (!aprsstr_StrToFix(&aprsdecode_parmfinezoom, h,
|
|
4096ul) || aprsdecode_parmfinezoom<=1.0f) {
|
|
Err("-z zoomlevel", 13ul);
|
|
}
|
|
n = aprsdecode_trunc(aprsdecode_parmfinezoom);
|
|
aprsdecode_parmfinezoom = (1.0f+aprsdecode_parmfinezoom)
|
|
-(float)n;
|
|
aprsdecode_parmzoom = (int32_t)n;
|
|
}
|
|
else if (lasth=='m') {
|
|
osi_NextArg(h, 4096ul);
|
|
if (!aprsstr_StrToFix(&aprsdecode_mappos.long0, h, 4096ul)) {
|
|
Err("-m long lat", 12ul);
|
|
}
|
|
osi_NextArg(h, 4096ul);
|
|
if (!aprsstr_StrToFix(&aprsdecode_mappos.lat, h, 4096ul)) {
|
|
Err("-m long lat", 12ul);
|
|
}
|
|
aprsdecode_mappos.long0 = aprspos_rad0(aprsdecode_mappos.long0);
|
|
aprsdecode_mappos.lat = aprspos_rad0(aprsdecode_mappos.lat);
|
|
}
|
|
else if (lasth=='c') osi_NextArg(aprsdecode_lums.configfn, 257ul);
|
|
else if (lasth=='g') {
|
|
osi_NextArg(h, 4096ul);
|
|
if (gatecnt>9UL) Err("-g gateway table full", 22ul);
|
|
h[4095U] = 0;
|
|
if (h[0U]=='[') {
|
|
ii = 1L;
|
|
while (h[ii] && h[ii]!=']') ++ii;
|
|
if (h[ii]!=']' || h[ii+1L]!=':') Err("-g [url]:port", 14ul);
|
|
h[ii] = 0;
|
|
i = 1UL;
|
|
while (i<=4095UL) {
|
|
h[i-1UL] = h[i];
|
|
++i;
|
|
}
|
|
}
|
|
else ii = aprsstr_InStr(h, 4096ul, ":", 2ul);
|
|
if (ii>=0L) h[ii] = 0;
|
|
aprsstr_Assign(aprsdecode_gateways[gatecnt].url, 256ul, h,
|
|
4096ul);
|
|
if (ii>0L) {
|
|
/* port number */
|
|
++ii;
|
|
i = 0UL;
|
|
while (ii<=4095L) {
|
|
h[i] = h[ii];
|
|
++i;
|
|
++ii;
|
|
}
|
|
}
|
|
else osi_NextArg(h, 4096ul);
|
|
h[4095U] = 0;
|
|
ii = aprsstr_InStr(h, 4096ul, "#", 2ul);
|
|
if (ii>=0L) h[ii] = 0;
|
|
if (h[0U]==0) Err("-g url:port", 12ul);
|
|
aprsstr_Assign(aprsdecode_gateways[gatecnt].port, 6ul, h,
|
|
4096ul);
|
|
if (ii>0L) {
|
|
/* we have a filter string */
|
|
++ii;
|
|
i = 0UL;
|
|
while (ii<=4095L) {
|
|
if (h[ii]==',') h[ii] = ' ';
|
|
h[i] = h[ii];
|
|
++i;
|
|
++ii;
|
|
}
|
|
aprsstr_Assign(aprsdecode_gateways[gatecnt].filterst, 256ul,
|
|
h, 4096ul);
|
|
}
|
|
++gatecnt;
|
|
}
|
|
else {
|
|
if (lasth=='h') {
|
|
osi_WrStrLn(" -c <configfilename>", 21ul);
|
|
osi_WrStrLn(" -g <url>:<port>#<filters> connect to APRS-IS gat\
|
|
eway, repeat -g to other", 74ul);
|
|
osi_WrStrLn(" gateways write favorites first fo\
|
|
r 1 activ link to the best", 76ul);
|
|
osi_WrStrLn(" reachable and a polling link to r\
|
|
evert immediately to preferred again", 86ul);
|
|
osi_WrStrLn(" -g www.db0anf.de:14580#m/300 -g 1\
|
|
27.0.0.1:3000 -g [::1]:3000", 77ul);
|
|
osi_WrStrLn(" <filters> text sent to out connec\
|
|
ted server -f m/50", 68ul);
|
|
osi_WrStrLn(" if blanks dont pass parameter set\
|
|
tings use , (-f m/30,-d/CW)", 77ul);
|
|
osi_WrStrLn(" ipv6 if enabled by kernel",
|
|
42ul);
|
|
osi_WrStrLn(" -h this", 21ul);
|
|
osi_WrStrLn(" -M <ip>:<dport>/<lport>[+<byte/s>[:<radius>]]",
|
|
47ul);
|
|
osi_WrStrLn(" udp rf port (monitor frame format\
|
|
) for local (t)rx", 67ul);
|
|
osi_WrStrLn(" <dport>:<lport> read from any ip,\
|
|
dport=0 no tx", 64ul);
|
|
osi_WrStrLn(" +byte/s enable inet to rf for ser\
|
|
vices like WLNK, WHO-IS", 73ul);
|
|
osi_WrStrLn(" :radius enable all inet to rf gat\
|
|
e (from km around digi)", 73ul);
|
|
osi_WrStrLn(" repeat -M for each radio port wit\
|
|
h a tx", 56ul);
|
|
osi_WrStrLn(" -o <outfile> out file, delete after read",
|
|
44ul);
|
|
osi_WrStrLn(" -R same as -M but axudp format",
|
|
44ul);
|
|
osi_WrStrLn(" -v show frames and analytics on stdo\
|
|
ut", 52ul);
|
|
osic_WrLn();
|
|
X2C_ABORT();
|
|
}
|
|
if (lasth=='C') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=100UL) {
|
|
aprsdecode_lums.centering = (int32_t)n;
|
|
}
|
|
else Err("-C center%", 11ul);
|
|
}
|
|
else if (lasth=='X') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.sym = (int32_t)n;
|
|
}
|
|
else Err("-X symbollumen", 15ul);
|
|
}
|
|
else if (lasth=='O') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.obj = (int32_t)n;
|
|
}
|
|
else Err("-O objectlumen", 15ul);
|
|
}
|
|
else if (lasth=='W') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.waypoint = (int32_t)n;
|
|
}
|
|
else Err("-W waypointlumen", 17ul);
|
|
}
|
|
else if (lasth=='A') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.text = (int32_t)n;
|
|
}
|
|
else Err("-A textlumen", 13ul);
|
|
}
|
|
else if (lasth=='T') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.track = (int32_t)n;
|
|
}
|
|
else Err("-T tracklumen", 14ul);
|
|
}
|
|
else if (lasth=='F') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
|
|
aprsdecode_lums.firstdim = n*60UL;
|
|
}
|
|
else Err("-F fadetime (min)", 18ul);
|
|
}
|
|
else if (lasth=='V') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
|
|
aprsdecode_lums.fps = (int32_t)n;
|
|
}
|
|
else Err("-V fps", 7ul);
|
|
}
|
|
else if (lasth=='B') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
|
|
aprsdecode_lums.maxdim = n*60UL;
|
|
}
|
|
else Err("-B blanktime (min)", 19ul);
|
|
}
|
|
else if (lasth=='P') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n>0UL) {
|
|
aprsdecode_lums.purgetime = n*60UL;
|
|
}
|
|
else Err("-P purgetime (min)", 19ul);
|
|
}
|
|
else if (lasth=='r') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.rf = (int32_t)n;
|
|
}
|
|
else Err("-r rftracklumen", 16ul);
|
|
}
|
|
else if (lasth=='o') {
|
|
osi_NextArg(h, 4096ul);
|
|
i = 0UL;
|
|
if (GetNum(h, 4096ul, &i, &n)>=0L && n<=1024UL) {
|
|
aprsdecode_lums.map = (int32_t)n;
|
|
}
|
|
else Err("-o maplumen", 12ul);
|
|
}
|
|
else if (lasth=='v') aprsdecode_verb = 1;
|
|
else err = 1;
|
|
}
|
|
}
|
|
else {
|
|
/*h[0]:=0C;*/
|
|
err = 1;
|
|
}
|
|
if (err) break;
|
|
}
|
|
if (err) {
|
|
aprsstr_Append(h, 4096ul, " ? use -h", 10ul);
|
|
Err(h, 4096ul);
|
|
}
|
|
} /* end parms() */
|
|
|
|
|
|
static void getval(const char s[], uint32_t s_len, uint32_t * i,
|
|
int32_t * v)
|
|
{
|
|
char m;
|
|
++*i;
|
|
*v = 0L;
|
|
m = s[*i]=='-';
|
|
if (m) ++*i;
|
|
while ((*i<s_len-1 && (uint8_t)s[*i]>='0') && (uint8_t)s[*i]<='9') {
|
|
*v = *v*10L+(int32_t)((uint32_t)(uint8_t)s[*i]-48UL);
|
|
++*i;
|
|
}
|
|
while (*i<s_len-1 && (uint8_t)s[*i]>' ') ++*i;
|
|
while (*i<s_len-1 && s[*i]==' ') ++*i;
|
|
if (m) *v = -*v;
|
|
} /* end getval() */
|
|
|
|
|
|
static void decodeudp2(const char ub[], uint32_t ub_len,
|
|
struct UDPSET * modeminfo)
|
|
{
|
|
uint32_t i;
|
|
int32_t res;
|
|
if (ub[0UL] && ub[1UL]) {
|
|
i = 2UL;
|
|
while (i<ub_len-1 && ub[i]) {
|
|
switch ((unsigned)ub[i]) {
|
|
case 'T':
|
|
getval(ub, ub_len, &i, &res);
|
|
modeminfo->txd = res;
|
|
break;
|
|
case 'V':
|
|
getval(ub, ub_len, &i, &res);
|
|
modeminfo->level = res;
|
|
break;
|
|
case 'Q':
|
|
getval(ub, ub_len, &i, &res);
|
|
modeminfo->quali = res;
|
|
break;
|
|
default:;
|
|
getval(ub, ub_len, &i, &res);
|
|
break;
|
|
} /* end switch */
|
|
}
|
|
}
|
|
} /* end decodeudp2() */
|
|
|
|
|
|
static char getudp(uint32_t usock, aprsdecode_FRAMEBUF buf,
|
|
struct UDPSET * modeminfo, aprsstr_GHOSTSET ghostset)
|
|
{
|
|
uint32_t fromport;
|
|
uint32_t ipn;
|
|
char crc2;
|
|
char crc1;
|
|
int32_t len;
|
|
uint32_t mlen;
|
|
aprsdecode_FRAMEBUF mbuf;
|
|
char udp2[100];
|
|
aprsstr_GHOSTSET tmp;
|
|
ghostset = (uint32_t *)memcpy(tmp,ghostset,36u);
|
|
if ((int32_t)aprsdecode_udpsocks0[usock].fd<0L) return 0;
|
|
len = udpreceive(aprsdecode_udpsocks0[usock].fd, buf, 512L, &fromport,
|
|
&ipn);
|
|
if ((len>2L && len<512L) && (!aprsdecode_udpsocks0[usock].checkip || aprsdecode_udpsocks0[usock].ip==ipn)
|
|
) {
|
|
/*WrInt(udpsend(usock^.fd, buf, len, usock^.dport, usock^.ip), 1);
|
|
WrStrLn(" us"); */
|
|
memset((char *)modeminfo,(char)0,sizeof(struct UDPSET));
|
|
buf[len] = 0;
|
|
if (aprsdecode_udpsocks0[usock].rawread) {
|
|
len -= 2L;
|
|
crc1 = buf[len];
|
|
crc2 = buf[len+1L];
|
|
aprsstr_AppCRC(buf, 512ul, len);
|
|
if (crc1!=buf[len] || crc2!=buf[len+1L]) {
|
|
if (aprsdecode_verb) osi_WrStrLn(" axudp crc error", 17ul);
|
|
buf[0UL] = 0;
|
|
}
|
|
else {
|
|
if (buf[0UL]=='\001') {
|
|
aprsstr_extrudp2(buf, 512ul, udp2, 100ul, &len);
|
|
decodeudp2(udp2, 100ul, modeminfo);
|
|
}
|
|
/*WrInt(modeminfo.txd, 5); WrInt(modeminfo.level, 5);
|
|
WrInt(modeminfo.quali, 5); WrStrLn(" modem"); */
|
|
aprsstr_raw2mon(buf, 512ul, mbuf, 512ul, (uint32_t)len, &mlen,
|
|
ghostset);
|
|
memcpy(buf,mbuf,512u);
|
|
}
|
|
}
|
|
}
|
|
else return 0;
|
|
return 1;
|
|
} /* end getudp() */
|
|
|
|
|
|
static int32_t Gettcp(int32_t fd, aprsdecode_FRAMEBUF line,
|
|
aprsdecode_FRAMEBUF buf, int32_t * pos)
|
|
{
|
|
int32_t j;
|
|
int32_t i;
|
|
int32_t len;
|
|
int32_t tmp;
|
|
i = *pos;
|
|
if (i>=512L) i = 0L;
|
|
/*
|
|
len:=RdBin(fd, line, SIZE(line)-i);
|
|
IF len<=0 THEN RETURN -1 END;
|
|
(* disconnected *)
|
|
*/
|
|
/*
|
|
IF len<0 THEN len:=0 END;
|
|
*/
|
|
len = readsock(fd, line, 512L-i);
|
|
if (len<0L) return -1L;
|
|
if (*pos>=512L) {
|
|
/* hunt mode */
|
|
i = 0L;
|
|
while (i<len && line[i]!='\012') ++i;
|
|
if (i>=len) return 0L;
|
|
/* no line start found */
|
|
*pos = 0L;
|
|
++i;
|
|
j = 0L;
|
|
while (i<len) {
|
|
line[j] = line[i];
|
|
++j;
|
|
++i;
|
|
}
|
|
len = j;
|
|
}
|
|
if (*pos>0L) {
|
|
for (i = len-1L; i>=0L; i--) {
|
|
line[i+*pos] = line[i]; /* move up new */
|
|
} /* end for */
|
|
tmp = *pos-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
line[i] = buf[i]; /* ins buf before */
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
len += *pos;
|
|
*pos = 0L;
|
|
}
|
|
i = 0L;
|
|
while (i<len && line[i]!='\012') ++i;
|
|
if (i>=len) {
|
|
/* no line end found */
|
|
while (*pos<len) {
|
|
buf[*pos] = line[*pos]; /* move to buf */
|
|
++*pos;
|
|
}
|
|
len = 0L;
|
|
}
|
|
else {
|
|
j = i+1L;
|
|
while (j<len) {
|
|
buf[*pos] = line[j]; /* move rest to buf */
|
|
++*pos;
|
|
++j;
|
|
}
|
|
len = i;
|
|
}
|
|
line[len] = 0;
|
|
return len;
|
|
} /* end Gettcp() */
|
|
|
|
|
|
static void saybusy(int32_t * fd, char s[], uint32_t s_len)
|
|
/* send good by text and close tcp */
|
|
{
|
|
int32_t res;
|
|
X2C_PCOPY((void **)&s,s_len);
|
|
if ((int32_t)*fd>=0L) {
|
|
res = sendsock(*fd, s, (int32_t)aprsstr_Length(s, s_len));
|
|
osic_CloseSock(*fd);
|
|
*fd = -1L;
|
|
}
|
|
X2C_PFREE(s);
|
|
} /* end saybusy() */
|
|
|
|
|
|
static void saylinkbad(int32_t s)
|
|
{
|
|
char hh[101];
|
|
char h[101];
|
|
strncpy(h,"AprsIs uplink delays ",101u);
|
|
aprsstr_IntToStr(s, 1UL, hh, 101ul);
|
|
aprsstr_Append(h, 101ul, hh, 101ul);
|
|
aprsstr_Append(h, 101ul, "s", 2ul);
|
|
useri_textautosize(0L, 5L, 4UL, 10UL, 'r', h, 101ul);
|
|
} /* end saylinkbad() */
|
|
|
|
|
|
static void WatchTXQ(aprsdecode_pTCPSOCK sock)
|
|
{
|
|
int32_t sent;
|
|
int32_t j;
|
|
int32_t i;
|
|
int32_t rb;
|
|
int32_t acked;
|
|
int32_t qb;
|
|
char rest;
|
|
int32_t tmp;
|
|
qb = getunack(sock->fd); /* tcp unack sendqueue in byte */
|
|
if (sock->lastping==0UL && qb==-1L) {
|
|
/* windoof */
|
|
sock->lastping = 1UL; /* switch on ping-pong mode */
|
|
return;
|
|
}
|
|
/*
|
|
configbool(fALLOWGATE, FALSE);
|
|
textautosize(0, 5, 6, 5, "r",
|
|
"TCP-Stack on this OS not usable for Igate,
|
|
gateing switched off");
|
|
END;
|
|
*/
|
|
sent = (int32_t)(sock->txbytes-sock->qwatch.lasttb);
|
|
/* last second sent bytes */
|
|
if (qb<=0L || sent<0L) sock->qwatch.qsize = 0L;
|
|
else {
|
|
/* we have unack bytes */
|
|
acked = (sock->qwatch.lastqb-qb)+sent; /* acked bytes in last s */
|
|
j = 0L;
|
|
rest = 0;
|
|
tmp = sock->qwatch.qsize-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
rb = sock->qwatch.txbyte[i]-acked;
|
|
sock->qwatch.txbyte[j] = rb;
|
|
if (rb>0L) rest = 1;
|
|
else acked = -rb;
|
|
if (rest) {
|
|
acked = 0L;
|
|
++j;
|
|
}
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
sock->qwatch.qsize = j;
|
|
if (sock->qwatch.qsize<=59L) {
|
|
sock->qwatch.txbyte[sock->qwatch.qsize] = sent;
|
|
++sock->qwatch.qsize;
|
|
if (sock->qwatch.qsize>1L) saylinkbad(sock->qwatch.qsize);
|
|
if (sock->qwatch.qsize>15L) {
|
|
stoptxrx(sock->fd, 2L); /* delete unsent data */
|
|
saybusy(&sock->fd, "\015\012", 3ul); /* close tcp immediately */
|
|
}
|
|
}
|
|
}
|
|
/* sock^.slowlink:=TRUE;
|
|
(* for log message *) */
|
|
sock->qwatch.lastqb = qb;
|
|
sock->qwatch.lasttb = sock->txbytes;
|
|
} /* end WatchTXQ() */
|
|
|
|
|
|
static void tickermon(const char port[], uint32_t port_len,
|
|
char dir, uint32_t ot, const char s[],
|
|
uint32_t s_len)
|
|
{
|
|
struct aprsdecode_DAT dat;
|
|
TICKERCALL h2;
|
|
TICKERCALL h1;
|
|
TICKERCALL h;
|
|
uint32_t cnt;
|
|
uint32_t i;
|
|
uint32_t tmp;
|
|
cnt = (uint32_t)useri_conf2int(useri_fWRTICKER, 0UL, 0L, 99L, 1L);
|
|
if (cnt==0UL && ot==0UL) cnt = 1UL;
|
|
if ((ot!=1UL && cnt>0UL) && aprsdecode_Decode(s, s_len, &dat)>=0L) {
|
|
h2[0] = 0;
|
|
if (cnt==1UL) {
|
|
if (ot==0UL) strncpy(h2,"New User: ",31u);
|
|
else if (ot<=aprsdecode_realtime) {
|
|
strncpy(h2,"since ",31u);
|
|
ot = aprsdecode_realtime-ot;
|
|
if (ot<180UL) {
|
|
aprsstr_IntToStr((int32_t)ot, 3UL, h1, 31ul);
|
|
aprsstr_Append(h1, 31ul, "s: ", 4ul);
|
|
}
|
|
else if (ot<10790UL) {
|
|
aprsstr_IntToStr((int32_t)((ot+10UL)/60UL), 3UL, h1, 31ul);
|
|
aprsstr_Append(h1, 31ul, "m: ", 4ul);
|
|
}
|
|
else {
|
|
aprsstr_IntToStr((int32_t)((ot+10UL)/3600UL), 3UL, h1,
|
|
31ul);
|
|
aprsstr_Append(h1, 31ul, "h: ", 4ul);
|
|
}
|
|
aprsstr_Append(h2, 31ul, h1, 31ul);
|
|
}
|
|
}
|
|
aprsstr_Assign(h1, 31ul, port, port_len);
|
|
h1[0U] = X2C_CAP(h1[0U]);
|
|
aprsstr_Append(h2, 31ul, h1, 31ul);
|
|
aprsstr_Append(h2, 31ul, (char *) &dir, 1u/1u);
|
|
aprsstr_Append(h2, 31ul, dat.symcall, 9ul);
|
|
if (dat.wx.temp!=1.E+6f) {
|
|
aprsstr_FixToStr(aprstext_FtoC(dat.wx.temp), 2UL, h, 31ul);
|
|
aprsstr_Append(h2, 31ul, " ", 2ul);
|
|
aprsstr_Append(h2, 31ul, h, 31ul);
|
|
aprsstr_Append(h2, 31ul, "C", 2ul);
|
|
}
|
|
else if ((dat.altitude<X2C_max_longint && dat.altitude>=1000L)
|
|
&& dat.altitude>=useri_conf2int(useri_fALTMIN, 0UL, -10000L,
|
|
65535L, -10000L)) {
|
|
aprsstr_Append(h2, 31ul, " ", 2ul);
|
|
aprsstr_IntToStr(dat.altitude, 1UL, h, 31ul);
|
|
aprsstr_Append(h2, 31ul, h, 31ul);
|
|
aprsstr_Append(h2, 31ul, "m", 2ul);
|
|
}
|
|
else if (dat.speed>0UL && dat.speed<2147483647UL) {
|
|
useri_confstr(useri_fKMH, h1, 31ul);
|
|
if (h1[0U]) {
|
|
aprsstr_IntToStr((int32_t)aprsdecode_trunc((float)
|
|
dat.speed*1.852f), 1UL, h, 31ul);
|
|
aprsstr_Append(h2, 31ul, " ", 2ul);
|
|
aprsstr_Append(h2, 31ul, h, 31ul);
|
|
aprsstr_Append(h2, 31ul, h1, 31ul);
|
|
}
|
|
}
|
|
for (i = 19UL; i>=1UL; i--) {
|
|
memcpy(frameticker[i],frameticker[i-1UL],31u);
|
|
} /* end for */
|
|
memcpy(frameticker[0U],h2,31u);
|
|
if (tickertime!=aprsdecode_realtime) {
|
|
aprsstr_Assign(xosi_headmh, 251ul, h2, 31ul);
|
|
if (cnt>19UL) cnt = 19UL;
|
|
tmp = cnt-1UL;
|
|
i = 1UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
aprsstr_Append(xosi_headmh, 251ul, " * ", 6ul);
|
|
aprsstr_Append(xosi_headmh, 251ul, frameticker[i], 31ul);
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
tickertime = aprsdecode_realtime;
|
|
}
|
|
}
|
|
} /* end tickermon() */
|
|
|
|
|
|
static void Stopticker(void)
|
|
{
|
|
aprsstr_Assign(xosi_headmh, 251ul, "\015", 2ul);
|
|
tickertime = 0x0FFFFFFC3UL;
|
|
memset((char *)frameticker,(char)0,620UL);
|
|
} /* end Stopticker() */
|
|
|
|
|
|
static void wrmon(uint32_t port, char dir,
|
|
const struct UDPSET modeminfo, uint32_t oldtime,
|
|
const char s[], uint32_t s_len)
|
|
{
|
|
char mcon[10];
|
|
char ms[31];
|
|
if (port==0UL) strncpy(mcon,"n",10u);
|
|
else aprsstr_IntToStr((int32_t)port, 0UL, mcon, 10ul);
|
|
if ((dir=='>' || dir=='-') && useri_configon(useri_fWRTICKER)) {
|
|
tickermon(mcon, 10ul, dir, oldtime, s, s_len);
|
|
}
|
|
/*IF configon(fWRINCOM) THEN */
|
|
useri_confstr(useri_fWRINCOM, ms, 31ul);
|
|
if (aprsstr_InStr(ms, 31ul, mcon, 10ul)>=0L) {
|
|
aprsstr_Append(mcon, 10ul, "+", 2ul);
|
|
aprstext_listin(s, s_len, X2C_CAP(mcon[0U]), dir, aprsstr_InStr(ms,
|
|
31ul, mcon, 10ul)>=0L, modeminfo.quali, modeminfo.txd,
|
|
modeminfo.level);
|
|
}
|
|
/*END; */
|
|
} /* end wrmon() */
|
|
|
|
|
|
static char filtdupes(const char tb[], uint32_t tb_len,
|
|
uint32_t oport, uint32_t dt)
|
|
{
|
|
uint32_t n2;
|
|
uint32_t n1;
|
|
uint32_t n;
|
|
uint32_t p;
|
|
uint8_t hashh;
|
|
uint8_t hashl;
|
|
struct aprsdecode_UDPSOCK * anonym;
|
|
hashl = 0U;
|
|
hashh = 0U;
|
|
p = 0UL;
|
|
n1 = 0UL;
|
|
n2 = 0UL;
|
|
for (;;) {
|
|
while (tb[p] && tb[p]!=':') ++p;
|
|
if (tb[p]!=':') break;
|
|
n1 = p;
|
|
++p;
|
|
if (tb[p]!='}') break;
|
|
++p;
|
|
n2 = p;
|
|
}
|
|
p = n2;
|
|
while (p<n1 && tb[p]!='>') {
|
|
aprsstr_HashCh(tb[p], &hashl, &hashh);
|
|
++p;
|
|
}
|
|
while ((p<n1 && tb[p]!='-') && tb[p]!=',') {
|
|
aprsstr_HashCh(tb[p], &hashl, &hashh);
|
|
++p;
|
|
}
|
|
p = n1;
|
|
while (tb[p]) {
|
|
aprsstr_HashCh(tb[p], &hashl, &hashh);
|
|
++p;
|
|
}
|
|
n = (uint32_t)(uint8_t)(char)hashl+(uint32_t)(uint8_t)
|
|
(char)hashh*256UL&65535UL;
|
|
{ /* with */
|
|
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[oport];
|
|
if (anonym->pdupetimes==0) {
|
|
osic_alloc((char * *) &anonym->pdupetimes, 262144UL);
|
|
useri_debugmem.req = 262144UL;
|
|
useri_debugmem.mon += 262144UL;
|
|
if (anonym->pdupetimes==0) {
|
|
osi_WrStrLn("duptime out of memory", 22ul);
|
|
useri_wrheap();
|
|
return 0;
|
|
}
|
|
memset((char *)anonym->pdupetimes,(char)0,262144UL);
|
|
}
|
|
if (anonym->pdupetimes[n]+dt>aprsdecode_realtime) return 0;
|
|
/* it is a dupe */
|
|
anonym->pdupetimes[n] = aprsdecode_realtime;
|
|
}
|
|
return 1;
|
|
} /* end filtdupes() */
|
|
|
|
|
|
static char Sendtcp(aprsdecode_pTCPSOCK to,
|
|
const aprsdecode_FRAMEBUF buf)
|
|
{
|
|
int32_t i;
|
|
int32_t len;
|
|
char ok0;
|
|
struct UDPSET modeminfo;
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
int32_t tmp;
|
|
ok0 = 0;
|
|
if (to) {
|
|
if (to->connt>0UL) {
|
|
memset((char *) &modeminfo,(char)0,sizeof(struct UDPSET));
|
|
wrmon(0UL, '<', modeminfo, 1UL, buf, 512ul);
|
|
}
|
|
len = (int32_t)aprsstr_Length(buf, 512ul);
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = to;
|
|
if (anonym->tlen+len<512L) {
|
|
tmp = len-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
anonym->tbuf[anonym->tlen] = buf[i];
|
|
++anonym->tlen;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
++anonym->txframes;
|
|
anonym->txbytes += (uint32_t)len;
|
|
aprsdecode_lasttcptx = aprsdecode_realtime;
|
|
ok0 = 1;
|
|
}
|
|
else if (aprsdecode_verb) osi_WrStrLn("tx buf overflow", 16ul);
|
|
}
|
|
}
|
|
return ok0;
|
|
} /* end Sendtcp() */
|
|
|
|
|
|
static int32_t Sendudp(const char s[], uint32_t s_len,
|
|
uint32_t uport, uint32_t dupetime0)
|
|
{
|
|
int32_t len;
|
|
aprsdecode_FRAMEBUF raw;
|
|
struct UDPSET modeminfo;
|
|
struct aprsdecode_UDPSOCK * anonym;
|
|
len = -1L;
|
|
if ((uport<=3UL && (int32_t)aprsdecode_udpsocks0[uport].fd>=0L)
|
|
&& aprsdecode_udpsocks0[uport].dport>0UL) {
|
|
if (dupetime0==0UL || filtdupes(s, s_len, uport, dupetime0)) {
|
|
aprsstr_mon2raw(s, s_len, raw, 512ul, &len);
|
|
if (len>1L) {
|
|
len = udpsend(aprsdecode_udpsocks0[uport].fd, raw, len,
|
|
aprsdecode_udpsocks0[uport].dport,
|
|
aprsdecode_udpsocks0[uport].ip);
|
|
if (len>0L) {
|
|
memset((char *) &modeminfo,(char)0,
|
|
sizeof(struct UDPSET));
|
|
wrmon(uport+1UL, '<', modeminfo, 1UL, s, s_len);
|
|
{ /* with */
|
|
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[uport]
|
|
;
|
|
++anonym->txframes;
|
|
anonym->txbytes += (uint32_t)len;
|
|
anonym->lastudptx = aprsdecode_realtime;
|
|
if (anonym->starttime==0UL) {
|
|
anonym->starttime = aprsdecode_realtime;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (aprsdecode_verb) {
|
|
osi_WrStrLn("wrong rf monitor format", 24ul);
|
|
}
|
|
}
|
|
else len = 0L;
|
|
}
|
|
return len;
|
|
} /* end Sendudp() */
|
|
|
|
#define aprsdecode_MAXTXBIT 2000
|
|
/* clamp to +- bit */
|
|
|
|
#define aprsdecode_MSGPREF 1000
|
|
/* prefer msg time space */
|
|
|
|
|
|
static char Checkbps(uint32_t uport, uint32_t bps,
|
|
uint32_t bytes, char msgprefer)
|
|
/* check/set bit/s for net>rf*/
|
|
{
|
|
uint32_t t;
|
|
struct aprsdecode_UDPSOCK * anonym;
|
|
if (bps>0UL && uport<=3UL) {
|
|
t = 2000UL/bps;
|
|
{ /* with */
|
|
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[uport];
|
|
if (bytes==0UL) {
|
|
/* check */
|
|
/*WrInt(bpstime-realtime, 10); WrStrLn(" check tx"); */
|
|
if (anonym->bpstime<=aprsdecode_realtime+(1000UL/bps)
|
|
*(uint32_t)msgprefer) return 1;
|
|
t += aprsdecode_realtime;
|
|
if (anonym->bpstime>t) anonym->bpstime = t;
|
|
}
|
|
else {
|
|
/* set next tx time */
|
|
if (anonym->bpstime+t<aprsdecode_realtime) {
|
|
anonym->bpstime = aprsdecode_realtime-t;
|
|
/* limit transmission at once */
|
|
}
|
|
anonym->bpstime += (bytes*8UL)/bps;
|
|
}
|
|
}
|
|
}
|
|
/*WrInt(bpstime-realtime, 10); WrStrLn(" next tx"); */
|
|
return 0;
|
|
} /* end Checkbps() */
|
|
|
|
#define aprsdecode_RAININCH 3.9370078740157
|
|
|
|
#define aprsdecode_SEP ","
|
|
|
|
|
|
static char csvget(char w[], uint32_t w_len, const char s[],
|
|
uint32_t s_len, uint32_t n)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
w[0UL] = 0;
|
|
i = 0UL;
|
|
while (n>0UL) {
|
|
if (i>s_len-1 || s[i]==0) return 0;
|
|
if (s[i]==',') --n;
|
|
++i;
|
|
}
|
|
j = 0UL;
|
|
while (((j<=w_len-1 && i<s_len-1) && s[i]) && s[i]!=',') {
|
|
w[j] = s[i];
|
|
++i;
|
|
++j;
|
|
}
|
|
if (j<=w_len-1) w[j] = 0;
|
|
return 1;
|
|
} /* end csvget() */
|
|
|
|
|
|
static char getreal(float * x, const char s[],
|
|
uint32_t s_len)
|
|
{
|
|
char val;
|
|
char dot;
|
|
float div0;
|
|
uint32_t i;
|
|
dot = 0;
|
|
val = 0;
|
|
*x = 0.0f;
|
|
div0 = 1.0f;
|
|
i = 0UL;
|
|
for (;;) {
|
|
if (div0>=0.0f && s[i]=='-') div0 = -div0;
|
|
else if ((uint8_t)s[i]>='0' && (uint8_t)s[i]<='9') {
|
|
*x = *x*10.0f+(float)((uint32_t)(uint8_t)s[i]-48UL);
|
|
if (*x>1.E+6f) {
|
|
val = 0;
|
|
break;
|
|
}
|
|
if (dot) div0 = div0*0.1f;
|
|
val = 1;
|
|
}
|
|
else if (!dot && s[i]=='.') dot = 1;
|
|
else break;
|
|
++i;
|
|
if (i>s_len-1) break;
|
|
}
|
|
*x = *x*div0;
|
|
return val;
|
|
} /* end getreal() */
|
|
|
|
|
|
static void apd(char ws[], uint32_t ws_len, char c, float v,
|
|
uint32_t f)
|
|
{
|
|
int32_t d;
|
|
int32_t n;
|
|
char tmp;
|
|
if (c) aprsstr_Append(ws, ws_len, (char *) &c, 1u/1u);
|
|
n = (int32_t)X2C_TRUNCI(v+0.5f,X2C_min_longint,X2C_max_longint);
|
|
if (n<0L) {
|
|
aprsstr_Append(ws, ws_len, "-", 2ul);
|
|
n = -n;
|
|
--f;
|
|
}
|
|
d = 1L;
|
|
while (f>1UL) {
|
|
d = d*10L;
|
|
--f;
|
|
}
|
|
do {
|
|
aprsstr_Append(ws, ws_len, (char *)(tmp = (char)((n/d)%10L+48L),
|
|
&tmp), 1u/1u);
|
|
d = d/10L;
|
|
} while (d);
|
|
} /* end apd() */
|
|
|
|
|
|
static void wxmacro(char ws[], uint32_t ws_len, char wms[],
|
|
uint32_t wms_len)
|
|
/* \\!wx.txt,,t,,h,b,,w3.6,d! */
|
|
{
|
|
struct aprsdecode_WX w;
|
|
uint32_t n;
|
|
int32_t payload;
|
|
int32_t len;
|
|
int32_t f;
|
|
float mul;
|
|
float v;
|
|
float winddir;
|
|
float wind;
|
|
char cb[1024];
|
|
char ns[1024];
|
|
char fn[1024];
|
|
char cn[21];
|
|
char c;
|
|
struct aprsdecode_DAT d;
|
|
X2C_PCOPY((void **)&wms,wms_len);
|
|
if (csvget(fn, 1024ul, wms, wms_len, 0UL)) {
|
|
/* csv filename */
|
|
len = 0L;
|
|
if (fn[0U]) {
|
|
f = osi_OpenRead(fn, 1024ul);
|
|
if (osic_FdValid(f)) {
|
|
n = (uint32_t)osic_Size(f);
|
|
if (n>1024UL) osic_Seek(f, n-1024UL);
|
|
len = osi_RdBin(f, (char *)cb, 1024u/1u, 1024UL);
|
|
}
|
|
if (len>0L) {
|
|
while (len>0L && (uint8_t)cb[len-1L]<=' ') {
|
|
--len; /* find first visable char from end */
|
|
}
|
|
if (len<=1023L) cb[len] = 0;
|
|
while (len>0L && (uint8_t)cb[len-1L]>=' ') {
|
|
--len; /* find begin of last csv line */
|
|
}
|
|
aprsstr_Delstr(cb, 1024ul, 0UL, (uint32_t)len);
|
|
}
|
|
else cb[0U] = 0;
|
|
if (cb[0U]==0) {
|
|
aprsstr_Assign(ns, 1024ul, "wx csv file not readable ", 26ul);
|
|
aprsstr_Append(ns, 1024ul, fn, 1024ul);
|
|
useri_xerrmsg(ns, 1024ul);
|
|
wms[0UL] = 0;
|
|
goto label;
|
|
}
|
|
w.temp = 1.E+6f;
|
|
winddir = 1.E+6f;
|
|
wind = 1.E+6f;
|
|
w.gust = 1.E+6f;
|
|
w.hygro = 1.E+6f;
|
|
w.baro = 1.E+6f;
|
|
w.lum = 1.E+6f;
|
|
w.rain1 = 1.E+6f;
|
|
w.rain24 = 1.E+6f;
|
|
w.raintoday = 1.E+6f;
|
|
n = 1UL;
|
|
while (csvget(cn, 21ul, wms, wms_len, n)) {
|
|
c = cn[0U]; /* w3.6 */
|
|
if (c) {
|
|
aprsstr_Delstr(cn, 21ul, 0UL, 1UL); /* 3.6 */
|
|
if (!getreal(&mul, cn, 21ul)) mul = 1.0f;
|
|
if (csvget(ns, 1024ul, cb, 1024ul, n-1UL) && getreal(&v, ns,
|
|
1024ul)) {
|
|
v = v*mul;
|
|
switch ((unsigned)c) {
|
|
case 't':
|
|
if (v>=(-60.0f) && v<=79.0f) w.temp = v;
|
|
break;
|
|
case 'g':
|
|
if (v>=0.0f && v<=500.0f) w.gust = v;
|
|
break;
|
|
case 'w':
|
|
if (v>=0.0f && v<=500.0f) wind = v;
|
|
break;
|
|
case 'd':
|
|
if (v>=0.0f && v<360.0f) winddir = v;
|
|
break;
|
|
case 'b':
|
|
if (v>=900.0f && v<=1100.0f) w.baro = v;
|
|
break;
|
|
case 'h':
|
|
if (v>=0.0f && v<=100.0f) w.hygro = v;
|
|
break;
|
|
case 'L':
|
|
if (v>=0.0f && v<=1500.0f) w.lum = v;
|
|
break;
|
|
case 'r':
|
|
if (v>=0.0f && v<=500.0f) w.rain1 = v;
|
|
break;
|
|
case 'P':
|
|
if (v>=0.0f && v<=500.0f) w.rain24 = v;
|
|
break;
|
|
case 'p':
|
|
if (v>=0.0f && v<=500.0f) w.raintoday = v;
|
|
break;
|
|
} /* end switch */
|
|
}
|
|
}
|
|
++n;
|
|
}
|
|
d.postyp = 'g';
|
|
payload = aprsstr_InStr(ws, ws_len, ":", 2ul);
|
|
if (payload>0L) {
|
|
aprspos_GetPos(&d.pos, &d.speed, &d.course, &d.altitude, &d.sym,
|
|
&d.symt, ws, ws_len, 0UL, (uint32_t)(payload+1L),
|
|
d.comment0, 256ul, &d.postyp);
|
|
/* exchange spd/dir */
|
|
if (d.postyp=='c') {
|
|
aprsstr_Delstr(ws, ws_len, (uint32_t)(payload+2L), ws_len);
|
|
d.speed = aprsdecode_trunc(X2C_DIVR(wind,1.609f));
|
|
d.course = aprsdecode_trunc(winddir);
|
|
cb[0U] = d.symt;
|
|
cb[1U] = d.sym;
|
|
cb[2U] = 0;
|
|
aprstext_compressdata(d.pos, d.speed, d.course, 0L, cb,
|
|
1024ul, cb, 1024ul);
|
|
aprsstr_Append(ws, ws_len, cb, 1024ul);
|
|
}
|
|
else if (d.postyp!='g') {
|
|
aprsstr_Assign(ns, 1024ul, "wx beacon not MICE encodable",
|
|
29ul);
|
|
useri_xerrmsg(ns, 1024ul);
|
|
}
|
|
}
|
|
if (d.postyp!='c') {
|
|
if (winddir!=1.E+6f) apd(ws, ws_len, 0, winddir+1.0f, 3UL);
|
|
else aprsstr_Append(ws, ws_len, "...", 4ul);
|
|
if (wind!=1.E+6f) {
|
|
apd(ws, ws_len, '/', X2C_DIVR(wind,1.609f), 3UL);
|
|
}
|
|
else aprsstr_Append(ws, ws_len, "/...", 5ul);
|
|
}
|
|
if (w.gust!=1.E+6f) {
|
|
apd(ws, ws_len, 'g', X2C_DIVR(w.gust,1.609f), 3UL);
|
|
}
|
|
else aprsstr_Append(ws, ws_len, "g...", 5ul);
|
|
if (w.temp!=1.E+6f) {
|
|
apd(ws, ws_len, 't', aprstext_CtoF(w.temp), 3UL);
|
|
}
|
|
else aprsstr_Append(ws, ws_len, "t...", 5ul);
|
|
if (w.rain1!=1.E+6f) {
|
|
apd(ws, ws_len, 'r', w.rain1*3.9370078740157f, 3UL);
|
|
}
|
|
if (w.rain24!=1.E+6f) {
|
|
apd(ws, ws_len, 'P', w.rain24*3.9370078740157f, 3UL);
|
|
}
|
|
if (w.raintoday!=1.E+6f) {
|
|
apd(ws, ws_len, 'p', w.raintoday*3.9370078740157f, 3UL);
|
|
}
|
|
if (w.hygro!=1.E+6f) apd(ws, ws_len, 'h', w.hygro, 2UL);
|
|
if (w.baro!=1.E+6f) apd(ws, ws_len, 'b', w.baro*10.0f, 5UL);
|
|
if (w.lum!=1.E+6f) {
|
|
if (w.lum>=1000.0f) apd(ws, ws_len, 'l', w.lum-1000.0f, 3UL);
|
|
else apd(ws, ws_len, 'L', w.lum, 3UL);
|
|
}
|
|
}
|
|
else {
|
|
aprsstr_Assign(ns, 1024ul, "wx beacon macro needs valid filename ",
|
|
38ul);
|
|
useri_xerrmsg(ns, 1024ul);
|
|
ws[0UL] = 0;
|
|
}
|
|
}
|
|
else {
|
|
aprsstr_Assign(ns, 1024ul, "wx beacon macro \\\\!filename,...! ",
|
|
34ul);
|
|
useri_xerrmsg(ns, 1024ul);
|
|
ws[0UL] = 0;
|
|
}
|
|
label:;
|
|
X2C_PFREE(wms);
|
|
} /* end wxmacro() */
|
|
|
|
#define aprsdecode_MSYM "\\"
|
|
|
|
#define aprsdecode_INSOPEN "<"
|
|
|
|
#define aprsdecode_INSCLOSE ">"
|
|
|
|
#define aprsdecode_DELOPEN "["
|
|
|
|
#define aprsdecode_DELCLOSE "]"
|
|
|
|
#define aprsdecode_WROPEN ">"
|
|
|
|
#define aprsdecode_WRCLOSE "<"
|
|
|
|
#define aprsdecode_WXOPEN "!"
|
|
|
|
#define aprsdecode_WXCLOSE "!"
|
|
|
|
|
|
static void beaconmacros(char s[], uint32_t s_len,
|
|
const char path[], uint32_t path_len, char wdata[],
|
|
uint32_t wdata_len, char all)
|
|
{
|
|
uint32_t i;
|
|
int32_t j;
|
|
int32_t len;
|
|
char ns[256];
|
|
char ds[256];
|
|
char fn[1024];
|
|
int32_t f;
|
|
char ok0;
|
|
char rwc;
|
|
char rw;
|
|
struct aprspos_POSITION pos;
|
|
X2C_PCOPY((void **)&wdata,wdata_len);
|
|
i = 0UL;
|
|
ns[0U] = 0;
|
|
while (i<s_len-1 && s[i]) {
|
|
if (s[i]=='\\' && s[i+1UL]=='\\') {
|
|
i += 2UL;
|
|
if (s[i]=='z' && all || s[i]=='Z') {
|
|
/* insert day, hour, min */
|
|
aprsstr_DateToStr(aprsdecode_realtime, ds, 256ul);
|
|
ds[0U] = ds[8U];
|
|
ds[1U] = ds[9U];
|
|
ds[2U] = ds[11U];
|
|
ds[3U] = ds[12U];
|
|
ds[4U] = ds[14U];
|
|
ds[5U] = ds[15U];
|
|
ds[6U] = 0;
|
|
aprsstr_Append(ns, 256ul, ds, 256ul);
|
|
}
|
|
else if (s[i]=='h' && all || s[i]=='H') {
|
|
/* insert hour, min, s */
|
|
aprsstr_DateToStr(aprsdecode_realtime, ds, 256ul);
|
|
ds[0U] = ds[11U];
|
|
ds[1U] = ds[12U];
|
|
ds[2U] = ds[14U];
|
|
ds[3U] = ds[15U];
|
|
ds[4U] = ds[17U];
|
|
ds[5U] = ds[18U];
|
|
ds[6U] = 0;
|
|
aprsstr_Append(ns, 256ul, ds, 256ul);
|
|
}
|
|
else if (all) {
|
|
rw = s[i];
|
|
if (rw=='<') rwc = '>';
|
|
else if (rw=='>') rwc = '<';
|
|
else if (rw=='[') rwc = ']';
|
|
else if (rw=='!') rwc = '!';
|
|
else rwc = 0;
|
|
if (rwc) {
|
|
/* insert or write file or insert and delete */
|
|
fn[0U] = 0;
|
|
++i;
|
|
while ((i<s_len-1 && s[i]) && s[i]!=rwc) {
|
|
aprsstr_Append(fn, 1024ul, (char *) &s[i], 1u/1u);
|
|
++i;
|
|
}
|
|
if (rw=='<' || rw=='[') {
|
|
/* read file */
|
|
f = osi_OpenRead(fn, 1024ul);
|
|
if (osic_FdValid(f)) {
|
|
len = osi_RdBin(f, (char *)ds, 256u/1u, 255UL);
|
|
osic_Close(f);
|
|
if (rw=='[') osi_Erase(fn, 1024ul, &ok0);
|
|
j = 0L;
|
|
while (((j<len && ds[j]!='\015') && ds[j]!='\012')
|
|
&& ds[j]) {
|
|
aprsstr_Append(ns, 256ul, (char *) &ds[j],
|
|
1u/1u);
|
|
++j;
|
|
}
|
|
}
|
|
else {
|
|
aprsstr_Assign(s, s_len, "beacon macro file not readable\
|
|
", 32ul);
|
|
aprsstr_Append(s, s_len, fn, 1024ul);
|
|
useri_xerrmsg(s, s_len);
|
|
s[0UL] = 0;
|
|
goto label;
|
|
}
|
|
}
|
|
else if (rw=='>') {
|
|
if (wdata[0UL]) {
|
|
/* write file */
|
|
f = osi_OpenWrite(fn, 1024ul);
|
|
if (osic_FdValid(f)) {
|
|
osi_WrBin(f, (char *)wdata, (wdata_len)/1u,
|
|
aprsstr_Length(wdata, wdata_len));
|
|
osic_Close(f);
|
|
}
|
|
}
|
|
}
|
|
else if (rw=='!') wxmacro(ns, 256ul, fn, 1024ul);
|
|
}
|
|
else if (s[i]=='\\') {
|
|
aprsstr_Append(ns, 256ul, "\\\\", 3ul);
|
|
}
|
|
else if (s[i]=='v') {
|
|
aprsstr_Append(ns, 256ul, "aprsmap(cu) 0.66", 17ul);
|
|
}
|
|
else if (s[i]=='l') {
|
|
if (aprstext_getmypos(&pos)) {
|
|
aprstext_postostr(pos, '2', ds, 256ul);
|
|
aprsstr_Append(ns, 256ul, ds, 256ul);
|
|
}
|
|
}
|
|
else if (s[i]=='p') aprsstr_Append(ns, 256ul, path, path_len);
|
|
else {
|
|
aprsstr_Assign(s, s_len, "bad beacon macro ", 18ul);
|
|
aprsstr_Append(s, s_len, ns, 256ul);
|
|
aprsstr_Append(s, s_len, "???", 4ul);
|
|
useri_xerrmsg(s, s_len);
|
|
s[0UL] = 0;
|
|
goto label;
|
|
}
|
|
}
|
|
else {
|
|
aprsstr_Append(ns, 256ul, "\\\\", 3ul);
|
|
aprsstr_Append(ns, 256ul, (char *) &s[i], 1u/1u);
|
|
}
|
|
}
|
|
else aprsstr_Append(ns, 256ul, (char *) &s[i], 1u/1u);
|
|
++i;
|
|
}
|
|
aprsstr_Assign(s, s_len, ns, 256ul);
|
|
label:;
|
|
X2C_PFREE(wdata);
|
|
} /* end beaconmacros() */
|
|
|
|
|
|
static void BuildNetBeacon(char h[], uint32_t h_len)
|
|
/* "!ddmm.mmNsdddmm.mms....." */
|
|
{
|
|
struct aprspos_POSITION mypos;
|
|
char h3[301];
|
|
char h2[301];
|
|
char h1[301];
|
|
useri_confstr(useri_fMYSYM, h3, 301ul);
|
|
useri_confstr(useri_fNBTEXT, h2, 301ul);
|
|
if (!aprstext_getmypos(&mypos)) {
|
|
useri_xerrmsg("netbeacon: wrong my position", 29ul);
|
|
h[0UL] = 0;
|
|
return;
|
|
}
|
|
if (aprsstr_Length(h3, 301ul)!=2UL) {
|
|
useri_xerrmsg("netbeacon: wrong symbol", 24ul);
|
|
h[0UL] = 0;
|
|
return;
|
|
}
|
|
aprstext_postostr(mypos, '2', h1, 301ul);
|
|
aprsstr_Assign(h, h_len, "=", 2ul);
|
|
h1[8U] = h3[0U];
|
|
h1[18U] = h3[1U];
|
|
h1[19U] = 0;
|
|
aprsstr_Append(h, h_len, h1, 301ul);
|
|
beaconmacros(h2, 301ul, "", 1ul, "", 1ul, 1);
|
|
aprsstr_Append(h, h_len, h2, 301ul);
|
|
} /* end BuildNetBeacon() */
|
|
|
|
|
|
static void SendNetBeacon(aprsdecode_pTCPSOCK cp,
|
|
const aprsdecode_FRAMEBUF b, char manual,
|
|
char errtxt[], uint32_t errtxt_len)
|
|
{
|
|
int32_t ret;
|
|
struct aprsdecode_DAT dat;
|
|
uint32_t t;
|
|
if (b[0UL]==0 || aprsdecode_Decode(b, 512ul, &dat)<0L) {
|
|
aprsstr_Assign(errtxt, errtxt_len, "Net Beacon not Decodable", 25ul);
|
|
return;
|
|
}
|
|
if (!Sendtcp(cp, b)) {
|
|
if (manual) {
|
|
aprsstr_Assign(errtxt, errtxt_len, "Netport not connected", 22ul);
|
|
}
|
|
return;
|
|
}
|
|
if (aprsdecode_lums.logmode) {
|
|
ret = aprsdecode_Stoframe(&aprsdecode_ophist2, b, 512ul,
|
|
aprsdecode_realtime, 0, &t, dat);
|
|
}
|
|
else {
|
|
ret = aprsdecode_Stoframe(&aprsdecode_ophist0, b, 512ul,
|
|
aprsdecode_realtime, 0, &t, dat);
|
|
}
|
|
} /* end SendNetBeacon() */
|
|
|
|
|
|
static void SendNet(aprsdecode_pTCPSOCK cp, char mycall[],
|
|
uint32_t mycall_len, const char data[],
|
|
uint32_t data_len, char manual, char errtxt[],
|
|
uint32_t errtxt_len)
|
|
/* make net header append string and send */
|
|
{
|
|
aprsdecode_FRAMEBUF s;
|
|
char pass[51];
|
|
char h[51];
|
|
uint32_t i;
|
|
X2C_PCOPY((void **)&mycall,mycall_len);
|
|
errtxt[0UL] = 0;
|
|
if (!useri_configon(useri_fALLOWNETTX) || !useri_configon(useri_fCONNECT))
|
|
{
|
|
if (manual) {
|
|
aprsstr_Assign(errtxt, errtxt_len,
|
|
"Net Port not configured to Send", 32ul);
|
|
}
|
|
goto label;
|
|
}
|
|
if (mycall[0UL]) aprsstr_Assign(s, 512ul, mycall, mycall_len);
|
|
else useri_confstr(useri_fMYCALL, s, 512ul);
|
|
i = 0UL;
|
|
while (i<511UL && s[i]) {
|
|
if ((uint8_t)s[i]<=' ' || (uint8_t)s[i]>='\177') s[0UL] = 0;
|
|
++i;
|
|
}
|
|
if (aprstext_callwrong(s, 512ul)) {
|
|
aprsstr_Assign(errtxt, errtxt_len, "netbeacon: no valid mycall", 27ul);
|
|
goto label;
|
|
}
|
|
useri_confstr(useri_fMSGNETDEST, h, 51ul);
|
|
if (h[0U]==0) {
|
|
aprsstr_Assign(errtxt, errtxt_len, "netbeacon: no destination call",
|
|
31ul);
|
|
goto label;
|
|
}
|
|
if (manual) {
|
|
useri_confstr(useri_fPW, pass, 51ul);
|
|
if (pass[0U]==0) {
|
|
useri_xerrmsg("sending to Net without Passcode", 32ul);
|
|
}
|
|
}
|
|
aprsstr_Append(s, 512ul, ">", 2ul);
|
|
aprsstr_Append(s, 512ul, h, 51ul);
|
|
aprsstr_Append(s, 512ul, ",TCPIP*:", 9ul);
|
|
aprsstr_Append(s, 512ul, data, data_len);
|
|
aprsstr_Append(s, 512ul, "\015\012", 3ul);
|
|
SendNetBeacon(cp, s, manual, errtxt, errtxt_len);
|
|
label:;
|
|
X2C_PFREE(mycall);
|
|
} /* end SendNet() */
|
|
|
|
|
|
static void makeping(uint32_t t, char pong, char b[],
|
|
uint32_t b_len)
|
|
{
|
|
char s[21];
|
|
if (pong) aprsstr_Assign(b, b_len, "pong ", 6ul);
|
|
else aprsstr_Assign(b, b_len, "ping ", 6ul);
|
|
aprsstr_IntToStr((int32_t)(t%86400UL), 0UL, s, 21ul);
|
|
aprsstr_Append(b, b_len, s, 21ul);
|
|
} /* end makeping() */
|
|
|
|
|
|
static void sendping(aprsdecode_pTCPSOCK tp)
|
|
{
|
|
char h[21];
|
|
aprsdecode_FRAMEBUF s;
|
|
char ok0;
|
|
if (aprsdecode_realtime<tp->lastping) tp->lastping = aprsdecode_realtime;
|
|
if (aprsdecode_realtime>=tp->lastping+20UL) {
|
|
tp->lastping = aprsdecode_realtime;
|
|
if (tp->waitpong<=1U) ++tp->waitpong;
|
|
strncpy(s,"#",512u);
|
|
makeping(tp->lastping, 0, h, 21ul);
|
|
aprsstr_Append(s, 512ul, h, 21ul);
|
|
aprsstr_Append(s, 512ul, "\015\012", 3ul);
|
|
ok0 = Sendtcp(tp, s);
|
|
}
|
|
} /* end sendping() */
|
|
|
|
|
|
static void getpong(aprsdecode_pTCPSOCK tp, const char mb[],
|
|
uint32_t mb_len)
|
|
{
|
|
char s[21];
|
|
makeping(tp->lastping, 1, s, 21ul);
|
|
if (aprsdecode_realtime<=tp->lastping+10UL && aprsstr_InStr(mb, mb_len, s,
|
|
21ul)>=1L) {
|
|
tp->lastpong = aprsdecode_realtime;
|
|
tp->waitpong = 0U;
|
|
}
|
|
} /* end getpong() */
|
|
|
|
|
|
static void Timebeacon(aprsdecode_pTCPSOCK cp)
|
|
{
|
|
aprsdecode_FRAMEBUF h;
|
|
uint32_t bt;
|
|
char err[100];
|
|
if (useri_configon(useri_fALLOWNETTX) && useri_configon(useri_fCONNECT)) {
|
|
bt = (uint32_t)useri_conf2int(useri_fNETBTIME, 0UL, 0L,
|
|
X2C_max_longint, 0L);
|
|
if ((bt>=1UL || cp->beacont==0UL) && Watchclock(&cp->beacont, bt)) {
|
|
if ((bt<60UL && bt>0UL) && cp->connt>0UL) {
|
|
useri_xerrmsg("Netbeacon: too fast", 20ul);
|
|
}
|
|
BuildNetBeacon(h, 512ul);
|
|
SendNet(cp, "", 1ul, h, 512ul, 0, err, 100ul);
|
|
useri_xerrmsg(err, 100ul);
|
|
}
|
|
if (cp->lastping>0UL && useri_configon(useri_fALLOWGATE)) sendping(cp);
|
|
}
|
|
} /* end Timebeacon() */
|
|
|
|
/*
|
|
PROCEDURE nibb(n:CARDINAL; VAR s:ARRAY OF CHAR);
|
|
BEGIN IF n<=9 THEN Append(s, CHR(n+ORD("0"))) ELSE Append(s,
|
|
CHR(n+(ORD("a")-10))) END END nibb;
|
|
*/
|
|
|
|
extern int32_t aprsdecode_knottokmh(int32_t kn)
|
|
{
|
|
if (kn>=0L && kn<50000L) {
|
|
return (int32_t)aprsdecode_trunc((float)kn*1.852f+0.5f);
|
|
}
|
|
else return 0L;
|
|
return 0;
|
|
} /* end knottokmh() */
|
|
|
|
|
|
static void NoWX(struct aprsdecode_WX * wx)
|
|
{
|
|
wx->gust = 1.E+6f;
|
|
wx->temp = 1.E+6f;
|
|
wx->rain1 = 1.E+6f;
|
|
wx->rain24 = 1.E+6f;
|
|
wx->raintoday = 1.E+6f;
|
|
wx->hygro = 1.E+6f;
|
|
wx->baro = 1.E+6f;
|
|
wx->lum = 1.E+6f;
|
|
wx->sievert = 1.E+6f;
|
|
wx->storm = aprsdecode_WXNOWX;
|
|
wx->sustaind = 0.0f;
|
|
wx->radiushurr = 0.0f;
|
|
wx->radiusstorm = 0.0f;
|
|
wx->wholegale = 0.0f;
|
|
} /* end NoWX() */
|
|
|
|
|
|
static void wpar(uint32_t * p, char buf[], uint32_t buf_len,
|
|
float * v, int32_t mindig, int32_t maxdig)
|
|
{
|
|
char empty;
|
|
char dot;
|
|
char sn;
|
|
char c;
|
|
float x;
|
|
float div0;
|
|
dot = 0;
|
|
empty = 1;
|
|
sn = buf[*p]=='t';
|
|
x = 0.0f;
|
|
div0 = 1.0f;
|
|
for (;;) {
|
|
++*p;
|
|
c = buf[*p];
|
|
if (sn && c=='-') {
|
|
div0 = -div0;
|
|
empty = 0;
|
|
--mindig;
|
|
--maxdig;
|
|
}
|
|
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
if (!dot && maxdig<=0L) {
|
|
x = 0.0f;
|
|
break;
|
|
}
|
|
x = x*10.0f+(float)((uint32_t)(uint8_t)buf[*p]-48UL);
|
|
if (x>1.E+5f) return;
|
|
if (dot) div0 = div0*0.1f;
|
|
else {
|
|
--mindig;
|
|
--maxdig;
|
|
}
|
|
empty = 0;
|
|
}
|
|
else if (empty) {
|
|
if (c!=' ' && c!='.') break;
|
|
}
|
|
else if (c=='.') {
|
|
if (dot) break;
|
|
dot = 1;
|
|
}
|
|
else break;
|
|
sn = 0;
|
|
}
|
|
if (!empty && mindig<=0L) *v = x*div0;
|
|
} /* end wpar() */
|
|
|
|
|
|
static void wexp(char buf[], uint32_t buf_len, uint32_t * p,
|
|
float * v, float mul)
|
|
{
|
|
uint32_t n;
|
|
float x;
|
|
x = 0.0f;
|
|
++*p;
|
|
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='9') {
|
|
x = 10.0f*(float)((uint32_t)(uint8_t)buf[*p]-48UL);
|
|
}
|
|
else return;
|
|
++*p;
|
|
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='9') {
|
|
x = x+(float)((uint32_t)(uint8_t)buf[*p]-48UL);
|
|
}
|
|
else return;
|
|
++*p;
|
|
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='9') {
|
|
n = (uint32_t)(uint8_t)buf[*p]-48UL;
|
|
while (n>0UL) {
|
|
x = x*10.0f; /* exponent */
|
|
--n;
|
|
}
|
|
++*p;
|
|
}
|
|
else return;
|
|
*v = x*mul;
|
|
} /* end wexp() */
|
|
|
|
|
|
static void GetWX(struct aprsdecode_WX * wx, uint32_t * course,
|
|
uint32_t * speed, char buf[], uint32_t buf_len,
|
|
char storm)
|
|
{
|
|
float wdir;
|
|
float wwind;
|
|
uint32_t p;
|
|
p = 0UL;
|
|
NoWX(wx);
|
|
wwind = 1.E+6f;
|
|
wdir = 1.E+6f;
|
|
/* IF buf[p]="_" THEN INC(p, 9) END; (* positionless wx *) */
|
|
if (storm) {
|
|
/* storm data */
|
|
/*4903.50N\07202.75W@088/036/HC/150^200/0980>090&030%040 */
|
|
if (((buf[0UL]=='/' && buf[3UL]=='/') && buf[7UL]=='^')
|
|
&& buf[11UL]=='/') {
|
|
++p;
|
|
if (buf[1UL]=='T' && buf[2UL]=='S') wx->storm = aprsdecode_WXTS;
|
|
else if (buf[1UL]=='H' && buf[2UL]=='C') {
|
|
wx->storm = aprsdecode_WXHC;
|
|
}
|
|
else if (buf[1UL]=='T' && buf[2UL]=='D') {
|
|
wx->storm = aprsdecode_WXTD;
|
|
}
|
|
if (wx->storm) {
|
|
p += 2UL;
|
|
wpar(&p, buf, buf_len, &wx->sustaind, 3L, 3L);
|
|
wpar(&p, buf, buf_len, &wx->gust, 3L, 3L);
|
|
wpar(&p, buf, buf_len, &wx->baro, 4L, 4L);
|
|
if (buf[p]=='>') wpar(&p, buf, buf_len, &wx->radiushurr, 3L, 3L);
|
|
if (buf[p]=='&') {
|
|
wpar(&p, buf, buf_len, &wx->radiusstorm, 3L, 3L);
|
|
}
|
|
if (buf[p]=='%') wpar(&p, buf, buf_len, &wx->wholegale, 3L, 3L);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* normal wx */
|
|
for (;;) {
|
|
switch ((unsigned)buf[p]) {
|
|
case 'g':
|
|
wpar(&p, buf, buf_len, &wx->gust, 3L, 3L);
|
|
break;
|
|
case 't':
|
|
wpar(&p, buf, buf_len, &wx->temp, 3L, 3L);
|
|
break;
|
|
case 'r':
|
|
wpar(&p, buf, buf_len, &wx->rain1, 3L, 3L);
|
|
break;
|
|
case 'p':
|
|
wpar(&p, buf, buf_len, &wx->rain24, 3L, 3L);
|
|
break;
|
|
case 'P':
|
|
wpar(&p, buf, buf_len, &wx->raintoday, 3L, 3L);
|
|
break;
|
|
case 'h':
|
|
wpar(&p, buf, buf_len, &wx->hygro, 2L, 3L);
|
|
break;
|
|
case 'b':
|
|
wpar(&p, buf, buf_len, &wx->baro, 5L, 5L);
|
|
break;
|
|
case 'L':
|
|
wpar(&p, buf, buf_len, &wx->lum, 3L, 3L);
|
|
break;
|
|
case 'l':
|
|
wpar(&p, buf, buf_len, &wx->lum, 3L, 3L);
|
|
wx->lum = wx->lum+1000.0f;
|
|
break;
|
|
case 'c':
|
|
wpar(&p, buf, buf_len, &wdir, 3L, 3L);
|
|
break;
|
|
case 's':
|
|
wpar(&p, buf, buf_len, &wwind, 3L, 3L);
|
|
break;
|
|
case 'X':
|
|
wexp(buf, buf_len, &p, &wx->sievert, 1.E-9f);
|
|
break;
|
|
default:;
|
|
goto loop_exit;
|
|
} /* end switch */
|
|
}
|
|
loop_exit:;
|
|
wx->storm = aprsdecode_WXNORMAL;
|
|
}
|
|
wdir = wdir+0.5f;
|
|
if (wdir>=1.0f && wdir<361.0f) *course = aprsdecode_trunc(wdir);
|
|
if (wwind>=0.0f && wwind<1000.0f) *speed = aprsdecode_trunc(wwind);
|
|
aprsstr_Delstr(buf, buf_len, 0UL, p);
|
|
/* X123 is 12 * 10^3 nanosieverts/hr*/
|
|
} /* end GetWX() */
|
|
|
|
#define aprsdecode_DATELEN 15
|
|
|
|
|
|
static char wrlog(const char b[], uint32_t b_len,
|
|
uint32_t time0, char wfn[], uint32_t wfn_len,
|
|
int32_t good)
|
|
{
|
|
int32_t f;
|
|
char h[1001];
|
|
uint32_t i;
|
|
uint32_t l;
|
|
char wrlog_ret;
|
|
X2C_PCOPY((void **)&wfn,wfn_len);
|
|
if (wfn[0UL]==0) {
|
|
wrlog_ret = 0;
|
|
goto label;
|
|
}
|
|
l = aprsstr_Length(b, b_len);
|
|
while (l>0UL && (uint8_t)b[l-1UL]<='\015') --l;
|
|
if (l>0UL) {
|
|
aprsstr_cleanfilename(wfn, wfn_len);
|
|
f = osi_OpenAppendLong(wfn, wfn_len);
|
|
if (!osic_FdValid(f)) f = osi_OpenWrite(wfn, wfn_len);
|
|
if (!osic_FdValid(f)) {
|
|
wrlog_ret = 0;
|
|
goto label;
|
|
}
|
|
aprsstr_DateToStr(time0, h, 1001ul);
|
|
h[4U] = h[5U];
|
|
h[5U] = h[6U];
|
|
h[6U] = h[8U];
|
|
h[7U] = h[9U];
|
|
h[8U] = ':';
|
|
h[9U] = h[11U];
|
|
h[10U] = h[12U];
|
|
h[11U] = h[14U];
|
|
h[12U] = h[15U];
|
|
h[13U] = h[17U];
|
|
h[14U] = h[18U];
|
|
if (good>=0L) h[15U] = ' ';
|
|
else h[15U] = '-';
|
|
if (l>=984UL) l = 984UL;
|
|
i = 0UL;
|
|
do {
|
|
h[i+16UL] = b[i];
|
|
++i;
|
|
} while (i<l);
|
|
h[i+16UL] = '\012';
|
|
++i;
|
|
osi_WrBin(f, (char *)h, 1001u/1u, i+16UL);
|
|
osic_Close(f);
|
|
}
|
|
wrlog_ret = 1;
|
|
label:;
|
|
X2C_PFREE(wfn);
|
|
return wrlog_ret;
|
|
} /* end wrlog() */
|
|
|
|
|
|
static aprsdecode_pOPHIST findop(aprsdecode_MONCALL call,
|
|
char online)
|
|
{
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_MONCALL tmp;
|
|
call = (char *)memcpy(tmp,call,9u);
|
|
if (online && aprsdecode_lums.logmode) op = aprsdecode_ophist2;
|
|
else op = aprsdecode_ophist0;
|
|
while (op && X2C_STRCMP(call,9u,op->call,9u)) op = op->next;
|
|
return op;
|
|
} /* end findop() */
|
|
|
|
|
|
static void poplogerr(char fn[], uint32_t fn_len)
|
|
{
|
|
char h[1001];
|
|
X2C_PCOPY((void **)&fn,fn_len);
|
|
strncpy(h,"\012logfile write error ",1001u);
|
|
aprsstr_Append(h, 1001ul, fn, fn_len);
|
|
aprsstr_Append(h, 1001ul, "\012", 2ul);
|
|
useri_textautosize(0L, 5L, 6UL, 4UL, 'e', h, 1001ul);
|
|
X2C_PFREE(fn);
|
|
} /* end poplogerr() */
|
|
|
|
|
|
extern void aprsdecode_savetrack(void)
|
|
{
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST pf;
|
|
char h[101];
|
|
char fn[1001];
|
|
char ap;
|
|
aprsdecode_MONCALL name;
|
|
name[0UL] = 0;
|
|
if (aprsdecode_click.mhop[0UL]) memcpy(name,aprsdecode_click.mhop,9u);
|
|
else if (aprsdecode_click.entries>0UL && aprsdecode_click.table[aprsdecode_click.selected]
|
|
.opf) {
|
|
memcpy(name,aprsdecode_click.table[aprsdecode_click.selected].opf->call,
|
|
9u);
|
|
}
|
|
if (name[0UL]) {
|
|
op = findop(name, 0);
|
|
if (op) {
|
|
aprsstr_Assign(fn, 1001ul, op->call, 9ul); /* make 0C terminated */
|
|
alfanum(fn, 1001ul); /* remove bad chars */
|
|
aprsdecode_makelogfn(fn, 1001ul);
|
|
ap = osi_Exists(fn, 1001ul);
|
|
pf = op->frames;
|
|
while (pf) {
|
|
if (!wrlog(pf->vardat->raw, 500ul, pf->time0, fn, 1001ul, 0L)) {
|
|
poplogerr(fn, 1001ul);
|
|
return;
|
|
}
|
|
pf = pf->next;
|
|
}
|
|
if (ap) strncpy(h,"Append to logfile ",101u);
|
|
else strncpy(h,"Write logfile ",101u);
|
|
aprsstr_Append(h, 101ul, fn, 1001ul);
|
|
useri_say(h, 101ul, 4UL, 'b');
|
|
}
|
|
}
|
|
} /* end savetrack() */
|
|
|
|
|
|
static char replyack(char rep[], uint32_t rep_len,
|
|
char restack[], uint32_t restack_len,
|
|
const char ack[], uint32_t ack_len)
|
|
{
|
|
aprsstr_Assign(rep, rep_len, ack, ack_len);
|
|
aprsstr_Assign(restack, restack_len, ack, ack_len);
|
|
if (aprsstr_Length(ack, ack_len)>2UL && ack[2UL]=='}') {
|
|
/* {xx}yy */
|
|
rep[0UL] = ack[3UL];
|
|
rep[1UL] = ack[4UL];
|
|
if (rep_len-1>=2UL) rep[2UL] = 0;
|
|
if (restack_len-1>=2UL) restack[2UL] = 0;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
} /* end replyack() */
|
|
|
|
|
|
static char iscall(const aprsdecode_MONCALL b)
|
|
{
|
|
uint32_t i;
|
|
uint32_t nu;
|
|
uint32_t li;
|
|
char c;
|
|
li = 0UL;
|
|
nu = 0UL;
|
|
for (i = 0UL; i<=2UL; i++) {
|
|
c = b[i];
|
|
if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++li;
|
|
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
if (i==0UL) ++li;
|
|
else ++nu;
|
|
}
|
|
} /* end for */
|
|
return (nu+li==3UL && nu>=1UL) && nu<=2UL;
|
|
} /* end iscall() */
|
|
|
|
|
|
static char viaghost(const char b[], uint32_t b_len)
|
|
/* n<>N */
|
|
{
|
|
uint32_t i;
|
|
char c;
|
|
i = aprsstr_Length(b, b_len);
|
|
if (i>3UL) {
|
|
c = b[i-1UL];
|
|
if (((uint8_t)c>='0' && (uint8_t)c<='9') && c!=b[i-3UL]) return 1;
|
|
}
|
|
return 0;
|
|
} /* end viaghost() */
|
|
|
|
/*
|
|
PROCEDURE viaghost(b-:ARRAY OF CHAR):BOOLEAN;
|
|
(* ECHO GATE RELAY n=n ELSE ghost *)
|
|
VAR i:CARDINAL;
|
|
c:CHAR;
|
|
BEGIN
|
|
IF (b[0]="E") & (b[1]="C") & (b[2]="H") & (b[3]="O") & (b[4]=0C)
|
|
THEN RETURN FALSE END;
|
|
IF (b[0]="G") & (b[1]="A") & (b[2]="T") & (b[3]="E") & (b[4]=0C)
|
|
THEN RETURN FALSE END;
|
|
IF (b[0]="R") & (b[1]="E") & (b[2]="L") & (b[3]="A") & (b[4]="Y")
|
|
& (b[5]=0C) THEN RETURN FALSE E
|
|
i:=Length(b);
|
|
c:=b[i-1];
|
|
IF (i>3) & (b[i-2]="-") & (c=b[i-3]) & (c>="1") & (c<="7")
|
|
THEN RETURN FALSE END;
|
|
RETURN TRUE
|
|
END viaghost;
|
|
*/
|
|
|
|
static float num(char buf[], uint32_t buf_len, uint32_t * p)
|
|
{
|
|
char c;
|
|
char sig;
|
|
float f;
|
|
float r;
|
|
r = 0.0f;
|
|
sig = 0;
|
|
f = 1.0f;
|
|
for (;;) {
|
|
if (*p>buf_len-1 || (float)fabs(r)>=2.147483647E+9f) break;
|
|
c = buf[*p];
|
|
if (sig==0 && c=='-' || c=='+') sig = c;
|
|
else if (f>0.5f && c=='.') f = f*0.1f;
|
|
else if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
if (f>0.5f) r = r*10.0f+(float)((uint32_t)(uint8_t)c-48UL);
|
|
else {
|
|
r = r+(float)((uint32_t)(uint8_t)c-48UL)*f;
|
|
f = f*0.1f;
|
|
}
|
|
}
|
|
else break;
|
|
++*p;
|
|
if (sig==0) sig = '\001';
|
|
}
|
|
if (r>=2.147483647E+9f) r = 2.147483647E+9f;
|
|
if (sig=='-') r = -r;
|
|
return r;
|
|
} /* end num() */
|
|
|
|
|
|
static void skip(char buf[], uint32_t buf_len, uint32_t * p)
|
|
{
|
|
if (*p<=buf_len-1 && buf[*p]==',') ++*p;
|
|
} /* end skip() */
|
|
|
|
|
|
static uint32_t corrtime(uint32_t syst, uint32_t mt, uint32_t span)
|
|
/* complete modulo time to absolute */
|
|
{
|
|
mt = (span+mt%span)-syst%span;
|
|
if (mt<span/2UL) mt += span;
|
|
else if (mt>span+span/2UL) mt -= span;
|
|
mt += syst;
|
|
if (mt>=span) mt -= span;
|
|
return mt;
|
|
} /* end corrtime() */
|
|
|
|
#define aprsdecode_H 3600
|
|
|
|
#define aprsdecode_DAY 86400
|
|
|
|
#define aprsdecode_DEGUNIT 1.7453292519444E-7
|
|
/* 1/100000 deg = 1.1111m*/
|
|
|
|
|
|
static void GetHRT(struct aprspos_POSITION * pos, int32_t * altitude,
|
|
uint32_t * speed, const char buf[], uint32_t buf_len,
|
|
struct aprsdecode_HRTPOS hrtposes[],
|
|
uint32_t hrtposes_len, uint32_t * hrtlen,
|
|
uint32_t * hrttime)
|
|
{
|
|
uint32_t p;
|
|
char cmd;
|
|
uint32_t i;
|
|
uint32_t crc;
|
|
uint32_t duration;
|
|
uint32_t wcnt;
|
|
float r;
|
|
float unit;
|
|
uint32_t ts;
|
|
struct aprspos_POSITION posh;
|
|
struct aprspos_POSITION dao;
|
|
char newcompos;
|
|
struct aprsdecode_HRTPOS * anonym;
|
|
uint32_t tmp;
|
|
/* $HR[t46531u1.5p48.0235,13.1512a367d15,11w-479,622,33w-5,
|
|
2-4w7+2-3ww4-1-5wg435644353-10c27001]
|
|
t s utc modulo 24h modulo 1h or absolut since 1970
|
|
p deg lat/long
|
|
a m altitude
|
|
v m/s speed
|
|
y m/s climb
|
|
d deg lat/long dao
|
|
w deg,deg,m,s lat long alt time
|
|
u 0.00001 deg,m unit
|
|
g direct heard gateway
|
|
c crc
|
|
q qrv mhz
|
|
r rx freq mhz or hz
|
|
*/
|
|
/*WrStrLn(buf); */
|
|
*hrtlen = 0UL;
|
|
*hrttime = 0UL;
|
|
p = 0UL;
|
|
newcompos = 1;
|
|
/*WrInt(p, 10);WrStrLn(" compos"); */
|
|
for (;;) {
|
|
if (p+3UL>buf_len-1 || buf[p]==0) return;
|
|
if (((buf[p]=='$' && buf[p+1UL]=='H') && buf[p+2UL]=='R')
|
|
&& buf[p+3UL]=='[') break;
|
|
/*WrStrLn(" newcompos"); */
|
|
++p;
|
|
newcompos = 0;
|
|
}
|
|
p += 4UL;
|
|
ts = aprsdecode_systime;
|
|
unit = 1.0f;
|
|
duration = 0UL;
|
|
wcnt = 0UL;
|
|
dao.lat = 0.0f;
|
|
dao.long0 = 0.0f;
|
|
memset((char *)hrtposes,(char)0,
|
|
hrtposes_len*sizeof(struct aprsdecode_HRTPOS));
|
|
crc = 0UL;
|
|
for (;;) {
|
|
cmd = buf[p];
|
|
++p;
|
|
if (cmd==0 || p>buf_len-1) {
|
|
*hrtlen = 0UL; /* end of string? */
|
|
return;
|
|
}
|
|
if (cmd=='t') {
|
|
ts = aprsdecode_trunc(num(buf, buf_len, &p)+0.5f);
|
|
if (ts<3600UL) {
|
|
ts = corrtime(aprsdecode_systime, ts, 3600UL);
|
|
/* move system time max +-30min */
|
|
}
|
|
else if (ts<90000UL) {
|
|
ts = corrtime(aprsdecode_systime, ts-3600UL, 86400UL);
|
|
/* move system time max +-12h */
|
|
}
|
|
/* absolute time */
|
|
*hrttime = ts;
|
|
}
|
|
else if (cmd=='u') unit = num(buf, buf_len, &p);
|
|
else if (cmd=='p') {
|
|
/* take position from extension if correct */
|
|
posh.lat = aprspos_rad0(num(buf, buf_len, &p));
|
|
skip(buf, buf_len, &p);
|
|
posh.long0 = aprspos_rad0(num(buf, buf_len, &p));
|
|
if (aprspos_posvalid(posh)) *pos = posh;
|
|
}
|
|
else if (cmd=='a') {
|
|
/* take altitude from extension if correct */
|
|
r = num(buf, buf_len, &p);
|
|
if (r>(-1.E+4f) && r<50000.0f) {
|
|
*altitude = (int32_t)X2C_TRUNCI(r+0.5f,X2C_min_longint,
|
|
X2C_max_longint);
|
|
}
|
|
}
|
|
else if (cmd=='v') {
|
|
/* take speed from extension if correct */
|
|
r = num(buf, buf_len, &p);
|
|
if (r>0.0f && r<50000.0f) {
|
|
*speed = (uint32_t)(int32_t)X2C_TRUNCI(r+0.5f,
|
|
X2C_min_longint,X2C_max_longint);
|
|
}
|
|
}
|
|
else if (cmd=='d') {
|
|
/* ELSIF cmd="i" THEN (* define constant time intervall *)
|
|
*/
|
|
/* duration:=trunc(num()+0.5); */
|
|
/* DAO, correct position */
|
|
dao.lat = num(buf, buf_len, &p);
|
|
skip(buf, buf_len, &p);
|
|
dao.long0 = num(buf, buf_len, &p);
|
|
}
|
|
else if (cmd=='w') {
|
|
/* waypoints, first is difference from now */
|
|
if (wcnt<=hrtposes_len-1) {
|
|
{ /* with */
|
|
struct aprsdecode_HRTPOS * anonym = &hrtposes[wcnt];
|
|
anonym->dlat = num(buf, buf_len, &p);
|
|
skip(buf, buf_len, &p);
|
|
anonym->dlong = num(buf, buf_len, &p);
|
|
skip(buf, buf_len, &p);
|
|
anonym->dalt = num(buf, buf_len, &p);
|
|
anonym->notinterpolated = (anonym->dlat!=0.0f || anonym->dlong!=0.0f)
|
|
|| anonym->dalt!=0.0f;
|
|
skip(buf, buf_len, &p);
|
|
r = num(buf, buf_len, &p);
|
|
anonym->dtime = aprsdecode_trunc((float)fabs(r)+0.5f);
|
|
if (r<0.0f) anonym->dtime = 0UL-anonym->dtime;
|
|
}
|
|
++wcnt;
|
|
}
|
|
}
|
|
else if (cmd=='c') {
|
|
/* crc incl sender call and destination without ssid */
|
|
crc = aprsdecode_trunc(num(buf, buf_len, &p)+0.5f);
|
|
}
|
|
else if (cmd==']') break;
|
|
}
|
|
/*
|
|
IF (wcnt>0) & (hrtposes[0].dtime>0) THEN
|
|
r:=1.0/FLOAT(wcnt);
|
|
kt:=r*FLOAT(hrtposes[0].dtime);
|
|
kx:=r*hrtposes[0].dlong;
|
|
ky:=r*hrtposes[0].dlat;
|
|
kh:=r*hrtposes[0].dalt;
|
|
FOR i:=1 TO wcnt-1 DO
|
|
r:=FLOAT(wcnt-i);
|
|
hrtposes[i].dtime:=trunc(kt*r + 0.5)-hrtposes[i].dtime;
|
|
hrtposes[i].dlong:=hrtposes[i].dlong + kx*r;
|
|
hrtposes[i].dlat :=hrtposes[i].dlat + ky*r;
|
|
hrtposes[i].dalt :=hrtposes[i].dalt + kh*r;
|
|
END;
|
|
|
|
r:=unit*DEGUNIT;
|
|
pos.long:=pos.long + dao.long*r;
|
|
pos.lat :=pos.lat + dao.lat *r;
|
|
|
|
FOR i:=0 TO wcnt-1 DO
|
|
hrtposes[i].dtime:=ts - hrtposes[i].dtime;
|
|
hrtposes[i].dlong:=pos.long + hrtposes[i].dlong*r;
|
|
hrtposes[i].dlat :=pos.lat + hrtposes[i].dlat*r;
|
|
hrtposes[i].dalt :=VAL(REAL, altitude) + hrtposes[i].dalt*unit;
|
|
--WrInt(hrtposes[i].dtime, 6); WrFixed(r, 8,15); WrFixed(dao.lat*r, 8,15);
|
|
WrFixed(hrtposes[i].dlat*360.0/PI2, 8,15);
|
|
WrFixed(hrtposes[i].dlong*360.0/PI2, 8,15);
|
|
WrInt(VAL(INTEGER, hrtposes[i].dalt), 6);WrStrLn("");
|
|
|
|
END;
|
|
hrtlen:=wcnt;
|
|
END;
|
|
*/
|
|
if (wcnt>0UL && hrtposes[0UL].dtime>0UL) {
|
|
tmp = wcnt-1UL;
|
|
i = 1UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
hrtposes[i].dtime += hrtposes[i-1UL].dtime-hrtposes[i-1UL]
|
|
.dtime/((wcnt-i)+1UL);
|
|
if (hrtposes[i-1UL].dtime>0UL) {
|
|
r = X2C_DIVR((float)hrtposes[i].dtime,
|
|
(float)hrtposes[i-1UL].dtime);
|
|
hrtposes[i].dlong = hrtposes[i].dlong+hrtposes[i-1UL].dlong*r;
|
|
hrtposes[i].dlat = hrtposes[i].dlat+hrtposes[i-1UL].dlat*r;
|
|
hrtposes[i].dalt = hrtposes[i].dalt+hrtposes[i-1UL].dalt*r;
|
|
}
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
r = unit*1.7453292519444E-7f;
|
|
pos->long0 = pos->long0+dao.long0*r;
|
|
pos->lat = pos->lat+dao.lat*r;
|
|
tmp = wcnt-1UL;
|
|
i = 0UL;
|
|
if (i<=tmp) for (;; i++) {
|
|
hrtposes[i].dtime = ts-hrtposes[i].dtime;
|
|
hrtposes[i].dlong = pos->long0+hrtposes[i].dlong*r;
|
|
hrtposes[i].dlat = pos->lat+hrtposes[i].dlat*r;
|
|
hrtposes[i].dalt = (float)*altitude+hrtposes[i].dalt*unit;
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
/*WrInt(hrtposes[i].dtime, 6); WrFixed(r, 8,15);
|
|
WrFixed(dao.lat*r, 8,15);
|
|
WrFixed(hrtposes[i].dlat*360.0/PI2, 8,15);
|
|
WrFixed(hrtposes[i].dlong*360.0/PI2, 8,15);
|
|
WrInt(VAL(INTEGER, hrtposes[i].dalt), 6);WrStrLn(""); */
|
|
*hrtlen = wcnt;
|
|
}
|
|
/* IF newcompos THEN compos:=p END; */
|
|
/*WrInt(compos, 10);WrStrLn(" composret"); */
|
|
} /* end GetHRT() */
|
|
|
|
|
|
static char r91(uint16_t * n, char c)
|
|
{
|
|
if ((uint8_t)c<'!' || (uint8_t)c>'|') return 0;
|
|
*n = (uint16_t)((uint32_t)( *n*91U)+((uint32_t)(uint8_t)c-33UL));
|
|
return 1;
|
|
} /* end r91() */
|
|
|
|
|
|
static void GetTLM(aprsdecode_TELEMETRY v, char b[], uint32_t b_len)
|
|
{
|
|
uint32_t ib;
|
|
uint32_t ia;
|
|
uint32_t j;
|
|
uint32_t i;
|
|
aprsdecode_TELEMETRY t;
|
|
uint32_t tmp;
|
|
ia = 0UL;
|
|
ib = 0UL;
|
|
i = 0UL;
|
|
while (i<b_len-1 && b[i]) {
|
|
if (b[i]=='|') {
|
|
ib = ia;
|
|
ia = i+1UL;
|
|
}
|
|
++i;
|
|
}
|
|
if (((ib>0UL && (ia-ib&1)) && ia-ib>=5UL) && ia-ib<=15UL) {
|
|
/*& (b[ia]=0C)*/
|
|
i = 0UL;
|
|
j = ib;
|
|
do {
|
|
t[i] = 0U;
|
|
if (!r91(&t[i], b[j]) || !r91(&t[i], b[j+1UL])) return;
|
|
++i;
|
|
j += 2UL;
|
|
} while (j+1UL<ia);
|
|
tmp = i-1UL;
|
|
ia = 0UL;
|
|
if (ia<=tmp) for (;; ia++) {
|
|
v[ia] = t[ia]+1U;
|
|
if (ia==tmp) break;
|
|
} /* end for */
|
|
/* b[ib-1]:=0C; */
|
|
aprsstr_Delstr(b, b_len, ib-1UL, (j-ib)+2UL);
|
|
}
|
|
} /* end GetTLM() */
|
|
|
|
/* === multiline */
|
|
|
|
extern void aprsdecode_GetMultiline(char buf[], uint32_t buf_len,
|
|
uint32_t * delfrom, struct aprsdecode_MULTILINE * md)
|
|
{
|
|
uint32_t idx;
|
|
uint32_t s;
|
|
uint32_t i;
|
|
char c;
|
|
float v;
|
|
float scale;
|
|
md->size = 0UL;
|
|
md->linetyp = 'a';
|
|
md->filltyp = '0';
|
|
i = 0UL;
|
|
s = 0UL;
|
|
*delfrom = (buf_len-1)+1UL;
|
|
while (i<buf_len-1 && buf[i]) {
|
|
c = buf[i];
|
|
if (s==0UL) {
|
|
if (c==' ') {
|
|
s = 1UL;
|
|
*delfrom = i;
|
|
}
|
|
}
|
|
else if (s==1UL) {
|
|
if (c=='}') s = 2UL;
|
|
else s = 0UL;
|
|
}
|
|
else if (s==2UL) {
|
|
if ((uint8_t)c>='a' && (uint8_t)c<='l') {
|
|
md->linetyp = c;
|
|
s = 3UL;
|
|
}
|
|
else s = 0UL;
|
|
}
|
|
else if (s==3UL) {
|
|
if ((uint8_t)c>='0' && (uint8_t)c<='9') {
|
|
md->filltyp = c;
|
|
s = 4UL;
|
|
}
|
|
else s = 0UL;
|
|
}
|
|
else if (s==4UL) {
|
|
if ((uint8_t)c>='!' && (uint8_t)c<='q') {
|
|
scale = osic_exp((float)((uint32_t)(uint8_t)c-33UL)
|
|
*1.15129255E-1f)*1.7453292519444E-6f;
|
|
/* 10^(x/20)*0.0001 deg */
|
|
s = 5UL;
|
|
idx = 0UL;
|
|
}
|
|
else s = 0UL;
|
|
}
|
|
else if (s==5UL || s==6UL) {
|
|
if ((uint8_t)c>='!' && (uint8_t)c<='z') {
|
|
if (idx<=40UL) {
|
|
v = ((float)(uint32_t)(uint8_t)c-78.0f)*scale;
|
|
/*WrFixed(v/RAD, 5, 10); WrStrLn(" deg"); */
|
|
if (s==5UL) {
|
|
md->vec[idx].lat = v;
|
|
s = 6UL;
|
|
}
|
|
else {
|
|
md->vec[idx].long0 = -v;
|
|
s = 5UL;
|
|
++idx;
|
|
}
|
|
}
|
|
else s = 0UL;
|
|
}
|
|
else if (s==5UL && c=='{') s = 7UL;
|
|
else s = 0UL;
|
|
/*
|
|
ELSIF (s>=7) & (s<=11) THEN
|
|
IF c>" " THEN INC(s) ELSE s:=0 END;
|
|
IF s=12 THEN
|
|
md.size:=idx;
|
|
RETURN (* protocol done *)
|
|
|
|
END;
|
|
*/
|
|
if (s==7UL) {
|
|
md->size = idx;
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
/* protocol done */
|
|
s = 0UL;
|
|
}
|
|
++i;
|
|
}
|
|
} /* end GetMultiline() */
|
|
|
|
|
|
extern char aprsdecode_ismultiline(char editing)
|
|
{
|
|
char s[251];
|
|
uint32_t i;
|
|
struct aprsdecode_MULTILINE ml;
|
|
if (editing) {
|
|
useri_confstr(useri_fRBPOSTYP, s, 251ul);
|
|
if (s[0U]!='L') return 0;
|
|
}
|
|
useri_confstr(useri_fRBCOMMENT, s, 251ul);
|
|
aprsdecode_GetMultiline(s, 251ul, &i, &ml);
|
|
return ml.size>=2UL;
|
|
} /* end ismultiline() */
|
|
|
|
#define aprsdecode_GRIDSIZE 88
|
|
|
|
#define aprsdecode_RA 3.4377467707849E+7
|
|
|
|
|
|
static void app(char buf[], uint32_t buf_len, float d)
|
|
{
|
|
char tmp;
|
|
/*WrFixed(d, 5, 8); WrStr(" "); */
|
|
d = d+78.5f;
|
|
if (d>=33.0f && d<=209.0f) {
|
|
aprsstr_Append(buf, buf_len,
|
|
(char *)(tmp = (char)aprsdecode_trunc(d),&tmp),
|
|
1u/1u);
|
|
}
|
|
} /* end app() */
|
|
|
|
|
|
static void EncMultiline(char buf[], uint32_t buf_len,
|
|
struct aprspos_POSITION * center,
|
|
struct aprsdecode_MULTILINE md)
|
|
{
|
|
uint32_t i;
|
|
uint32_t scaler;
|
|
float scale;
|
|
struct aprspos_POSITION max0;
|
|
struct aprspos_POSITION min0;
|
|
/* find size */
|
|
struct aprspos_POSITION * anonym;
|
|
char tmp;
|
|
min0.lat = 6.283185307f;
|
|
min0.long0 = 6.283185307f;
|
|
max0.lat = (-6.283185307f);
|
|
max0.long0 = (-6.283185307f);
|
|
i = 0UL;
|
|
while (i<md.size) {
|
|
{ /* with */
|
|
struct aprspos_POSITION * anonym = &md.vec[i];
|
|
if (anonym->lat<min0.lat) min0.lat = anonym->lat;
|
|
if (anonym->lat>max0.lat) max0.lat = anonym->lat;
|
|
if (anonym->long0<min0.long0) min0.long0 = anonym->long0;
|
|
if (anonym->long0>max0.long0) max0.long0 = anonym->long0;
|
|
}
|
|
++i;
|
|
}
|
|
center->lat = (max0.lat+min0.lat)*0.5f;
|
|
center->long0 = (max0.long0+min0.long0)*0.5f;
|
|
scale = max0.lat-min0.lat;
|
|
if (max0.long0-min0.long0>scale) scale = max0.long0-min0.long0;
|
|
/*WrFixed(scale, 10, 15); WrStrLn(" scaleo"); */
|
|
if (scale<1.57079632675f) {
|
|
if (scale>0.0f) {
|
|
scaler = aprsdecode_trunc(X2C_DIVR(osic_ln(X2C_DIVR(scale,
|
|
1.5358897417111E-4f)),1.15129255E-1f)+1.0f);
|
|
/*WrInt(scaler, 10);WrStrLn(" scaler"); */
|
|
scale = osic_exp((float)scaler*1.15129255E-1f)
|
|
*1.5358897417111E-4f; /* 10^(x/20)*0.0001 deg */
|
|
/*WrFixed(scale, 10, 15); WrStrLn(" scale"); */
|
|
scale = X2C_DIVR(88.0f,scale);
|
|
}
|
|
else {
|
|
scaler = 0UL;
|
|
scale = 0.0f;
|
|
}
|
|
aprsstr_Assign(buf, buf_len, " }", 3ul);
|
|
aprsstr_Append(buf, buf_len, (char *) &md.linetyp, 1u/1u);
|
|
aprsstr_Append(buf, buf_len, (char *) &md.filltyp, 1u/1u);
|
|
aprsstr_Append(buf, buf_len,
|
|
(char *)(tmp = (char)(33UL+scaler),&tmp), 1u/1u);
|
|
i = 0UL;
|
|
while (i<md.size) {
|
|
app(buf, buf_len, (md.vec[i].lat-center->lat)*scale);
|
|
app(buf, buf_len, (center->long0-md.vec[i].long0)*scale);
|
|
++i;
|
|
}
|
|
/* scale:=ln(scale/(0.0001*RAD))/(2.3025851/20.0); */
|
|
aprsstr_Append(buf, buf_len, "{", 2ul);
|
|
}
|
|
else {
|
|
/*
|
|
lati :=trunc(ABS(center.lat) *RA);
|
|
longi:=trunc(ABS(center.long)*RA);
|
|
latd :=VAL(CARDINAL, lati ) MOD 100;
|
|
longd:=VAL(CARDINAL, longi) MOD 100;
|
|
lati :=lati -latd;
|
|
longi:=longi-longd;
|
|
|
|
WrInt(latd,0); WrStrLn(" latd");
|
|
*/
|
|
/*WrStrLn(" <-appended"); */
|
|
buf[0UL] = 0;
|
|
}
|
|
} /* end EncMultiline() */
|
|
|
|
|
|
extern void aprsdecode_appendmultiline(struct aprspos_POSITION pos)
|
|
{
|
|
char h[251];
|
|
char cso[251];
|
|
char cs[251];
|
|
struct aprsdecode_MULTILINE ml;
|
|
struct aprspos_POSITION center;
|
|
uint32_t i;
|
|
char msgc;
|
|
/* make absolute */
|
|
struct aprspos_POSITION * anonym;
|
|
useri_confstr(useri_fRBPOS, cs, 251ul);
|
|
if (cs[0U]) aprstext_deganytopos(cs, 251ul, ¢er);
|
|
else aprsdecode_posinval(¢er);
|
|
useri_confstr(useri_fRBCOMMENT, cso, 251ul);
|
|
aprsdecode_GetMultiline(cso, 251ul, &i, &ml);
|
|
if (i<=250UL) cso[i] = 0;
|
|
if (ml.size<2UL) aprsdecode_click.insreplaceline = 1;
|
|
/*WrStr("<<<");WrStr(cso);WrStrLn(">>> csodel"); */
|
|
i = 0UL;
|
|
while (i<ml.size) {
|
|
{ /* with */
|
|
struct aprspos_POSITION * anonym = &ml.vec[i];
|
|
anonym->lat = anonym->lat+center.lat;
|
|
anonym->long0 = anonym->long0+center.long0;
|
|
}
|
|
++i;
|
|
}
|
|
if (ml.size>40UL) ml.size = 41UL;
|
|
if (aprsdecode_click.polilinecursor>=ml.size) {
|
|
aprsdecode_click.polilinecursor = ml.size;
|
|
}
|
|
if (aprspos_posvalid(pos)) {
|
|
if (aprsdecode_click.insreplaceline) {
|
|
if (ml.size<40UL) {
|
|
/* insert line */
|
|
i = 40UL;
|
|
while (i>0UL && i>aprsdecode_click.polilinecursor) {
|
|
ml.vec[i] = ml.vec[i-1UL];
|
|
--i;
|
|
}
|
|
ml.vec[aprsdecode_click.polilinecursor] = pos;
|
|
if (aprsdecode_click.polilinecursor>=ml.size) {
|
|
++aprsdecode_click.polilinecursor;
|
|
}
|
|
++ml.size;
|
|
}
|
|
}
|
|
else ml.vec[aprsdecode_click.polilinecursor] = pos;
|
|
}
|
|
else {
|
|
/* delete line */
|
|
i = aprsdecode_click.polilinecursor;
|
|
while (i<40UL) {
|
|
ml.vec[i] = ml.vec[i+1UL];
|
|
++i;
|
|
}
|
|
if (ml.size>0UL) --ml.size;
|
|
}
|
|
if (ml.size<=33UL) msgc = 'b';
|
|
else if (ml.size<40UL) msgc = 'r';
|
|
else msgc = 'e';
|
|
aprsstr_IntToStr((int32_t)ml.size, 0UL, h, 251ul);
|
|
aprsstr_Append(h, 251ul, " elements", 10ul);
|
|
useri_textautosize(0L, 0L, 6UL, 2UL, msgc, h, 251ul);
|
|
EncMultiline(cs, 251ul, ¢er, ml);
|
|
aprsstr_Append(cso, 251ul, cs, 251ul);
|
|
useri_AddConfLine(useri_fRBCOMMENT, 1U, cso, 251ul);
|
|
/*WrInt(ml.size, 10); WrStr("<<<");WrStr(cso);WrStrLn(">>> csoapp"); */
|
|
aprstext_postostr(center, '3', cs, 251ul);
|
|
useri_AddConfLine(useri_fRBPOS, 1U, cs, 251ul); /* update new center */
|
|
aprsdecode_tracenew.winevent = 2000UL;
|
|
} /* end appendmultiline() */
|
|
|
|
|
|
extern void aprsdecode_modmultiline(uint32_t n)
|
|
{
|
|
struct aprspos_POSITION pos;
|
|
struct aprsdecode_MULTILINE ml;
|
|
uint32_t i;
|
|
char s[251];
|
|
uint32_t v;
|
|
if (n==1UL) {
|
|
/* del line */
|
|
aprsdecode_posinval(&pos);
|
|
aprsdecode_appendmultiline(pos);
|
|
}
|
|
else {
|
|
useri_confstr(useri_fRBCOMMENT, s, 251ul);
|
|
aprsdecode_GetMultiline(s, 251ul, &i, &ml);
|
|
if (n==2UL) {
|
|
/* colour */
|
|
if (ml.size>0UL) {
|
|
v = (uint32_t)(uint8_t)s[i+2UL];
|
|
v += 3UL;
|
|
if (v>108UL) v -= 12UL;
|
|
s[i+2UL] = (char)v;
|
|
}
|
|
}
|
|
else if (n==3UL) {
|
|
/* colour */
|
|
if (ml.size>0UL) {
|
|
v = (uint32_t)(uint8_t)s[i+2UL];
|
|
++v;
|
|
if (v%3UL==1UL) v -= 3UL;
|
|
s[i+2UL] = (char)v;
|
|
}
|
|
}
|
|
else if (n==4UL) {
|
|
/* poliline/poligone */
|
|
if (ml.size>0UL) {
|
|
s[i+3UL] = (char)((uint32_t)(uint8_t)s[i+3UL]+1UL);
|
|
if ((uint8_t)s[i+3UL]<'0' || (uint8_t)s[i+3UL]>'9') {
|
|
s[i+3UL] = '0';
|
|
}
|
|
}
|
|
}
|
|
useri_AddConfLine(useri_fRBCOMMENT, 1U, s, 251ul);
|
|
}
|
|
aprsdecode_tracenew.winevent = 2000UL;
|
|
} /* end modmultiline() */
|
|
|
|
/* === multiline */
|
|
/*
|
|
PROCEDURE checksymb(symt, symb:CHAR):BOOLEAN;
|
|
(* true for bad symbol *)
|
|
BEGIN
|
|
(*
|
|
RETURN (symt<>"/") & (symt<>"\") & ((InStr("#&0>AW^_acnsuvz", symb)<0)
|
|
OR ((symt<"0") OR (symt>"9")) & ((symt<"A") OR (symt>"Z")))
|
|
*)
|
|
RETURN (symt<>"/") & (symt<>"\") & (((symt<"0") OR (symt>"9"))
|
|
& ((symt<"A") OR (symt>"Z")) & ((symt<"a") OR (symt>"z")))
|
|
END checksymb;
|
|
*/
|
|
static aprsdecode_SET256 _cnst = {0x00000000UL,0x03FF8000UL,0x17FFFFFEUL,
|
|
0x07FFFFFEUL,0x00000000UL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL};
|
|
|
|
extern int32_t aprsdecode_Decode(char buf[], uint32_t buf_len,
|
|
struct aprsdecode_DAT * dat)
|
|
{
|
|
uint32_t ia;
|
|
uint32_t iv;
|
|
uint32_t micedest;
|
|
uint32_t len;
|
|
uint32_t p;
|
|
uint32_t i;
|
|
char thirdparty;
|
|
memset((char *)dat,(char)0,sizeof(struct aprsdecode_DAT));
|
|
dat->speed = X2C_max_longcard;
|
|
dat->altitude = X2C_max_longint;
|
|
NoWX(&dat->wx);
|
|
len = 0UL;
|
|
while ((len<buf_len-1 && buf[len]) && buf[len]!='\015') ++len;
|
|
if (len==0UL || buf[0UL]=='#') return -1L;
|
|
i = 0UL;
|
|
do {
|
|
/* skip 3rd party headers */
|
|
p = i;
|
|
while (i<len && buf[i]!=':') ++i;
|
|
i += 2UL;
|
|
} while (!(i>len || buf[i-1UL]!='}'));
|
|
thirdparty = p!=0UL;
|
|
i = 0UL;
|
|
while (buf[p]!='>') {
|
|
/* source call */
|
|
if (p>=len || i>8UL) return -1L;
|
|
dat->symcall[i] = buf[p];
|
|
++p;
|
|
++i;
|
|
}
|
|
memcpy(dat->srcall,dat->symcall,9u);
|
|
++p;
|
|
micedest = p;
|
|
i = 0UL;
|
|
while (buf[p]!=',' && buf[p]!=':') {
|
|
/* dest call */
|
|
if (p>=len || i>8UL) return -1L;
|
|
dat->dstcall[i] = buf[p];
|
|
++p;
|
|
++i;
|
|
}
|
|
iv = 0UL;
|
|
while (buf[p]==',') {
|
|
if (iv>9UL) iv = 9UL;
|
|
++p;
|
|
if (((((thirdparty && buf[p]=='T') && buf[p+1UL]=='C')
|
|
&& buf[p+2UL]=='P') && buf[p+3UL]=='I')
|
|
&& buf[p+4UL]=='P' || ((buf[p]=='q' && buf[p+1UL]=='A')
|
|
&& buf[p+2UL]!='C') && iv<9UL) dat->igatep = iv+1UL;
|
|
if (dat->igatep==iv) dat->igaterawp = p;
|
|
i = 0UL;
|
|
while (buf[p]!=',' && buf[p]!=':') {
|
|
if (p>=len) return -1L;
|
|
if (buf[p]=='*') {
|
|
if (dat->igatep==0UL && dat->hbitp==0UL) dat->hbitp = iv+1UL;
|
|
}
|
|
else if (i<=8UL) {
|
|
dat->viacalls[iv][i] = buf[p];
|
|
++i;
|
|
}
|
|
++p;
|
|
}
|
|
/* IF dat.igatep=iv THEN dat.igatelen:=p-dat.igaterawp END; */
|
|
if (dat->igatep==iv) dat->igatelen = i;
|
|
++iv;
|
|
}
|
|
if (dat->hbitp>0UL || iv>(uint32_t)(dat->igatep!=0UL)
|
|
*2UL && viaghost(dat->viacalls[0UL], 9ul)) {
|
|
/* maybe not direct */
|
|
i = 0UL;
|
|
while ((i<9UL && i<dat->hbitp) && iscall(dat->viacalls[i])) ++i;
|
|
dat->hbitp = i+1UL;
|
|
}
|
|
else dat->hbitp = 0UL;
|
|
/*WrInt(dat.hbitp, 1);WrStrLn("=h"); */
|
|
if (p+1UL>=len || buf[p]!=':') return -1L;
|
|
++p;
|
|
dat->payload = p;
|
|
dat->typc = buf[dat->payload];
|
|
switch ((unsigned)dat->typc) {
|
|
case '\034':
|
|
case '\035':
|
|
case '\'':
|
|
case '`':
|
|
dat->type = aprsdecode_MICE;
|
|
break;
|
|
case '!':
|
|
case '$':
|
|
case '/':
|
|
case '=':
|
|
case '@':
|
|
dat->type = aprsdecode_POS;
|
|
break;
|
|
case '#':
|
|
case '*':
|
|
dat->type = aprsdecode_WETH;
|
|
break;
|
|
case '_':
|
|
dat->type = aprsdecode_PWETH;
|
|
dat->sym = '_'; /* positionless wx */
|
|
dat->symt = '/';
|
|
break;
|
|
case ':':
|
|
dat->type = aprsdecode_MSG;
|
|
break;
|
|
case ';':
|
|
dat->type = aprsdecode_OBJ;
|
|
break;
|
|
case ')':
|
|
dat->type = aprsdecode_ITEM;
|
|
break;
|
|
case '<':
|
|
dat->type = aprsdecode_SCAP;
|
|
break;
|
|
case '>':
|
|
dat->type = aprsdecode_STAT;
|
|
break;
|
|
case 'T':
|
|
dat->type = aprsdecode_TELE;
|
|
break;
|
|
case '?':
|
|
dat->type = aprsdecode_QUERY;
|
|
break;
|
|
default:;
|
|
dat->type = aprsdecode_UNKNOWN;
|
|
break;
|
|
} /* end switch */
|
|
++p;
|
|
if (dat->type==aprsdecode_OBJ) {
|
|
/* object */
|
|
if (buf[p+9UL]=='_' || buf[p+9UL]=='*') {
|
|
memcpy(dat->objectfrom,dat->symcall,9u);
|
|
i = 0UL;
|
|
while (i<=8UL) {
|
|
if (p+i>=len) return -1L;
|
|
dat->symcall[i] = buf[p+i];
|
|
++i;
|
|
}
|
|
if (buf[p+i]=='_') dat->objkill = '1';
|
|
else if (buf[p+i]!='*') dat->type = aprsdecode_UNKNOWN;
|
|
dat->timestamp = buf[p+16UL];
|
|
while (i>0UL && (uint8_t)dat->symcall[i-1UL]<=' ') {
|
|
dat->symcall[i-1UL] = 0;
|
|
--i;
|
|
}
|
|
}
|
|
else dat->type = aprsdecode_UNKNOWN;
|
|
}
|
|
else if (dat->typc==')') {
|
|
/* item */
|
|
memcpy(dat->objectfrom,dat->symcall,9u);
|
|
i = 0UL;
|
|
while (buf[p+i]!='!' && buf[p+i]!='_') {
|
|
if (p+i>=len) return -1L;
|
|
if (i<=8UL) dat->symcall[i] = buf[p+i];
|
|
++i;
|
|
}
|
|
if (i<=8UL) dat->symcall[i] = 0;
|
|
if (buf[p+i]=='_') dat->objkill = '1';
|
|
}
|
|
else if (dat->typc==':') {
|
|
/* msg, bulletin */
|
|
if (buf[p+9UL]==':') {
|
|
i = 0UL;
|
|
while (i<9UL && p<len) {
|
|
if (i<=8UL && (uint8_t)buf[p]>' ') dat->msgto[i] = buf[p];
|
|
++i;
|
|
++p;
|
|
}
|
|
if (X2C_STRCMP(dat->msgto,9u,dat->symcall,9u)==0) {
|
|
dat->type = aprsdecode_TELE; /* msg to itself */
|
|
}
|
|
++p;
|
|
i = 0UL;
|
|
if ((buf[p]=='r' && buf[p+1UL]=='e') && buf[p+2UL]=='j') {
|
|
dat->ackrej = aprsdecode_MSGREJ; /* reject */
|
|
}
|
|
else if ((buf[p]=='a' && buf[p+1UL]=='c') && buf[p+2UL]=='k') {
|
|
dat->ackrej = aprsdecode_MSGACK; /* ack */
|
|
}
|
|
if (dat->ackrej>aprsdecode_MSGMSG) {
|
|
p += 3UL;
|
|
while ((i<=4UL && (uint8_t)buf[p]>' ') && p<len) {
|
|
dat->acktext[i] = buf[p];
|
|
++i;
|
|
++p;
|
|
}
|
|
}
|
|
else {
|
|
i = p;
|
|
ia = len;
|
|
while (i<len) {
|
|
/* find last { */
|
|
if (buf[i]=='{') ia = i;
|
|
++i;
|
|
}
|
|
i = 0UL;
|
|
while (i<=66UL && p<ia) {
|
|
/* message text */
|
|
dat->msgtext[i] = buf[p];
|
|
++i;
|
|
++p;
|
|
}
|
|
dat->ackrej = aprsdecode_MSGMSG;
|
|
if (buf[p]=='{') {
|
|
/* message ack */
|
|
i = 0UL;
|
|
++p;
|
|
while ((i<=4UL && (uint8_t)buf[p]>' ') && p<len) {
|
|
dat->acktext[i] = buf[p];
|
|
++i;
|
|
++p;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (dat->typc=='?') {
|
|
/* general query */
|
|
i = 0UL;
|
|
while ((i<9UL && (uint8_t)buf[p]>' ') && p<len) {
|
|
if (i<=8UL) dat->msgto[i] = buf[p];
|
|
++i;
|
|
++p;
|
|
}
|
|
}
|
|
/* dat.course:=MAX(CARDINAL); */
|
|
dat->course = 0UL;
|
|
if (X2C_IN((int32_t)dat->type,12,0xCEU)) {
|
|
aprspos_GetPos(&dat->pos, &dat->speed, &dat->course, &dat->altitude,
|
|
&dat->sym, &dat->symt, buf, buf_len, micedest, dat->payload,
|
|
dat->comment0, 256ul, &dat->postyp);
|
|
aprspos_GetSym(dat->dstcall, 9ul, &dat->sym, &dat->symt);
|
|
if (!X2C_INL((uint8_t)dat->symt,256,_cnst)) {
|
|
dat->symt = 0; /* wrong symbol */
|
|
dat->sym = 0;
|
|
}
|
|
if (dat->postyp=='A' && dat->type==aprsdecode_OBJ) {
|
|
/* area object */
|
|
dat->areasymb.typ = (char)((dat->course/100UL)%10UL+48UL);
|
|
dat->areasymb.color = (uint8_t)(dat->speed/100UL);
|
|
dat->areasymb.dpos.lat = sqr((float)(dat->course%100UL))
|
|
*1.454441043287E-6f;
|
|
dat->areasymb.dpos.long0 = sqr((float)(dat->speed%100UL))
|
|
*1.454441043287E-6f;
|
|
if (dat->areasymb.typ=='6') {
|
|
dat->areasymb.dpos.long0 = -dat->areasymb.dpos.long0;
|
|
/* line to left down */
|
|
}
|
|
dat->pos.lat = dat->pos.lat-dat->areasymb.dpos.lat;
|
|
dat->pos.long0 = dat->pos.long0+dat->areasymb.dpos.long0;
|
|
/* shift pos to middle of area */
|
|
dat->speed = 0UL;
|
|
dat->course = 0UL;
|
|
}
|
|
if (dat->type==aprsdecode_OBJ || dat->type==aprsdecode_ITEM) {
|
|
aprsdecode_GetMultiline(dat->comment0, 256ul, &i, &dat->multiline);
|
|
if (dat->multiline.size>0UL) dat->postyp = 'L';
|
|
}
|
|
GetHRT(&dat->pos, &dat->altitude, &dat->speed, dat->comment0, 256ul,
|
|
dat->hrtposes, 32ul, &dat->hrtlen, &dat->hrttime);
|
|
GetTLM(dat->tlmvalues, dat->comment0, 256ul);
|
|
}
|
|
else {
|
|
i = 0UL;
|
|
p = dat->payload+(uint32_t)(dat->type!=aprsdecode_UNKNOWN);
|
|
while (p<len && i<=255UL) {
|
|
dat->comment0[i] = buf[p];
|
|
++p;
|
|
++i;
|
|
}
|
|
}
|
|
if (X2C_IN((int32_t)dat->type,12,0xCCU)) {
|
|
if (dat->sym=='_' || dat->type==aprsdecode_PWETH) {
|
|
if (dat->type==aprsdecode_PWETH) {
|
|
aprsstr_Delstr(dat->comment0, 256ul, 0UL, 8UL);
|
|
}
|
|
GetWX(&dat->wx, &dat->course, &dat->speed, dat->comment0, 256ul, 0);
|
|
}
|
|
else if (dat->sym=='@') {
|
|
GetWX(&dat->wx, &dat->course, &dat->speed, dat->comment0, 256ul, 1);
|
|
}
|
|
/*
|
|
IF dat.wx.storm>WXNORMAL THEN
|
|
dat.areasymb.typ:="5"; (* circle *)
|
|
dat.areasymb.color:=5;
|
|
dat.areasymb.dpos.lat :=0.006;
|
|
dat.areasymb.dpos.long:=0.0;
|
|
END;
|
|
*/
|
|
if (dat->course<1UL || dat->course>360UL) dat->course = 0UL;
|
|
}
|
|
return 0L;
|
|
} /* end Decode() */
|
|
|
|
|
|
static char getbeaconparm(char s[], uint32_t s_len,
|
|
uint32_t * time0, char * port)
|
|
/* time:port:rawframe */
|
|
{
|
|
uint32_t i;
|
|
*port = s[0UL];
|
|
if ((uint8_t)*port<' ' || s[1UL]!=':') return 0;
|
|
*time0 = 0UL;
|
|
i = 2UL;
|
|
while ((uint8_t)s[i]>='0' && (uint8_t)s[i]<='9') {
|
|
*time0 = ( *time0*10UL+(uint32_t)(uint8_t)s[i])-48UL;
|
|
++i;
|
|
}
|
|
if (s[i]!=':') return 0;
|
|
aprsstr_Delstr(s, s_len, 0UL, i+1UL);
|
|
return 1;
|
|
} /* end getbeaconparm() */
|
|
|
|
|
|
extern void aprsdecode_getbeaconname(char raw[], uint32_t raw_len,
|
|
char name[], uint32_t name_len, char symb[],
|
|
uint32_t symb_len, char * isobj,
|
|
char * isdel, char * isbad)
|
|
/* item object else src name */
|
|
{
|
|
struct aprsdecode_DAT dat;
|
|
char port;
|
|
uint32_t time0;
|
|
X2C_PCOPY((void **)&raw,raw_len);
|
|
*isobj = 0;
|
|
*isdel = 0;
|
|
*isbad = 1;
|
|
name[0UL] = 0;
|
|
if (getbeaconparm(raw, raw_len, &time0, &port)) {
|
|
beaconmacros(raw, raw_len, "", 1ul, "", 1ul, 0);
|
|
if (aprsdecode_Decode(raw, raw_len, &dat)==0L) {
|
|
aprsstr_Assign(name, name_len, dat.symcall, 9ul);
|
|
aprsstr_Assign(symb, symb_len, (char *) &dat.symt, 1u/1u);
|
|
aprsstr_Append(symb, symb_len, (char *) &dat.sym, 1u/1u);
|
|
*isobj = dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM;
|
|
*isdel = dat.objkill=='1';
|
|
*isbad = (uint8_t)dat.symt<' ' || (uint8_t)name[0UL]<=' ';
|
|
}
|
|
else *isbad = 1;
|
|
}
|
|
X2C_PFREE(raw);
|
|
} /* end getbeaconname() */
|
|
|
|
|
|
extern void aprsdecode_extractbeacon(char raw[], uint32_t raw_len,
|
|
char withparm, char macros)
|
|
/* monitor line to beacon config */
|
|
{
|
|
struct aprsdecode_DAT dat;
|
|
char port;
|
|
uint32_t i;
|
|
uint32_t time0;
|
|
int32_t j;
|
|
char s[1000];
|
|
X2C_PCOPY((void **)&raw,raw_len);
|
|
if (withparm) {
|
|
if (getbeaconparm(raw, raw_len, &time0, &port)) {
|
|
if (macros) beaconmacros(raw, raw_len, "", 1ul, "", 1ul, 0);
|
|
aprsstr_IntToStr((int32_t)time0, 0UL, s, 1000ul);
|
|
useri_AddConfLine(useri_fRBTIME, 1U, s, 1000ul);
|
|
useri_AddConfLine(useri_fRBPORT, 1U, (char *) &port, 1u/1u);
|
|
}
|
|
else {
|
|
useri_say("\012beacon syntax wrong, delete line!\012", 36ul, 4UL,
|
|
'e');
|
|
}
|
|
}
|
|
if (aprsdecode_Decode(raw, raw_len, &dat)==0L) {
|
|
if (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM) {
|
|
aprsstr_Assign(s, 1000ul, dat.symcall, 9ul);
|
|
}
|
|
else {
|
|
useri_confstr(useri_fMYCALL, s, 1000ul);
|
|
if (aprstext_callwrong(s, 1000ul)) {
|
|
useri_xerrmsg("need legal \'My Call\' to build Beacon", 37ul);
|
|
}
|
|
}
|
|
useri_AddConfLine(useri_fRBNAME, 1U, s, 1000ul);
|
|
if (aprspos_posvalid(dat.pos)) {
|
|
if (dat.postyp=='A' && dat.type==aprsdecode_OBJ) {
|
|
/* area object */
|
|
dat.pos.lat = dat.pos.lat+dat.areasymb.dpos.lat;
|
|
dat.pos.long0 = dat.pos.long0-dat.areasymb.dpos.long0;
|
|
/* shift pos to upleft of area */
|
|
}
|
|
aprstext_postostr(dat.pos, '3', s, 1000ul);
|
|
useri_AddConfLine(useri_fRBPOS, 1U, s, 1000ul);
|
|
}
|
|
useri_AddConfLine(useri_fRBCOMMENT, 1U, dat.comment0, 256ul);
|
|
s[0U] = dat.symt;
|
|
s[1U] = dat.sym;
|
|
s[2U] = 0;
|
|
useri_AddConfLine(useri_fRBSYMB, 1U, s, 1000ul);
|
|
useri_AddConfLine(useri_fRBSPEED, 1U, "", 1ul);
|
|
useri_AddConfLine(useri_fRBDIR, 1U, "", 1ul);
|
|
if ((uint8_t)dat.areasymb.typ>='0') {
|
|
/* IntToStr(dat.areasymb.color*100+trunc(sqrt(dat.areasymb.dpos.long/(RAD/200.0/60.0)
|
|
)), 1, s); */
|
|
aprsstr_IntToStr((int32_t)((uint32_t)
|
|
dat.areasymb.color*100UL+aprsdecode_trunc(osic_sqrt(X2C_DIVR((float)
|
|
fabs(dat.areasymb.dpos.long0),1.454441043287E-6f)))), 1UL, s,
|
|
1000ul);
|
|
useri_AddConfLine(useri_fRBSPEED, 1U, s, 1000ul);
|
|
aprsstr_IntToStr((int32_t)(((uint32_t)(uint8_t)
|
|
dat.areasymb.typ-48UL)
|
|
*100UL+aprsdecode_trunc(osic_sqrt(X2C_DIVR((float)
|
|
fabs(dat.areasymb.dpos.lat),1.454441043287E-6f)))), 1UL, s,
|
|
1000ul);
|
|
useri_AddConfLine(useri_fRBDIR, 1U, s, 1000ul);
|
|
}
|
|
else if (dat.speed>0UL && dat.speed<2147483647UL) {
|
|
aprsstr_IntToStr((int32_t)aprsdecode_trunc((float)
|
|
dat.speed*1.852f), 1UL, s, 1000ul);
|
|
useri_AddConfLine(useri_fRBSPEED, 1U, s, 1000ul);
|
|
if (dat.course>0UL) {
|
|
aprsstr_IntToStr((int32_t)(dat.course%360UL), 1UL, s, 1000ul);
|
|
useri_AddConfLine(useri_fRBDIR, 1U, s, 1000ul);
|
|
}
|
|
}
|
|
if (dat.altitude<X2C_max_longint) {
|
|
aprsstr_IntToStr(dat.altitude, 1UL, s, 1000ul);
|
|
}
|
|
else s[0U] = 0;
|
|
useri_AddConfLine(useri_fRBALT, 1U, s, 1000ul);
|
|
s[1U] = 0;
|
|
s[0U] = 'b';
|
|
if (dat.type==aprsdecode_OBJ) {
|
|
if (dat.timestamp=='h') s[0U] = 'H';
|
|
else s[0U] = 'O';
|
|
if (dat.objkill=='1') s[0U] = 'P';
|
|
}
|
|
else if (dat.type==aprsdecode_ITEM) {
|
|
if (dat.objkill=='1') s[0U] = 'J';
|
|
else s[0U] = 'I';
|
|
}
|
|
useri_AddConfLine(useri_fRBTYP, 1U, s, 1000ul);
|
|
useri_AddConfLine(useri_fRBPOSTYP, 1U, (char *) &dat.postyp,
|
|
1u/1u);
|
|
if (withparm) {
|
|
s[0U] = 0;
|
|
j = aprsstr_InStr(dat.dstcall, 9ul, "-", 2ul);
|
|
/* move dest ssid to viapath */
|
|
if (j>=0L) {
|
|
aprsstr_Assign(s, 1000ul, dat.dstcall, 9ul);
|
|
aprsstr_Delstr(s, 1000ul, 0UL, (uint32_t)j);
|
|
dat.dstcall[j] = 0;
|
|
}
|
|
if (dat.type==aprsdecode_MICE) strncpy(dat.dstcall,"APLM01",9u);
|
|
useri_AddConfLine(useri_fRBDEST, 1U, dat.dstcall, 9ul);
|
|
useri_AddConfLine(useri_fRBNAME, 1U, dat.symcall, 9ul);
|
|
i = 0UL;
|
|
while (i<=9UL && dat.viacalls[i][0UL]) {
|
|
/* make via path */
|
|
if (s[0U]) aprsstr_Append(s, 1000ul, ",", 2ul);
|
|
aprsstr_Append(s, 1000ul, dat.viacalls[i], 9ul);
|
|
++i;
|
|
}
|
|
useri_AddConfLine(useri_fRBPATH, 1U, s, 1000ul);
|
|
}
|
|
else useri_AddConfLine(useri_fRBDEST, 1U, "APLM01", 7ul);
|
|
}
|
|
X2C_PFREE(raw);
|
|
} /* end extractbeacon() */
|
|
|
|
|
|
extern void aprsdecode_importbeacon(void)
|
|
{
|
|
/* op last pos frame to beacon config */
|
|
aprsdecode_pOPHIST opf;
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST pl;
|
|
aprsdecode_pFRAMEHIST pf;
|
|
struct aprsdecode_DAT dat;
|
|
if (useri_beaconediting && aprsdecode_click.entries>0UL) {
|
|
opf = aprsdecode_click.table[aprsdecode_click.selected].opf;
|
|
if (opf) {
|
|
op = aprsdecode_ophist0;
|
|
while (op && X2C_STRCMP(opf->call,9u,op->call,9u)) op = op->next;
|
|
if (op) {
|
|
pl = 0;
|
|
pf = op->frames;
|
|
while (pf) {
|
|
if (aprspos_posvalid(pf->vardat->pos)) pl = pf;
|
|
pf = pf->next;
|
|
}
|
|
if ((pl && pl->vardat) && aprsdecode_Decode(pl->vardat->raw,
|
|
500ul, &dat)==0L) {
|
|
aprsdecode_extractbeacon(pl->vardat->raw, 500ul, 0, 0);
|
|
useri_beaconed = 1;
|
|
useri_textautosize(0L, 0L, 5UL, 5UL, 'b', "Object Cloned to Be\
|
|
acon Editor!", 32ul);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} /* end importbeacon() */
|
|
|
|
|
|
static void beepmsg(char isack)
|
|
{
|
|
if (useri_configon(useri_fBEEPMSG)) {
|
|
aprsdecode_beeplim(100L, (uint32_t)useri_conf2int(useri_fBEEPMSG,
|
|
(uint32_t)isack*2UL, 20L, 8000L, 1000L),
|
|
(uint32_t)useri_conf2int(useri_fBEEPMSG,
|
|
(uint32_t)isack*2UL+1UL, 0L, 5000L, 250L));
|
|
}
|
|
} /* end beepmsg() */
|
|
|
|
|
|
static void popupmessage(const char from[], uint32_t from_len,
|
|
const char to[], uint32_t to_len, const char txt[],
|
|
uint32_t txt_len, const char ack[],
|
|
uint32_t ack_len, uint32_t time0, char port,
|
|
char isquery0, char kill,
|
|
struct aprspos_POSITION pos, const char item[],
|
|
uint32_t item_len)
|
|
{
|
|
aprsdecode_pMSGFIFO pl;
|
|
aprsdecode_pMSGFIFO pm;
|
|
int32_t cnt;
|
|
pm = aprsdecode_msgfifo0;
|
|
pl = 0;
|
|
while (pm) {
|
|
/* delete older same messages */
|
|
if (((aprsstr_StrCmp(pm->from, 9ul, from,
|
|
from_len) && aprsstr_StrCmp(pm->to, 9ul, to,
|
|
to_len)) && aprsstr_StrCmp(pm->txt, 67ul, txt,
|
|
txt_len)) && aprsstr_StrCmp(pm->ack, 5ul, ack, ack_len)) {
|
|
if (pl==0) aprsdecode_msgfifo0 = pm->next;
|
|
else pl->next = pm->next;
|
|
osic_free((char * *) &pm, sizeof(struct aprsdecode_MSGFIFO));
|
|
pm = aprsdecode_msgfifo0;
|
|
pl = 0;
|
|
}
|
|
else {
|
|
pl = pm;
|
|
pm = pm->next;
|
|
}
|
|
}
|
|
osic_alloc((char * *) &pm, sizeof(struct aprsdecode_MSGFIFO));
|
|
if (pm==0) {
|
|
osi_WrStrLn("msg out of memory", 18ul);
|
|
return;
|
|
}
|
|
aprsstr_Assign(pm->from, 9ul, from, from_len);
|
|
aprsstr_Assign(pm->to, 9ul, to, to_len);
|
|
aprsstr_Assign(pm->txt, 67ul, txt, txt_len);
|
|
aprsstr_Assign(pm->ack, 5ul, ack, ack_len);
|
|
aprsstr_Assign(pm->itemname, 9ul, item, item_len);
|
|
pm->itempos = pos;
|
|
pm->time0 = time0;
|
|
pm->port = port;
|
|
pm->query = isquery0;
|
|
pm->next = 0;
|
|
pm->deleteitem = kill;
|
|
cnt = 1L;
|
|
if (aprsdecode_msgfifo0==0) aprsdecode_msgfifo0 = pm;
|
|
else {
|
|
cnt = 2L;
|
|
pl = aprsdecode_msgfifo0;
|
|
while (pl->next) {
|
|
pl = pl->next;
|
|
++cnt;
|
|
}
|
|
pl->next = pm;
|
|
}
|
|
if (useri_nextmsg==0L) {
|
|
if (useri_configon(useri_fPOPUPMSG)) useri_nextmsg = -cnt;
|
|
}
|
|
else useri_nextmsg = -labs(useri_nextmsg);
|
|
} /* end popupmessage() */
|
|
|
|
|
|
extern void aprsdecode_getactack(aprsdecode_MONCALL call, char ack[],
|
|
uint32_t ack_len)
|
|
/* get actual message ack */
|
|
{
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST pf;
|
|
struct aprsdecode_DAT dat;
|
|
char mid[2];
|
|
char aa[2];
|
|
char ok0;
|
|
aprsdecode_MONCALL my;
|
|
ack[0UL] = 0;
|
|
op = findop(call, 0);
|
|
if (op) {
|
|
useri_confstr(useri_fMYCALL, my, 9ul);
|
|
pf = op->frames;
|
|
while (pf) {
|
|
if (((aprsdecode_Decode(pf->vardat->raw, 500ul,
|
|
&dat)>=0L && dat.type==aprsdecode_MSG)
|
|
&& dat.ackrej==aprsdecode_MSGMSG) && X2C_STRCMP(dat.msgto,9u,
|
|
my,9u)==0) {
|
|
ok0 = replyack(aa, 2ul, mid, 2ul, dat.acktext, 5ul);
|
|
if (mid[0U]) aprsstr_Assign(ack, ack_len, mid, 2ul);
|
|
}
|
|
pf = pf->next;
|
|
}
|
|
}
|
|
} /* end getactack() */
|
|
|
|
|
|
static char ch(uint32_t n)
|
|
{
|
|
if (n<10UL) n += 48UL;
|
|
else if (n<36UL) n += 55UL;
|
|
else n += 61UL;
|
|
return (char)n;
|
|
} /* end ch() */
|
|
|
|
|
|
extern void aprsdecode_acknumstr(char aa[], uint32_t aa_len,
|
|
uint32_t n)
|
|
{
|
|
aa[0UL] = ch((n/62UL)%62UL);
|
|
aa[1UL] = ch(n%62UL);
|
|
if (aa_len-1>=2UL) aa[2UL] = 0;
|
|
} /* end acknumstr() */
|
|
|
|
|
|
static char sendtxmsg(uint32_t acknum, const aprsdecode_MONCALL to,
|
|
const char txt[], uint32_t txt_len, char port,
|
|
char rfonly, uint32_t ackcnt, char errm[],
|
|
uint32_t errm_len)
|
|
{
|
|
uint32_t i;
|
|
aprsdecode_FRAMEBUF s;
|
|
aprsdecode_FRAMEBUF rfs;
|
|
char am[51];
|
|
char h1[51];
|
|
char h[51];
|
|
char tmp;
|
|
if (ackcnt==0UL) strncpy(am,"Ack ",51u);
|
|
else strncpy(am,"Msg ",51u);
|
|
errm[0UL] = 0;
|
|
if (to[0UL]==0) return 0;
|
|
useri_confstr(useri_fMYCALL, rfs, 512ul);
|
|
if (aprstext_callwrong(rfs, 512ul)) {
|
|
aprsstr_Assign(errm, errm_len, "Msg not sent (no valid Mycall)", 31ul);
|
|
return 0;
|
|
}
|
|
aprsstr_Append(rfs, 512ul, ">", 2ul);
|
|
if (rfonly) useri_confstr(useri_fMSGRFDEST, h, 51ul);
|
|
else useri_confstr(useri_fMSGNETDEST, h, 51ul);
|
|
aprsstr_Append(rfs, 512ul, h, 51ul);
|
|
if (h[0U]==0) {
|
|
aprsstr_Assign(errm, errm_len, am, 51ul);
|
|
aprsstr_Append(errm, errm_len, "not sent (no Port set)", 23ul);
|
|
return 0;
|
|
}
|
|
if (port=='A' || (uint8_t)port>='1' && (uint8_t)port<='9') {
|
|
/* radio so add via path */
|
|
useri_confstr(useri_fMSGPATH, h, 51ul);
|
|
if ((uint8_t)h[0U]>='1' && (uint8_t)h[0U]<='7') {
|
|
aprsstr_Append(rfs, 512ul, "-", 2ul);
|
|
aprsstr_Append(rfs, 512ul, (char *) &h[0U], 1u/1u);
|
|
}
|
|
else if (h[0U]) {
|
|
aprsstr_Append(rfs, 512ul, ",", 2ul);
|
|
aprsstr_Append(rfs, 512ul, h, 51ul);
|
|
}
|
|
}
|
|
aprsstr_Append(rfs, 512ul, ":", 2ul);
|
|
strncpy(s,":",512u);
|
|
aprsstr_Append(s, 512ul, to, 9ul);
|
|
for (i = aprsstr_Length(to, 9ul); i<=8UL; i++) {
|
|
aprsstr_Append(s, 512ul, " ", 2ul);
|
|
} /* end for */
|
|
aprsstr_Append(s, 512ul, ":", 2ul);
|
|
if (ackcnt==0UL) aprsstr_Append(s, 512ul, "ack", 4ul);
|
|
aprsstr_Append(s, 512ul, txt, txt_len);
|
|
if (acknum>0UL) {
|
|
aprsstr_Append(s, 512ul, "{", 2ul);
|
|
aprsdecode_acknumstr(h, 51ul, acknum);
|
|
aprsstr_Append(s, 512ul, h, 51ul);
|
|
aprsstr_Append(s, 512ul, "}", 2ul);
|
|
aprsdecode_getactack(to, h, 51ul);
|
|
if (h[0U]) aprsstr_Append(s, 512ul, h, 51ul);
|
|
}
|
|
/*WrInt(ORD(rfonly), 10);WrStrLn(port); */
|
|
aprsstr_Append(rfs, 512ul, s, 512ul);
|
|
for (i = 0UL; i<=3UL; i++) {
|
|
/* try the rf ports */
|
|
if ((useri_configon((uint8_t)(36UL+i))
|
|
&& (port=='A' || port==(char)(i+49UL))) && Sendudp(rfs,
|
|
512ul, i, 0UL)>0L) {
|
|
memcpy(h,am,51u);
|
|
if (ackcnt==1UL) aprsstr_Append(h, 51ul, "sent", 5ul);
|
|
else {
|
|
aprsstr_Append(h, 51ul, "resent(", 8ul);
|
|
aprsstr_IntToStr((int32_t)ackcnt, 0UL, h1, 51ul);
|
|
aprsstr_Append(h, 51ul, h1, 51ul);
|
|
aprsstr_Append(h, 51ul, ")", 2ul);
|
|
}
|
|
aprsstr_Append(h, 51ul, " to ", 5ul);
|
|
aprsstr_Append(h, 51ul, to, 9ul);
|
|
aprsstr_Append(h, 51ul, " on Port ", 10ul);
|
|
aprsstr_Append(h, 51ul, (char *)(tmp = (char)(i+49UL),&tmp),
|
|
1u/1u);
|
|
useri_say(h, 51ul, 2UL, 'b');
|
|
return 1;
|
|
}
|
|
} /* end for */
|
|
/* make it better */
|
|
if (!rfonly && port=='N') {
|
|
SendNet(aprsdecode_tcpsocks, "", 1ul, s, 512ul, 1, errm, errm_len);
|
|
if (errm[0UL]) {
|
|
memcpy(h,am,51u);
|
|
aprsstr_Append(h, 51ul, "not sent ", 10ul);
|
|
aprsstr_Append(h, 51ul, errm, errm_len);
|
|
aprsstr_Assign(errm, errm_len, h, 51ul);
|
|
}
|
|
else {
|
|
memcpy(h,am,51u);
|
|
aprsstr_Append(h, 51ul, "(re)sent to ", 13ul);
|
|
aprsstr_Append(h, 51ul, to, 9ul);
|
|
aprsstr_Append(h, 51ul, " on Net", 8ul);
|
|
useri_say(h, 51ul, 2UL, 'b');
|
|
}
|
|
return 1;
|
|
}
|
|
else {
|
|
aprsstr_Assign(errm, errm_len, am, 51ul);
|
|
aprsstr_Append(errm, errm_len, "not sent (delete Msg or open outgoing P\
|
|
ort)", 44ul);
|
|
return 0;
|
|
}
|
|
return 0;
|
|
} /* end sendtxmsg() */
|
|
|
|
|
|
static void iteminmsg(const char from[], uint32_t from_len,
|
|
const char to[], uint32_t to_len, const char txt[],
|
|
uint32_t txt_len, struct aprspos_POSITION * pos,
|
|
char name[], uint32_t name_len, char * del)
|
|
/* test for and draw item in a message */
|
|
{
|
|
char h[1000];
|
|
char s[1000];
|
|
struct aprsdecode_DAT dat;
|
|
aprsdecode_posinval(pos);
|
|
aprsstr_Assign(s, 1000ul, from, from_len);
|
|
aprsstr_Append(s, 1000ul, ">", 2ul);
|
|
aprsstr_Append(s, 1000ul, to, to_len);
|
|
aprsstr_Append(s, 1000ul, ":", 2ul);
|
|
aprsstr_Append(s, 1000ul, txt, txt_len);
|
|
if ((aprsdecode_Decode(s, 1000ul,
|
|
&dat)>=0L && dat.type==aprsdecode_ITEM)
|
|
&& aprspos_posvalid(dat.pos)) {
|
|
aprsstr_Assign(h, 1000ul, "0:0:", 5ul);
|
|
aprsstr_Append(h, 1000ul, s, 1000ul);
|
|
aprsdecode_drawbeacon(h, 1000ul);
|
|
*pos = dat.pos;
|
|
aprsstr_Assign(name, name_len, dat.symcall, 9ul);
|
|
*del = dat.objkill=='1';
|
|
}
|
|
} /* end iteminmsg() */
|
|
|
|
|
|
static void ackmsg(const char from[], uint32_t from_len,
|
|
const char rep[], uint32_t rep_len, uint8_t rej)
|
|
{
|
|
aprsdecode_pTXMESSAGE pm;
|
|
char bb[2];
|
|
char aa[2];
|
|
/*
|
|
WrStr("replyack:");
|
|
WrStr(from);
|
|
WrStr("|");
|
|
WrStr(rep);
|
|
WrStr("|");
|
|
WrLn;
|
|
*/
|
|
if (rej==aprsdecode_MSGMSG) {
|
|
if (!replyack(bb, 2ul, aa, 2ul, rep, rep_len)) return;
|
|
}
|
|
else {
|
|
/* message only */
|
|
aprsstr_Assign(bb, 2ul, rep, rep_len);
|
|
}
|
|
pm = aprsdecode_txmessages;
|
|
while (pm) {
|
|
if (pm->acktime==0UL && X2C_STRCMP(from,from_len,pm->to,9u)==0) {
|
|
aprsdecode_acknumstr(aa, 2ul, pm->acknum);
|
|
if (X2C_STRCMP(aa,2u,bb,2u)==0) {
|
|
/* message acked now */
|
|
pm->acktime = aprsdecode_realtime;
|
|
pm->rej = rej==aprsdecode_MSGREJ;
|
|
useri_refresh = 1;
|
|
/*WrInt(ORD(rej), 10); WrStrLn("=rej"); */
|
|
beepmsg(1);
|
|
}
|
|
}
|
|
pm = pm->next;
|
|
}
|
|
} /* end ackmsg() */
|
|
|
|
#define aprsdecode_QUERYRESPONSEWINDOW 30
|
|
/* time after sending a msg to display already received query response */
|
|
|
|
|
|
static void showmsg(const char from[], uint32_t from_len,
|
|
const char to[], uint32_t to_len, const char txt[],
|
|
uint32_t txt_len, const char ack[],
|
|
uint32_t ack_len, uint8_t rej, char my,
|
|
char query, char port)
|
|
{
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST opf;
|
|
aprsdecode_ACKTEXT aack;
|
|
aprsdecode_ACKTEXT rep;
|
|
aprsdecode_MONCALL call;
|
|
struct aprsdecode_DAT dat;
|
|
struct aprspos_POSITION itempos;
|
|
aprsdecode_MONCALL itemname;
|
|
char delitem;
|
|
char s[501];
|
|
opf = 0;
|
|
if (ack[0UL]) {
|
|
aprsstr_Assign(call, 9ul, from, from_len);
|
|
op = findop(call, 1); /* find sender of msg */
|
|
if (op) {
|
|
opf = op->frames;
|
|
for (;;) {
|
|
if (opf==0) break;
|
|
if ((((aprsdecode_Decode(opf->vardat->raw, 500ul,
|
|
&dat)>=0L && dat.type==aprsdecode_MSG)
|
|
&& dat.ackrej==aprsdecode_MSGMSG) && X2C_STRCMP(dat.msgto,9u,
|
|
to,to_len)==0) && X2C_STRCMP(txt,txt_len,dat.msgtext,
|
|
67u)==0) {
|
|
if (ack[0UL]==0) {
|
|
if (lastmsgtx+30UL<aprsdecode_realtime) {
|
|
break; /* we do not wait for a query response */
|
|
}
|
|
}
|
|
else if (X2C_STRCMP(dat.acktext,5u,ack,
|
|
ack_len)==0 || replyack(rep, 5ul, aack, 5ul, dat.acktext,
|
|
5ul) && X2C_STRCMP(aack,5u,ack,ack_len)==0) {
|
|
break; /* we have this msg got before */
|
|
}
|
|
}
|
|
opf = opf->next;
|
|
}
|
|
}
|
|
}
|
|
if (opf==0) {
|
|
if (my || useri_configon(useri_fMSGALLSSID) && (!aprsstr_StrCmp(from,
|
|
from_len, to, to_len) || useri_configon(useri_fPASSSELFMSG))) {
|
|
if (!useri_configon(useri_fPOPUPMSG)) {
|
|
if (query) strncpy(s,"Query from ",501u);
|
|
else strncpy(s,"Message from ",501u);
|
|
aprsstr_Append(s, 501ul, from, from_len);
|
|
aprsstr_Append(s, 501ul, " to ", 5ul);
|
|
aprsstr_Append(s, 501ul, to, to_len);
|
|
aprsstr_Append(s, 501ul, " (click on M Button)", 21ul);
|
|
useri_textautosize(0L, 5L, 6UL, 0UL, 'y', s, 501ul);
|
|
}
|
|
iteminmsg(from, from_len, to, to_len, txt, txt_len, &itempos,
|
|
itemname, 9ul, &delitem);
|
|
popupmessage(from, from_len, to, to_len, txt, txt_len, ack, ack_len,
|
|
aprsdecode_realtime, port, query, delitem, itempos,
|
|
itemname, 9ul);
|
|
++aprsdecode_tracenew.winevent;
|
|
beepmsg(0);
|
|
}
|
|
}
|
|
else if (aprsdecode_verb) {
|
|
osi_WrStr("seen msg:", 10ul);
|
|
osi_WrStr(from, from_len);
|
|
osi_WrStr(">", 2ul);
|
|
osi_WrStr(to, to_len);
|
|
osi_WrStr("|", 2ul);
|
|
osi_WrStr(txt, txt_len);
|
|
osi_WrStr("|", 2ul);
|
|
osi_WrStr(ack, ack_len);
|
|
osi_WrStr("|", 2ul);
|
|
osi_WrStr((char *) &port, 1u/1u);
|
|
osic_WrLn();
|
|
}
|
|
} /* end showmsg() */
|
|
|
|
|
|
static char isquery(const struct aprsdecode_DAT dat, char port)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char err[201];
|
|
char wdata[201];
|
|
char key[201];
|
|
char path[201];
|
|
char s[201];
|
|
/* IF dat.msgtext[0]<>"?" THEN RETURN FALSE END; */
|
|
aprsstr_Assign(path, 201ul, dat.symcall, 9ul);
|
|
aprsstr_Append(path, 201ul, ">", 2ul);
|
|
aprsstr_Append(path, 201ul, dat.dstcall, 9ul);
|
|
i = 0UL;
|
|
while (dat.viacalls[i][0UL]) {
|
|
aprsstr_Append(path, 201ul, ",", 2ul);
|
|
aprsstr_Append(path, 201ul, dat.viacalls[i], 9ul);
|
|
if (i+2UL==dat.hbitp) aprsstr_Append(path, 201ul, "*", 2ul);
|
|
++i;
|
|
}
|
|
i = 0UL;
|
|
for (;;) {
|
|
useri_confstrings(useri_fQUERYS, i, 0, s, 201ul);
|
|
if (s[0U]==0) break;
|
|
j = (uint32_t)aprsstr_InStr(s, 201ul, ":", 2ul);
|
|
if (j>0UL) {
|
|
aprsstr_Assign(key, 201ul, s, 201ul);
|
|
key[j] = 0;
|
|
aprsstr_Delstr(s, 201ul, 0UL, j+1UL);
|
|
if (aprsstr_InStr(dat.msgtext, 67ul, key, 201ul)==0L) {
|
|
aprsstr_Assign(wdata, 201ul, dat.msgtext, 67ul);
|
|
aprsstr_Delstr(wdata, 201ul, 0UL, aprsstr_Length(key, 201ul));
|
|
beaconmacros(s, 201ul, path, 201ul, wdata, 201ul, 1);
|
|
if (s[0U]==0) return 1;
|
|
if (!sendtxmsg(0UL, dat.symcall, s, 201ul, port, port!='N', 1UL,
|
|
err, 201ul)) {
|
|
useri_xerrmsg(err, 201ul);
|
|
return 0;
|
|
}
|
|
else {
|
|
useri_xerrmsg(err, 201ul);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
++i;
|
|
}
|
|
/*WrStrLn(port);WrStrLn(dat.symcall);WrStrLn(dat.msgtext); */
|
|
return 0;
|
|
} /* end isquery() */
|
|
|
|
|
|
static void getmessage(aprsdecode_pTCPSOCK cp, uint32_t up,
|
|
const struct aprsdecode_DAT dat)
|
|
/* if first: popup, if full match & lastack>10s: send ack */
|
|
{
|
|
uint32_t i;
|
|
char void0;
|
|
char query;
|
|
char fit;
|
|
char my[100];
|
|
char h[100];
|
|
char port;
|
|
/* my:MONCALL; */
|
|
char ch0;
|
|
useri_confstr(useri_fMYCALL, my, 100ul);
|
|
if (aprstext_callwrong(my, 100ul)) return;
|
|
aprsstr_Assign(h, 100ul, dat.msgto, 9ul);
|
|
fit = 0;
|
|
i = 0UL;
|
|
while (h[i]==my[i] && h[i]) {
|
|
if (h[i]=='-' || my[i]=='-') fit = 1;
|
|
++i;
|
|
}
|
|
if (i==0UL) return;
|
|
ch0 = my[i];
|
|
if (h[i]==0 && ch0=='-' || h[i]=='-' && ch0==0) fit = 1;
|
|
if (cp) port = 'N';
|
|
else port = (char)(up+48UL);
|
|
if (ch0==0 && h[i]==0) {
|
|
/* WrStr("my message "); */
|
|
if (dat.ackrej==aprsdecode_MSGMSG) {
|
|
/*FOR i:=0 TO HIGH(dat.acktext) DO WrInt(ORD(dat.acktext[i]), 4);
|
|
END; WrStrLn("=ack"); */
|
|
query = isquery(dat, port);
|
|
showmsg(dat.symcall, 9ul, dat.msgto, 9ul, dat.msgtext, 67ul,
|
|
dat.acktext, 5ul, dat.ackrej, 1, query, port);
|
|
if (!query && dat.acktext[0UL]) {
|
|
void0 = sendtxmsg(0UL, dat.symcall, dat.acktext, 5ul, port,
|
|
port!='N', 0UL, h, 100ul);
|
|
useri_xerrmsg(h, 100ul);
|
|
}
|
|
}
|
|
if (dat.acktext[0UL]) {
|
|
ackmsg(dat.symcall, 9ul, dat.acktext, 5ul, dat.ackrej);
|
|
}
|
|
}
|
|
else if (fit && dat.ackrej==aprsdecode_MSGMSG) {
|
|
/* WrStr("other ssid message "); */
|
|
showmsg(dat.symcall, 9ul, dat.msgto, 9ul, dat.msgtext, 67ul,
|
|
dat.acktext, 5ul, dat.ackrej, 0, 0, port);
|
|
}
|
|
} /* end getmessage() */
|
|
|
|
#define aprsdecode_SETPORT 2
|
|
|
|
#define aprsdecode_DEL 6
|
|
|
|
#define aprsdecode_KICK 5
|
|
|
|
#define aprsdecode_RESTART 4
|
|
|
|
#define aprsdecode_HOLD 3
|
|
|
|
#define aprsdecode_EDIT 1
|
|
|
|
|
|
extern void aprsdecode_deltxmsg(uint32_t cmd, uint32_t n)
|
|
/* delete/edit tx message number */
|
|
{
|
|
aprsdecode_pTXMESSAGE po;
|
|
aprsdecode_pTXMESSAGE pm;
|
|
pm = aprsdecode_txmessages;
|
|
if (pm) {
|
|
if (cmd==6UL || cmd==1UL) {
|
|
if (n==0UL) aprsdecode_txmessages = aprsdecode_txmessages->next;
|
|
else {
|
|
do {
|
|
po = pm;
|
|
pm = pm->next;
|
|
--n;
|
|
} while (!(n==0UL || pm==0));
|
|
if (pm) po->next = pm->next;
|
|
}
|
|
if (pm) {
|
|
if (cmd==1UL) {
|
|
useri_AddConfLine(useri_fMSGTEXT, 0U, pm->msgtext, 67ul);
|
|
useri_AddConfLine(useri_fMSGTO, 0U, pm->to, 9ul);
|
|
useri_AddConfLine(useri_fMSGPORT, 0U, (char *) &pm->port,
|
|
1u/1u);
|
|
}
|
|
osic_free((char * *) &pm,
|
|
sizeof(struct aprsdecode_TXMESSAGE));
|
|
}
|
|
}
|
|
else {
|
|
while (n>0UL && pm) {
|
|
pm = pm->next;
|
|
--n;
|
|
}
|
|
if (pm && pm->acktime==0UL) {
|
|
if (cmd==5UL) pm->txtime = 0UL;
|
|
else if (cmd==4UL) {
|
|
pm->txtime = 0UL;
|
|
pm->acktime = 0UL;
|
|
pm->txcnt = 0UL;
|
|
pm->heard = 0;
|
|
}
|
|
else if (cmd==3UL) pm->txtime = X2C_max_longcard;
|
|
else if (cmd==2UL) {
|
|
useri_confstr(useri_fMSGPORT, (char *) &pm->port, 1u/1u);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} /* end deltxmsg() */
|
|
|
|
|
|
extern void aprsdecode_makemsg(char ack)
|
|
{
|
|
aprsdecode_pTXMESSAGE pn;
|
|
aprsdecode_pTXMESSAGE pm;
|
|
char po;
|
|
char ht[101];
|
|
char hm[101];
|
|
char mes[101];
|
|
int32_t i;
|
|
char c;
|
|
struct aprsdecode_TXMESSAGE * anonym;
|
|
int32_t tmp;
|
|
mes[0U] = 0;
|
|
useri_confstr(useri_fMSGPORT, (char *) &po, 1u/1u);
|
|
if (po==' ' || X2C_CAP(po)=='A') po = 'A';
|
|
else if (X2C_CAP(po)=='N' || X2C_CAP(po)=='I') po = 'N';
|
|
else if ((uint8_t)po<'0' || (uint8_t)po>'9') {
|
|
strncpy(mes,"need Port where to send",101u);
|
|
}
|
|
useri_confstr(useri_fMSGTO, ht, 101ul); /* no destination call */
|
|
if (ht[0U]==0) strncpy(mes,"need call to send to",101u);
|
|
useri_confstr(useri_fMSGTEXT, hm, 101ul);
|
|
if (hm[0U]==0) {
|
|
/* empty message line */
|
|
if (!sentemptymsg) {
|
|
strncpy(mes,"send empty line? if so, enter again",101u);
|
|
sentemptymsg = 1;
|
|
}
|
|
else sentemptymsg = 0;
|
|
}
|
|
else sentemptymsg = 0;
|
|
pn = aprsdecode_txmessages; /* look for same msg pending */
|
|
while (pn) {
|
|
if (((((ack && pn->acknum>0UL) && pn->acktime==0UL)
|
|
&& aprsstr_StrCmp(pn->to, 9ul, ht,
|
|
101ul)) && aprsstr_StrCmp(pn->msgtext, 67ul, hm,
|
|
101ul)) && pn->port==po) {
|
|
strncpy(mes,"same message pending, try [kick] or delete",101u);
|
|
}
|
|
pn = pn->next;
|
|
}
|
|
if (mes[0U]==0) {
|
|
osic_alloc((char * *) &pm, sizeof(struct aprsdecode_TXMESSAGE));
|
|
if (pm==0) Err("out of memory", 14ul);
|
|
memset((char *)pm,(char)0,sizeof(struct aprsdecode_TXMESSAGE));
|
|
{ /* with */
|
|
struct aprsdecode_TXMESSAGE * anonym = pm;
|
|
anonym->port = po;
|
|
useri_confstr(useri_fMSGTO, anonym->to, 9ul);
|
|
aprsstr_Caps(anonym->to, 9ul);
|
|
useri_confstr(useri_fMSGTEXT, anonym->msgtext, 67ul);
|
|
tmp = (int32_t)aprsstr_Length(anonym->msgtext, 67ul)-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
c = anonym->msgtext[i];
|
|
if (c=='|' || c=='~') {
|
|
/* OR (c=cMSGACK) */
|
|
anonym->msgtext[i] = ' ';
|
|
}
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
if (ack) {
|
|
if (msgmid==0UL) {
|
|
msgmid = (aprsdecode_realtime%68400UL)/30UL;
|
|
/* init msg number with 30s daytime */
|
|
}
|
|
msgmid = (msgmid+1UL)%3843UL;
|
|
anonym->acknum = msgmid+1UL; /* 0 is query with no ack */
|
|
}
|
|
}
|
|
pn = aprsdecode_txmessages;
|
|
if (pn==0) aprsdecode_txmessages = pm;
|
|
else {
|
|
while (pn->next) pn = pn->next;
|
|
pn->next = pm;
|
|
}
|
|
useri_clrmsgtext("", 1ul);
|
|
useri_textautosize(0L, 5L, 6UL, 5UL, 'b', "Msg Stored", 11ul);
|
|
}
|
|
useri_xerrmsg(mes, 101ul);
|
|
} /* end makemsg() */
|
|
|
|
#define aprsdecode_MAXMSGTXTIME 3600
|
|
|
|
#define aprsdecode_MAXMSGRETRY 20
|
|
|
|
#define aprsdecode_MAXNOACKRETRY 1
|
|
|
|
#define aprsdecode_MSGNOTXTIME 10
|
|
|
|
#define aprsdecode_MSGTXTIME 15
|
|
|
|
/* my:MONCALL; */
|
|
|
|
static void sendmsg(void)
|
|
{
|
|
aprsdecode_pTXMESSAGE pn;
|
|
aprsdecode_pTXMESSAGE pm;
|
|
uint32_t t;
|
|
uint32_t maxret;
|
|
uint32_t tc;
|
|
char port;
|
|
char sent;
|
|
char err[101];
|
|
if (lastmsgtx>aprsdecode_realtime) lastmsgtx = aprsdecode_realtime;
|
|
/* confstr(fMYCALL, my); */
|
|
/* IF (lastmsgtx+MSGNOTXTIME<realtime) & (Length(my)>=3) THEN */
|
|
if (lastmsgtx+10UL<aprsdecode_realtime) {
|
|
err[0U] = 0;
|
|
pm = aprsdecode_txmessages;
|
|
for (;;) {
|
|
if (pm==0) break;
|
|
if (pm->acknum>0UL) maxret = 20UL;
|
|
else maxret = 1UL;
|
|
if ((pm->acktime==0UL && pm->txtime!=X2C_max_longcard)
|
|
&& (pm->txcnt<maxret || pm->txtime==0UL)) {
|
|
tc = pm->txcnt;
|
|
t = 15UL;
|
|
for (;;) {
|
|
if (tc<=1UL) break;
|
|
t += t;
|
|
--tc;
|
|
if (t>3600UL) {
|
|
t = 3600UL;
|
|
break;
|
|
}
|
|
}
|
|
if (pm->txtime+t<=aprsdecode_realtime) {
|
|
pn = aprsdecode_txmessages;
|
|
while (pn!=pm && ((((pn->acknum==0UL || pn->acktime>0UL)
|
|
|| pn->txcnt>=20UL) || !aprsstr_StrCmp(pn->to, 9ul, pm->to,
|
|
9ul)) || pn->txtime==X2C_max_longcard)) pn = pn->next;
|
|
if (pn==pm) {
|
|
/* not older unacked msg to this call */
|
|
port = pm->port;
|
|
sent = 0;
|
|
if ((pm->txcnt<=(uint32_t)pm->heard || pm->txtime==0UL)
|
|
&& (port=='N' || port=='A')) {
|
|
if (sendtxmsg(pm->acknum, pm->to, pm->msgtext, 67ul,
|
|
'N', 0, pm->txcnt+1UL, err, 101ul) && err[0U]==0) sent = 1;
|
|
}
|
|
if (port=='A' || (uint8_t)port>='1' && (uint8_t)
|
|
port<='9') {
|
|
if (sendtxmsg(pm->acknum, pm->to, pm->msgtext, 67ul,
|
|
port, sent || port!='A', pm->txcnt+1UL, err,
|
|
101ul) && err[0U]==0) sent = 1;
|
|
else if (sent || pm->txcnt>0UL) err[0U] = 0;
|
|
}
|
|
if (sent) {
|
|
++pm->txcnt;
|
|
pm->txtime = aprsdecode_realtime;
|
|
lastmsgtx = aprsdecode_realtime;
|
|
useri_refresh = 1;
|
|
break; /* send 1 msg a time */
|
|
}
|
|
}
|
|
}
|
|
}
|
|
pm = pm->next;
|
|
}
|
|
useri_xerrmsg(err, 101ul);
|
|
}
|
|
} /* end sendmsg() */
|
|
|
|
|
|
static void setmsgheard(const aprsdecode_MONCALL us)
|
|
/* set heard flag in tx msg if user heard now */
|
|
{
|
|
aprsdecode_pTXMESSAGE pm;
|
|
pm = aprsdecode_txmessages;
|
|
for (;;) {
|
|
if (pm==0) break;
|
|
if ((pm->acktime==0UL && pm->txcnt==1UL) && aprsstr_StrCmp(pm->to, 9ul,
|
|
us, 9ul)) pm->heard = 1;
|
|
pm = pm->next;
|
|
}
|
|
} /* end setmsgheard() */
|
|
|
|
|
|
extern aprsdecode_pOPHIST aprsdecode_selop(void)
|
|
{
|
|
if (aprsdecode_click.entries>0UL) {
|
|
return aprsdecode_click.table[aprsdecode_click.selected].opf;
|
|
}
|
|
else return 0;
|
|
return 0;
|
|
} /* end selop() */
|
|
|
|
/*
|
|
PROCEDURE objsender(op:pOPHIST; VAR s:ARRAY OF CHAR);
|
|
(* find (last) sender of an item/object *)
|
|
VAR dat:DAT;
|
|
f:pFRAMEHIST;
|
|
BEGIN
|
|
s[0]:=0C;
|
|
IF (op<>NIL) & (ISOBJECT IN op^.drawhints) THEN
|
|
f:=op^.frames;
|
|
IF f<>NIL THEN
|
|
WHILE f^.next<>NIL DO f:=f^.next END;
|
|
(* goto last frame *)
|
|
IF (Decode(f^.vardat^.raw, dat)>=0) & ((dat.type=OBJ) OR (dat.type=ITEM))
|
|
THEN Assign(s, dat.objectfrom) END;
|
|
END;
|
|
END;
|
|
END objsender;
|
|
*/
|
|
|
|
extern void aprsdecode_objsender(aprsdecode_pOPHIST op, char s[],
|
|
uint32_t s_len)
|
|
/* find (last) sender of an item/object */
|
|
{
|
|
struct aprsdecode_DAT dat;
|
|
aprsdecode_pFRAMEHIST f;
|
|
aprsdecode_pOPHIST o;
|
|
s[0UL] = 0;
|
|
if (op) {
|
|
if ((0x2U & op->drawhints)) {
|
|
f = op->frames;
|
|
if (f) {
|
|
while (f->next) f = f->next;
|
|
if (aprsdecode_Decode(f->vardat->raw, 500ul,
|
|
&dat)>=0L && (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM)
|
|
) aprsstr_Assign(s, s_len, dat.objectfrom, 9ul);
|
|
}
|
|
}
|
|
else {
|
|
o = aprsdecode_ophist0;
|
|
for (;;) {
|
|
if (o==0) break;
|
|
f = o->frames;
|
|
if (((f && aprsdecode_Decode(f->vardat->raw, 500ul,
|
|
&dat)>=0L) && (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM)
|
|
) && X2C_STRCMP(dat.objectfrom,9u,op->call,9u)==0) {
|
|
aprsstr_Assign(s, s_len, op->call, 9ul);
|
|
break;
|
|
}
|
|
o = o->next;
|
|
}
|
|
}
|
|
}
|
|
} /* end objsender() */
|
|
|
|
#define aprsdecode_MAXDELAY 30
|
|
/* add seconds to time */
|
|
|
|
|
|
static void timespeed(aprsdecode_pFRAMEHIST lastf,
|
|
struct aprspos_POSITION pos1, uint32_t time1,
|
|
uint8_t * err)
|
|
{
|
|
float d;
|
|
uint32_t t;
|
|
if (((((*err&0xFU)!=0U || lastf==0) || (lastf->nodraw&0xFU)!=0U)
|
|
|| !aprspos_posvalid(lastf->vardat->pos))
|
|
|| !aprspos_posvalid(pos1)) return;
|
|
d = aprspos_distance(lastf->vardat->pos, pos1);
|
|
/*
|
|
IF d>50.0 THEN INCL(err, eDIST) END;
|
|
*/
|
|
if (lastf->time0>=time1) t = 0UL;
|
|
else t = time1-lastf->time0;
|
|
if (X2C_DIVR(d*3600.0f,(float)(t+30UL))>maxspeed) *err |= 0x10U;
|
|
} /* end timespeed() */
|
|
|
|
#define aprsdecode_MINHOP 20.0
|
|
|
|
#define aprsdecode_HOPPART 0.5
|
|
/* MINSPIKE=0.02; (* min distance to mark as spike *) */
|
|
|
|
#define aprsdecode_SPIKEANGLE 30.0
|
|
/* min deg spanned by 3 waypoints for no SPIKE */
|
|
|
|
|
|
/* 1 wayout, delete before, 2 wayout join last good with last else delete before */
|
|
static void joinchunk(aprsdecode_pOPHIST op)
|
|
{
|
|
aprsdecode_pFRAMEHIST lbad;
|
|
aprsdecode_pFRAMEHIST bad;
|
|
aprsdecode_pFRAMEHIST lllpf;
|
|
aprsdecode_pFRAMEHIST llpf;
|
|
aprsdecode_pFRAMEHIST lpf;
|
|
aprsdecode_pFRAMEHIST pf;
|
|
aprsdecode_pVARDAT v;
|
|
float kml;
|
|
float km;
|
|
float ang;
|
|
float waylen;
|
|
waylen = (float)op->lastkmh*0.03f+20.0f;
|
|
lllpf = 0;
|
|
llpf = 0;
|
|
lpf = 0;
|
|
pf = op->frames;
|
|
lbad = 0;
|
|
while (pf) {
|
|
v = pf->vardat;
|
|
if (aprspos_posvalid(v->pos) && (pf->nodraw&0xCU)==0U) {
|
|
if (lpf) {
|
|
km = aprspos_distance(lpf->vardat->pos, v->pos);
|
|
if (llpf && km!=0.0f) {
|
|
/* we have 3 waypoints */
|
|
kml = aprspos_distance(lpf->vardat->pos, llpf->vardat->pos);
|
|
if (kml!=0.0f) {
|
|
ang = (float)fabs(aprspos_azimuth(lpf->vardat->pos,
|
|
v->pos)-aprspos_azimuth(lpf->vardat->pos,
|
|
llpf->vardat->pos));
|
|
if (ang>180.0f) ang = 360.0f-ang;
|
|
if (ang<30.0f) {
|
|
/* a spike */
|
|
if (lllpf==0) {
|
|
/* first spike */
|
|
lpf->nodraw = lpf->nodraw&~0x10U|0x2U;
|
|
pf->nodraw &= ~0x10U;
|
|
lllpf = llpf;
|
|
}
|
|
else {
|
|
/* second spike */
|
|
if (km>aprspos_distance(llpf->vardat->pos, v->pos)) {
|
|
lpf->nodraw = lpf->nodraw&~0x10U|0x2U;
|
|
pf->nodraw &= ~0x10U;
|
|
llpf->nodraw &= ~0x2U; /* the second is bad */
|
|
}
|
|
lllpf = 0;
|
|
}
|
|
}
|
|
else lllpf = 0;
|
|
}
|
|
}
|
|
if (aprsdecode_maxhop>0.0f) {
|
|
if (km>waylen) lbad = pf;
|
|
else {
|
|
waylen = waylen+km*0.5f;
|
|
/* inc max hop if there are some steps */
|
|
if (waylen>aprsdecode_maxhop) waylen = aprsdecode_maxhop;
|
|
}
|
|
}
|
|
}
|
|
if ((pf->nodraw&0xCU)==0U) {
|
|
/* use only until now ok waypoints */
|
|
llpf = lpf;
|
|
lpf = pf;
|
|
}
|
|
}
|
|
pf = pf->next;
|
|
}
|
|
if (lbad) {
|
|
/* there is a dist */
|
|
bad = 0;
|
|
lpf = 0;
|
|
pf = op->frames;
|
|
for (;;) {
|
|
/* find last long hop in track */
|
|
if (pf==0) break;
|
|
if (aprspos_posvalid(pf->vardat->pos) && (pf->nodraw&0x1EU)==0U) {
|
|
if (lpf && aprspos_distance(lpf->vardat->pos,
|
|
pf->vardat->pos)>waylen) bad = pf;
|
|
lpf = pf;
|
|
}
|
|
if (lpf==lbad) break;
|
|
pf = pf->next;
|
|
}
|
|
if (bad) {
|
|
/* hide path until last bad */
|
|
pf = op->frames;
|
|
while (pf!=bad) {
|
|
pf->nodraw |= 0x20U;
|
|
pf = pf->next;
|
|
}
|
|
}
|
|
}
|
|
} /* end joinchunk() */
|
|
|
|
|
|
extern void aprsdecode_makelogfn(char s[], uint32_t s_len)
|
|
{
|
|
aprsdecode_FILENAME fn;
|
|
useri_confstr(useri_fLOGWFN, fn, 1024ul);
|
|
filepath(fn, 1024ul);
|
|
if (fn[0UL]) aprsstr_Append(fn, 1024ul, "/", 2ul);
|
|
aprsstr_Append(fn, 1024ul, s, s_len);
|
|
aprsstr_Assign(s, s_len, fn, 1024ul);
|
|
/*WrStr("<"); WrStr(s);WrStrLn(">"); */
|
|
} /* end makelogfn() */
|
|
|
|
|
|
static void inwindow(aprsdecode_pOPHIST op, const char rawbuf[],
|
|
uint32_t rawbuf_len)
|
|
{
|
|
uint32_t matchlen;
|
|
uint32_t j;
|
|
uint32_t ii;
|
|
uint32_t i;
|
|
char in;
|
|
aprsdecode_pFRAMEHIST pf;
|
|
char wc[100];
|
|
aprsdecode_FILENAME fn;
|
|
aprsdecode_pVARDAT pv;
|
|
uint8_t doset;
|
|
struct aprspos_POSITION * anonym;
|
|
in = 0;
|
|
aprsdecode_tracenew.call[0UL] = 0;
|
|
doset = 0U;
|
|
if (op) {
|
|
setmsgheard(op->call);
|
|
pf = op->frames;
|
|
while (pf && !in) {
|
|
/* find waypoint inside screen */
|
|
pv = pf->vardat;
|
|
if (aprspos_posvalid(pv->pos)) {
|
|
{ /* with */
|
|
struct aprspos_POSITION * anonym = &pv->pos;
|
|
if (((anonym->long0>aprsdecode_tracenew.winpos0.long0 && anonym->lat<aprsdecode_tracenew.winpos0.lat)
|
|
&& anonym->long0<aprsdecode_tracenew.winpos1.long0)
|
|
&& anonym->lat>aprsdecode_tracenew.winpos1.lat) in = 1;
|
|
}
|
|
}
|
|
pf = pf->next;
|
|
}
|
|
if (in) ++aprsdecode_tracenew.winevent;
|
|
/*find user in watchlist */
|
|
/* IF posvalid(op^.lastpos) THEN */
|
|
j = 0UL;
|
|
matchlen = 0UL;
|
|
for (;;) {
|
|
useri_confstrings(useri_fWATCH, j, 1, wc, 100ul);
|
|
if (wc[0U]==0) break;
|
|
i = 0UL;
|
|
ii = 0UL;
|
|
for (;;) {
|
|
if (((i>99UL || ii>8UL) || wc[i]==0) || op->call[ii]==0) {
|
|
if ((ii>8UL || op->call[ii]==0) && (wc[i]==0 || wc[i]=='*')) {
|
|
if (i>=matchlen) {
|
|
memcpy(aprsdecode_tracenew.call,op->call,9u);
|
|
doset = useri_confflags(useri_fWATCH, j);
|
|
matchlen = i;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (wc[i]=='*') {
|
|
if (wc[i+1UL]) ++i;
|
|
}
|
|
else {
|
|
if (X2C_CAP(wc[i])!=X2C_CAP(op->call[ii])) break;
|
|
++i;
|
|
}
|
|
++ii;
|
|
}
|
|
++j;
|
|
}
|
|
/* END; */
|
|
aprsdecode_tracenew.beep = (char)(doset&1);
|
|
aprsdecode_tracenew.follow = (char)(doset/2U&1);
|
|
if ((!aprsdecode_tracenew.follow && aprsdecode_click.watchmhop)
|
|
&& X2C_STRCMP(op->call,9u,aprsdecode_click.mhop,9u)==0) {
|
|
aprsdecode_tracenew.follow = 1;
|
|
memcpy(aprsdecode_tracenew.call,op->call,9u);
|
|
}
|
|
/*WrStrLn(op^.call); WrStrLn(click.mhop);
|
|
WrInt(ORD(click.watchmhop), 1);
|
|
WrInt(ORD(tracenew.follow), 1); WrStrLn(""); */
|
|
if ((doset/4U&1)) {
|
|
/* append to watchcall file */
|
|
aprsstr_Assign(fn, 1024ul, op->call, 9ul);
|
|
alfanum(fn, 1024ul); /* remove bad chars */
|
|
/*
|
|
confstr(fLOGWFN, fn);
|
|
filepath(fn);
|
|
IF fn[0]<>0C THEN Append(fn, DIRSEP) END;
|
|
Append(fn, wc);
|
|
*/
|
|
aprsdecode_makelogfn(fn, 1024ul);
|
|
if (!wrlog(rawbuf, rawbuf_len, aprsdecode_realtime, fn, 1024ul,
|
|
0L)) poplogerr(op->call, 9ul);
|
|
}
|
|
}
|
|
} /* end inwindow() */
|
|
|
|
|
|
extern uint32_t aprsdecode_finddup(aprsdecode_pFRAMEHIST pf,
|
|
aprsdecode_pFRAMEHIST frame)
|
|
/* return delay time if dupe found */
|
|
{
|
|
struct aprspos_POSITION apos;
|
|
uint32_t ret;
|
|
uint32_t dupedelay;
|
|
uint32_t speed;
|
|
uint32_t course;
|
|
int32_t altitude;
|
|
struct aprsdecode_DAT dat;
|
|
/* search from begin to 1 frame before */
|
|
struct aprsdecode_VARDAT * anonym;
|
|
apos = frame->vardat->pos;
|
|
ret = 0UL;
|
|
if ((pf!=frame && aprspos_posvalid(apos))
|
|
&& aprsdecode_Decode(frame->vardat->raw, 500ul, &dat)>=0L) {
|
|
speed = dat.speed;
|
|
course = dat.course;
|
|
altitude = dat.altitude;
|
|
dupedelay = frame->time0-aprsdecode_lums.dupemaxtime;
|
|
while (pf->next!=frame) {
|
|
{ /* with */
|
|
struct aprsdecode_VARDAT * anonym = pf->vardat;
|
|
if (pf->time0>=dupedelay && (frame->vardat==pf->vardat || ((((apos.lat==anonym->pos.lat && apos.long0==anonym->pos.long0)
|
|
&& aprsdecode_Decode(anonym->raw, 500ul,
|
|
&dat)>=0L) && speed==dat.speed) && course==dat.course)
|
|
&& altitude==dat.altitude)) {
|
|
/* dupe pos found */
|
|
ret = frame->time0-pf->time0;
|
|
}
|
|
else if (ret>0UL) return ret;
|
|
}
|
|
/* pos changed so we have real dupe */
|
|
pf = pf->next;
|
|
}
|
|
}
|
|
return 0UL;
|
|
} /* end finddup() */
|
|
|
|
#define aprsdecode_POLY13 0x112D
|
|
|
|
#define aprsdecode_TOPBIT 12
|
|
|
|
|
|
static void initcrc12(void)
|
|
{
|
|
uint16_t remainder;
|
|
uint32_t bit;
|
|
uint32_t dividend;
|
|
for (dividend = 0UL; dividend<=255UL; dividend++) {
|
|
remainder = X2C_LSH((uint16_t)dividend,16,4);
|
|
for (bit = 8UL;; bit--) {
|
|
if ((0x1000U & remainder)) {
|
|
remainder = X2C_LSH(remainder,16,1)^0x112DU;
|
|
}
|
|
else remainder = X2C_LSH(remainder,16,1);
|
|
if (bit==0UL) break;
|
|
} /* end for */
|
|
crctable12[dividend] = remainder&0x1FFFU;
|
|
} /* end for */
|
|
} /* end initcrc12() */
|
|
|
|
typedef uint8_t * RAW;
|
|
|
|
#define aprsdecode_TOPBIT0 12
|
|
|
|
|
|
static void crca12(const RAW data, int32_t len, uint16_t * rem)
|
|
{
|
|
int32_t i;
|
|
int32_t tmp;
|
|
tmp = len-1L;
|
|
i = 0L;
|
|
if (i<=tmp) for (;; i++) {
|
|
*rem = X2C_LSH(*rem,16,8)^crctable12[(uint16_t)(X2C_LSH(*rem,16,
|
|
-5)&0xFFU)]^(uint16_t)data[i];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
} /* end crca12() */
|
|
|
|
struct _0;
|
|
|
|
|
|
struct _0 {
|
|
aprsdecode_pFRAMEHIST wayp;
|
|
uint16_t next;
|
|
};
|
|
|
|
|
|
static char lookup(uint32_t * wridx, struct _0 table[4096],
|
|
uint16_t index[8192], aprsdecode_pFRAMEHIST waypoint)
|
|
{
|
|
uint32_t sum;
|
|
uint16_t ojp;
|
|
uint16_t jp;
|
|
uint16_t ip;
|
|
struct aprsdecode_DAT dat1;
|
|
struct aprsdecode_DAT dat;
|
|
uint16_t rem;
|
|
struct aprsdecode_FRAMEHIST * anonym;
|
|
if (aprsdecode_Decode(waypoint->vardat->raw, 500ul,
|
|
&dat)>=0L && aprspos_posvalid(dat.pos)) {
|
|
rem = 0U;
|
|
crca12((RAW) &dat.speed, 2L, &rem);
|
|
crca12((RAW) &dat.course, 2L, &rem);
|
|
crca12((RAW) &dat.altitude, 2L, &rem);
|
|
crca12((RAW) &dat.pos.lat, (int32_t)sizeof(float), &rem);
|
|
crca12((RAW) &dat.pos.long0, (int32_t)sizeof(float), &rem);
|
|
sum = (uint32_t)(rem&0x1FFFU);
|
|
ip = index[sum];
|
|
/*WrInt(sum, 10);WrInt(ip, 10);WrStrLn("=ip"); */
|
|
if (ip) {
|
|
/* starts with 1, not found */
|
|
--ip;
|
|
jp = ip;
|
|
for (;;) {
|
|
{ /* with */
|
|
struct aprsdecode_FRAMEHIST * anonym = table[jp].wayp;
|
|
if (anonym->vardat==waypoint->vardat || ((((anonym->vardat->pos.lat==dat.pos.lat && anonym->vardat->pos.long0==dat.pos.long0)
|
|
&& aprsdecode_Decode(anonym->vardat->raw, 500ul,
|
|
&dat1)>=0L) && dat1.speed==dat.speed)
|
|
&& dat1.course==dat.course) && dat1.altitude==dat.altitude) {
|
|
if (anonym->time0+aprsdecode_lums.dupemaxtime>waypoint->time0)
|
|
return 1;
|
|
else break;
|
|
}
|
|
}
|
|
ojp = jp;
|
|
jp = table[jp].next;
|
|
if (jp>4095U || ojp<=jp==((uint32_t)ojp<*wridx==(uint32_t)
|
|
jp<*wridx)) {
|
|
/*WrInt(ORD(jp>HIGH(table)), 2); WrInt(ojp, 6); WrInt(jp, 6);
|
|
WrInt(wridx, 6); WrStr("o"); */
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/*INC(collis); */
|
|
ip = 65535U;
|
|
}
|
|
index[sum] = (uint16_t)(*wridx+1UL);
|
|
table[*wridx].wayp = waypoint;
|
|
table[*wridx].next = ip;
|
|
*wridx = *wridx+1UL&4095UL;
|
|
}
|
|
return 0;
|
|
} /* end lookup() */
|
|
|
|
|
|
extern void aprsdecode_Checktrack(aprsdecode_pOPHIST op,
|
|
aprsdecode_pFRAMEHIST lastf)
|
|
{
|
|
aprsdecode_pFRAMEHIST f;
|
|
aprsdecode_pFRAMEHIST frame;
|
|
struct aprspos_POSITION last2;
|
|
struct aprspos_POSITION last;
|
|
struct aprspos_POSITION apos;
|
|
uint32_t starttime;
|
|
char cmp;
|
|
uint32_t wridx;
|
|
uint16_t index[8192];
|
|
struct _0 table[4096];
|
|
struct aprsdecode_OPHIST * anonym;
|
|
if (lastf) frame = lastf->next;
|
|
else {
|
|
op->margin0.long0 = 3.1415926535f;
|
|
op->margin0.lat = (-1.57079632675f);
|
|
op->margin1.long0 = (-3.1415926535f);
|
|
op->margin1.lat = 1.57079632675f;
|
|
frame = op->frames;
|
|
while (frame) {
|
|
frame->vardat->refcnt = 0UL;
|
|
frame = frame->next;
|
|
}
|
|
frame = op->frames;
|
|
while (frame) {
|
|
++frame->vardat->refcnt;
|
|
frame = frame->next;
|
|
}
|
|
frame = op->frames;
|
|
}
|
|
if (frame==0) return;
|
|
starttime = frame->time0; /* from this waypoint dupes will be set */
|
|
f = op->frames;
|
|
while (f && f->time0+aprsdecode_lums.dupemaxtime<starttime) f = f->next;
|
|
memset((char *)index,(char)0,16384UL);
|
|
wridx = 0UL;
|
|
lastf = 0;
|
|
cmp = 0;
|
|
aprsdecode_posinval(&last);
|
|
aprsdecode_posinval(&last2);
|
|
while (f) {
|
|
if (f==frame) cmp = 1;
|
|
apos = f->vardat->pos;
|
|
if (aprspos_posvalid(apos)) {
|
|
if (cmp) {
|
|
{ /* with */
|
|
struct aprsdecode_OPHIST * anonym = op;
|
|
if (apos.long0<anonym->margin0.long0) {
|
|
anonym->margin0.long0 = apos.long0;
|
|
}
|
|
if (apos.long0>anonym->margin1.long0) {
|
|
anonym->margin1.long0 = apos.long0;
|
|
}
|
|
if (apos.lat>anonym->margin0.lat) {
|
|
anonym->margin0.lat = apos.lat;
|
|
}
|
|
if (apos.lat<anonym->margin1.lat) {
|
|
anonym->margin1.lat = apos.lat;
|
|
}
|
|
}
|
|
f->nodraw &= ~0x8U;
|
|
}
|
|
if (lookup(&wridx, table, index, f) && cmp) {
|
|
if (apos.lat!=last.lat || apos.long0!=last.long0) {
|
|
if (apos.lat!=last2.lat || apos.long0!=last2.long0) {
|
|
f->nodraw |= 0x8U;
|
|
}
|
|
}
|
|
}
|
|
if (maxspeed>0.0f) timespeed(lastf, apos, f->time0, &f->nodraw);
|
|
if (!(f->nodraw&~0x14U) || !aprspos_posvalid(op->lastpos)) {
|
|
op->lastpos = apos;
|
|
}
|
|
last2 = last;
|
|
last = apos;
|
|
}
|
|
else f->nodraw |= 0x40U;
|
|
lastf = f;
|
|
f = f->next;
|
|
}
|
|
joinchunk(op);
|
|
} /* end Checktrack() */
|
|
|
|
|
|
static char strcmp0(const char a[], uint32_t a_len,
|
|
const char b[], uint32_t b_len)
|
|
/* faster but needs 0 termination */
|
|
{
|
|
uint32_t i;
|
|
i = 0UL;
|
|
for (;;) {
|
|
if (a[i]!=b[i]) return 0;
|
|
if (a[i]==0) return 1;
|
|
++i;
|
|
}
|
|
return 0;
|
|
} /* end strcmp() */
|
|
|
|
|
|
static char callfilt(uint8_t v, const char str[],
|
|
uint32_t str_len, char fullmatch)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char s[31];
|
|
if (str[0UL]==0) return 0;
|
|
i = 0UL;
|
|
for (;;) {
|
|
useri_confstrings(v, i, 0, s, 31ul);
|
|
if (s[0U]==0) return 0;
|
|
s[30U] = 0;
|
|
/* IF fullmatch THEN IF StrCmp(s, str) THEN RETURN TRUE END; */
|
|
if (fullmatch) {
|
|
j = 0UL;
|
|
for (;;) {
|
|
if (s[j]=='*') {
|
|
if (s[j+1UL]==0 || str[j]==0) return 1;
|
|
}
|
|
else {
|
|
if (s[j]!=str[j]) break;
|
|
if (str[j]==0) return 1;
|
|
}
|
|
++j;
|
|
if (j>str_len-1) return 1;
|
|
}
|
|
}
|
|
else if (aprsstr_InStr(str, str_len, s, 31ul)>=0L) return 1;
|
|
/* comment filter */
|
|
++i;
|
|
}
|
|
return 0;
|
|
} /* end callfilt() */
|
|
|
|
|
|
static void inserthrt(const struct aprsdecode_DAT dat,
|
|
aprsdecode_pOPHIST * op, uint8_t errs)
|
|
{
|
|
aprsdecode_pFRAMEHIST lastf;
|
|
aprsdecode_pFRAMEHIST f;
|
|
aprsdecode_pVARDAT v;
|
|
uint32_t len;
|
|
uint32_t ih;
|
|
uint32_t i;
|
|
uint32_t stime;
|
|
char s[51];
|
|
char rb[51];
|
|
struct aprsdecode_VARDAT * anonym;
|
|
uint32_t tmp;
|
|
f = (*op)->frames;
|
|
lastf = 0;
|
|
tmp = dat.hrtlen-1UL;
|
|
ih = 0UL;
|
|
if (ih<=tmp) for (;; ih++) {
|
|
if (dat.hrtposes[ih].notinterpolated) {
|
|
/* interpolating does vector drawer */
|
|
stime = dat.hrtposes[ih].dtime;
|
|
while (f && f->time0<stime) {
|
|
lastf = f;
|
|
f = f->next;
|
|
}
|
|
if (f==0 || f->time0!=stime) {
|
|
/* not a redundant same time frame */
|
|
osic_alloc((char * *) &f,
|
|
sizeof(struct aprsdecode_FRAMEHIST));
|
|
useri_debugmem.req = sizeof(struct aprsdecode_FRAMEHIST);
|
|
useri_debugmem.mon += useri_debugmem.req;
|
|
if (f==0) return;
|
|
memset((char *)f,(char)0,
|
|
sizeof(struct aprsdecode_FRAMEHIST));
|
|
if ((float)fabs(dat.hrtposes[ih].dalt)<2.147483646E+9f) {
|
|
aprsstr_IntToStr((int32_t)X2C_TRUNCI(dat.hrtposes[ih].dalt,
|
|
X2C_min_longint,X2C_max_longint), 0UL, s, 51ul);
|
|
strncpy(rb,">:$HR[a",51u);
|
|
aprsstr_Append(rb, 51ul, s, 51ul);
|
|
aprsstr_Append(rb, 51ul, "]", 2ul);
|
|
}
|
|
else rb[0U] = 0;
|
|
len = (sizeof(struct aprsdecode_VARDAT)-499UL)+aprsstr_Length(rb,
|
|
51ul);
|
|
osic_alloc((char * *) &v, len);
|
|
useri_debugmem.req = len;
|
|
useri_debugmem.mon += len;
|
|
if (v==0) return;
|
|
memset((char *)v,(char)0,len);
|
|
{ /* with */
|
|
struct aprsdecode_VARDAT * anonym = v;
|
|
anonym->pos.long0 = dat.hrtposes[ih].dlong;
|
|
anonym->pos.lat = dat.hrtposes[ih].dlat;
|
|
i = 0UL;
|
|
do {
|
|
anonym->raw[i] = rb[i];
|
|
++i;
|
|
} while (rb[i]);
|
|
}
|
|
v->lastref = f;
|
|
f->vardat = v;
|
|
f->time0 = stime;
|
|
f->nodraw = errs;
|
|
if (lastf==0) {
|
|
f->next = (*op)->frames;
|
|
(*op)->frames = f; /* new track */
|
|
}
|
|
else {
|
|
f->next = lastf->next; /* not nil if insert older frame */
|
|
lastf->next = f; /* append waypoint */
|
|
}
|
|
}
|
|
}
|
|
if (ih==tmp) break;
|
|
} /* end for */
|
|
} /* end inserthrt() */
|
|
|
|
|
|
static void settempspeed(aprsdecode_pOPHIST op,
|
|
const struct aprsdecode_DAT dat)
|
|
{
|
|
float rv;
|
|
op->drawhints = op->drawhints&~0x3U;
|
|
if (dat.objectfrom[0UL]) op->drawhints |= 0x2U;
|
|
/* EXCL(op^.drawhints, MIRRORSYM); */
|
|
if (dat.sym=='_') {
|
|
op->lastinftyp = 0U;
|
|
op->lasttempalt = -32768;
|
|
rv = aprstext_FtoC(dat.wx.temp);
|
|
if (rv>=(-99.0f) && rv<=99.0f) {
|
|
op->lasttempalt = (short)X2C_TRUNCI(rv,-32768,32767);
|
|
op->temptime = aprsdecode_systime;
|
|
op->lastinftyp = 100U;
|
|
}
|
|
if (dat.course>=1UL && dat.course<=360UL) {
|
|
op->lastinftyp = (uint8_t)(110UL+(dat.course%360UL)/4UL);
|
|
op->temptime = aprsdecode_systime;
|
|
}
|
|
else op->lastinftyp = 100U;
|
|
if (dat.speed<500UL) {
|
|
op->lastkmh = (short)X2C_TRUNCI((float)dat.speed*1.609f+0.5f,
|
|
-32768,32767);
|
|
if (op->lastinftyp<100U) op->lastinftyp = 100U;
|
|
op->temptime = aprsdecode_systime;
|
|
}
|
|
else op->lastkmh = 0;
|
|
}
|
|
else if (dat.speed<30000UL) {
|
|
op->lastkmh = (short)X2C_TRUNCI((float)dat.speed*1.852f+0.5f,
|
|
-32768,32767);
|
|
if (dat.speed>0UL && dat.course>180UL) op->drawhints |= 0x1U;
|
|
if (dat.course<=360UL) {
|
|
op->lastinftyp = (uint8_t)(10UL+dat.course/4UL);
|
|
}
|
|
else op->lastinftyp = 1U;
|
|
}
|
|
else if (op->lastinftyp<100U) op->lastinftyp = 0U;
|
|
if (op->lastinftyp<100U) {
|
|
if (dat.altitude>-10000L && dat.altitude<55535L) {
|
|
op->lasttempalt = (short)(dat.altitude+(-22768L));
|
|
}
|
|
else op->lasttempalt = -32768;
|
|
}
|
|
} /* end settempspeed() */
|
|
|
|
|
|
static char widefilt(void)
|
|
{
|
|
char s[101];
|
|
useri_confstr(useri_fFINGERPRINT, s, 101ul);
|
|
return aprsstr_InStr(s, 101ul, "0:2", 4ul)>=0L;
|
|
} /* end widefilt() */
|
|
|
|
#define aprsdecode_SAMETIME 27
|
|
/* max time diff for merged in frames */
|
|
|
|
static CHSET _cnst0 = {0x30000000UL,0x280086BAUL,0x80000001UL,0x00000001UL};
|
|
|
|
extern int32_t aprsdecode_Stoframe(aprsdecode_pOPHIST * optab,
|
|
char rawbuf[], uint32_t rawbuf_len, uint32_t stime,
|
|
char logmode, uint32_t * oldtime,
|
|
struct aprsdecode_DAT dat)
|
|
{
|
|
aprsdecode_pOPHIST opo;
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST lastf;
|
|
aprsdecode_pFRAMEHIST frame;
|
|
aprsdecode_pVARDAT same;
|
|
aprsdecode_MONCALL igate;
|
|
uint32_t cnt;
|
|
uint32_t len;
|
|
uint32_t i;
|
|
uint16_t ch0;
|
|
uint16_t hash;
|
|
struct aprsdecode_VARDAT * anonym;
|
|
int32_t aprsdecode_Stoframe_ret;
|
|
X2C_PCOPY((void **)&rawbuf,rawbuf_len);
|
|
*oldtime = 1UL; /* say not "new user" if filtered out */
|
|
i = 0UL;
|
|
hash = 0U;
|
|
do {
|
|
ch0 = (uint16_t)(uint8_t)rawbuf[i];
|
|
hash += ch0;
|
|
++i;
|
|
} while (ch0);
|
|
do {
|
|
--i;
|
|
} while (!(i==0UL || (rawbuf[i]!='\015' && rawbuf[i]!='\012') && rawbuf[i]));
|
|
rawbuf[i+1UL] = 0; /* remove trailing CR LF */
|
|
/*FOR len:=0 TO i DO WrInt(ORD(rawbuf[len]), 4) END; WrLn; */
|
|
/* IF NOT logmode THEN */
|
|
if (dat.igatep>0UL && dat.igatep<=9UL) {
|
|
memcpy(igate,dat.viacalls[dat.igatep],9u);
|
|
}
|
|
else igate[0UL] = 0;
|
|
if (((((callfilt(useri_fOPFILT, dat.symcall, 9ul,
|
|
1) || callfilt(useri_fIGATEFILT, igate, 9ul,
|
|
1)) || callfilt(useri_fOBJSRCFILT, dat.objectfrom, 9ul,
|
|
1)) || callfilt(useri_fDESTFILT, dat.dstcall, 9ul,
|
|
0)) || callfilt(useri_fSTRFILT, dat.comment0, 256ul,
|
|
0)) || callfilt(useri_fRAWFILT, rawbuf, rawbuf_len, 0)) {
|
|
aprsdecode_Stoframe_ret = -1L;
|
|
goto label;
|
|
}
|
|
if (useri_configon(useri_fMUSTBECALL)) {
|
|
if (dat.type==aprsdecode_OBJ || dat.type==aprsdecode_ITEM) {
|
|
if (!aprstext_isacall(dat.objectfrom, 9ul)) {
|
|
aprsdecode_Stoframe_ret = -1L;
|
|
goto label;
|
|
}
|
|
}
|
|
else if (!aprstext_isacall(dat.symcall, 9ul)) {
|
|
aprsdecode_Stoframe_ret = -1L;
|
|
goto label;
|
|
}
|
|
}
|
|
/* END; */
|
|
*oldtime = 0UL;
|
|
cnt = 0UL; /* check for 2 WIDE chunk */
|
|
if (widefilt()) {
|
|
i = 0UL;
|
|
while (((cnt<2UL && i<=9UL) && dat.viacalls[i][0UL])
|
|
&& (dat.igatep==0UL || i<dat.igatep)) {
|
|
if (aprsstr_InStr(dat.viacalls[i], 9ul, "WIDE", 5ul)==0L) ++cnt;
|
|
++i;
|
|
}
|
|
}
|
|
opo = 0;
|
|
op = *optab;
|
|
while (op && X2C_STRCMP(dat.symcall,9u,op->call,9u)) {
|
|
opo = op;
|
|
op = op->next;
|
|
}
|
|
if (op==0) {
|
|
osic_alloc((char * *) &op, sizeof(struct aprsdecode_OPHIST));
|
|
useri_debugmem.req = sizeof(struct aprsdecode_OPHIST);
|
|
useri_debugmem.mon += useri_debugmem.req;
|
|
if (op==0) {
|
|
aprsdecode_Stoframe_ret = -2L;
|
|
goto label;
|
|
}
|
|
memset((char *)op,(char)0,sizeof(struct aprsdecode_OPHIST));
|
|
memcpy(op->call,dat.symcall,9u);
|
|
if (logmode || opo==0) {
|
|
/* store it at begin of list for quick find */
|
|
op->next = *optab;
|
|
*optab = op;
|
|
}
|
|
else opo->next = op;
|
|
}
|
|
else if (logmode && opo) {
|
|
/* move it to begin of list */
|
|
opo->next = op->next;
|
|
op->next = *optab;
|
|
*optab = op;
|
|
}
|
|
else *oldtime = op->lasttime;
|
|
if (dat.hrttime>0UL) stime = dat.hrttime;
|
|
if (op->lasttime<=stime) {
|
|
/* new waypoint */
|
|
settempspeed(op, dat);
|
|
op->lasttime = stime;
|
|
}
|
|
frame = op->frames;
|
|
lastf = 0;
|
|
same = 0;
|
|
if (logmode) {
|
|
/* refcnt used as raw string hash */
|
|
while (frame && (frame->vardat->refcnt!=(uint32_t)
|
|
hash || !strcmp0(frame->vardat->raw, 500ul, rawbuf,
|
|
rawbuf_len))) {
|
|
lastf = frame;
|
|
frame = frame->next;
|
|
}
|
|
}
|
|
else {
|
|
/* online data find without hash */
|
|
while (frame && !strcmp0(frame->vardat->raw, 500ul, rawbuf,
|
|
rawbuf_len)) {
|
|
lastf = frame;
|
|
frame = frame->next;
|
|
}
|
|
}
|
|
if (frame) {
|
|
/* found same frame */
|
|
same = frame->vardat;
|
|
lastf = same->lastref;
|
|
while (lastf->next) lastf = lastf->next;
|
|
}
|
|
if (lastf && lastf->time0>stime) {
|
|
/* older frame to insert */
|
|
lastf = 0;
|
|
frame = op->frames;
|
|
while (frame && frame->time0<stime) {
|
|
lastf = frame;
|
|
frame = frame->next;
|
|
}
|
|
if (frame && frame->time0-stime<27UL) {
|
|
aprsdecode_Stoframe_ret = -2L;
|
|
goto label;
|
|
}
|
|
}
|
|
/* not insert same frame */
|
|
osic_alloc((char * *) &frame, sizeof(struct aprsdecode_FRAMEHIST));
|
|
useri_debugmem.req = sizeof(struct aprsdecode_FRAMEHIST);
|
|
useri_debugmem.mon += useri_debugmem.req;
|
|
if (frame==0) {
|
|
aprsdecode_Stoframe_ret = -2L;
|
|
goto label;
|
|
}
|
|
memset((char *)frame,(char)0,sizeof(struct aprsdecode_FRAMEHIST));
|
|
if (same==0) {
|
|
/* found new data */
|
|
len = (sizeof(struct aprsdecode_VARDAT)-499UL)+aprsstr_Length(rawbuf,
|
|
rawbuf_len);
|
|
osic_alloc((char * *) &same, len);
|
|
useri_debugmem.req = len;
|
|
useri_debugmem.mon += len;
|
|
if (same==0) {
|
|
aprsdecode_Stoframe_ret = -2L;
|
|
goto label;
|
|
}
|
|
memset((char *)same,(char)0,len);
|
|
{ /* with */
|
|
struct aprsdecode_VARDAT * anonym = same;
|
|
anonym->pos = dat.pos;
|
|
/* altitude:=dat.altitude; */
|
|
if (dat.hbitp==0UL && dat.igaterawp<=255UL) {
|
|
/* direct to igate */
|
|
anonym->igatepos = (uint8_t)dat.igaterawp;
|
|
anonym->igatelen = (uint8_t)dat.igatelen;
|
|
}
|
|
i = 0UL;
|
|
do {
|
|
anonym->raw[i] = rawbuf[i];
|
|
++i;
|
|
} while (rawbuf[i]);
|
|
if (logmode) anonym->refcnt = (uint32_t)hash;
|
|
}
|
|
}
|
|
else if (!logmode) ++same->refcnt;
|
|
if (same->lastref==0 || same->lastref->time0<=stime) {
|
|
same->lastref = frame;
|
|
}
|
|
frame->vardat = same;
|
|
frame->time0 = stime;
|
|
if (X2C_INL((int32_t)(uint8_t)dat.typc,128,_cnst0)) {
|
|
if (((X2C_INL((uint8_t)dat.symt,256,
|
|
_cnst) && (uint8_t)dat.sym>' ') && (uint8_t)
|
|
dat.sym<'\177') && op->sym.tab!='\001') {
|
|
op->sym.tab = dat.symt;
|
|
op->sym.pic = dat.sym;
|
|
}
|
|
else frame->nodraw |= 0x4U;
|
|
if (cnt>=2UL || dat.objkill=='1') {
|
|
op->sym.tab = '\001';
|
|
op->sym.pic = 0;
|
|
}
|
|
}
|
|
op->areasymb = dat.areasymb;
|
|
op->poligon = dat.multiline.size>2UL;
|
|
op->lastrxport = dat.lastrxport;
|
|
if (lastf==0) {
|
|
frame->next = op->frames;
|
|
op->frames = frame; /* new track */
|
|
}
|
|
else {
|
|
frame->next = lastf->next; /* not nil if insert older frame */
|
|
lastf->next = frame; /* append waypoint */
|
|
}
|
|
if (dat.hrtlen>0UL) {
|
|
inserthrt(dat, &op, frame->nodraw);
|
|
}
|
|
if (!logmode) {
|
|
/* read log check whole track at end */
|
|
aprsdecode_Checktrack(op, lastf);
|
|
inwindow(op, rawbuf, rawbuf_len);
|
|
}
|
|
if (!(frame->nodraw&~0x1U)) aprsdecode_Stoframe_ret = 0L;
|
|
else aprsdecode_Stoframe_ret = -1L;
|
|
label:;
|
|
X2C_PFREE(rawbuf);
|
|
return aprsdecode_Stoframe_ret;
|
|
} /* end Stoframe() */
|
|
|
|
|
|
static char locked(aprsdecode_pOPHIST op)
|
|
/* prevent entries in click table from purge */
|
|
{
|
|
uint32_t i;
|
|
i = 0UL;
|
|
while (i<aprsdecode_click.entries) {
|
|
if (aprsdecode_click.table[i].opf==op) return 1;
|
|
++i;
|
|
}
|
|
return 0;
|
|
} /* end locked() */
|
|
|
|
|
|
static void freevardat(aprsdecode_pVARDAT v)
|
|
{
|
|
uint32_t alen;
|
|
alen = (sizeof(struct aprsdecode_VARDAT)-499UL)+aprsstr_Length(v->raw,
|
|
500ul);
|
|
osic_free((char * *) &v, alen);
|
|
useri_debugmem.mon -= alen;
|
|
} /* end freevardat() */
|
|
|
|
#define aprsdecode_CHKINTERVALL 120
|
|
/* seconds to next check track */
|
|
|
|
|
|
extern void aprsdecode_purge(aprsdecode_pOPHIST * ops, uint32_t oldt,
|
|
uint32_t oldobj)
|
|
{
|
|
aprsdecode_pOPHIST opx;
|
|
aprsdecode_pOPHIST lastop;
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST frame;
|
|
aprsdecode_pVARDAT v;
|
|
uint32_t old;
|
|
char chk;
|
|
/*chkptr(ops); */
|
|
/*
|
|
WrInt(ORD(lums.logmode), 1);
|
|
IF ops=ophist THEN WrStrLn("purge oph")
|
|
ELSIF ops=ophist2 THEN WrStrLn("purge oph2")
|
|
ELSE WrStrLn("purge error") END;
|
|
*/
|
|
op = *ops;
|
|
lastop = 0;
|
|
while (op) {
|
|
/*WrStr("op:"); WrStr(op^.call); WrStr(" "); */
|
|
if (op->sym.tab=='\001') old = X2C_max_longcard;
|
|
else if ((0x2U & op->drawhints) && op->lastinftyp<100U) {
|
|
old = oldobj; /* object but no wx obj for wx graphs */
|
|
}
|
|
else old = oldt;
|
|
chk = 0;
|
|
for (;;) {
|
|
frame = op->frames;
|
|
if (frame==0) break;
|
|
/*WrCard(systime-frame^.time, 6);
|
|
IF frame^.next<>NIL THEN WrStr("+") END; */
|
|
if (frame->time0>=old || locked(op)) break;
|
|
if (frame->next && frame->time0/120UL!=frame->next->time0/120UL) {
|
|
chk = 1;
|
|
}
|
|
v = frame->vardat;
|
|
if (v->lastref==frame) freevardat(v);
|
|
else --v->refcnt;
|
|
op->frames = frame->next;
|
|
/*WrStr("(purge)"); */
|
|
useri_debugmem.mon -= sizeof(struct aprsdecode_FRAMEHIST);
|
|
osic_free((char * *) &frame,
|
|
sizeof(struct aprsdecode_FRAMEHIST));
|
|
}
|
|
if (op->frames==0 && !locked(op)) {
|
|
/* empty op */
|
|
opx = op;
|
|
op = op->next;
|
|
if (lastop==0) *ops = op;
|
|
else lastop->next = op;
|
|
/*WrStr(opx^.call); WrStrLn("(purgop) "); */
|
|
useri_debugmem.mon -= sizeof(struct aprsdecode_OPHIST);
|
|
osic_free((char * *) &opx, sizeof(struct aprsdecode_OPHIST));
|
|
}
|
|
else {
|
|
if (chk) {
|
|
aprsdecode_Checktrack(op, 0); /*WrStr(op^.call); WrStr(" ")*/
|
|
}
|
|
lastop = op;
|
|
op = op->next;
|
|
}
|
|
}
|
|
/*WrLn; */
|
|
/*WrStrLn(" --purge"); */
|
|
} /* end purge() */
|
|
|
|
|
|
extern void aprsdecode_delwaypoint(aprsdecode_pOPHIST op,
|
|
aprsdecode_pFRAMEHIST * frame)
|
|
{
|
|
aprsdecode_pFRAMEHIST lastf;
|
|
aprsdecode_pFRAMEHIST lf;
|
|
aprsdecode_pFRAMEHIST f;
|
|
int32_t mi;
|
|
int32_t di;
|
|
int32_t i;
|
|
struct aprsdecode_DAT dat;
|
|
if (op==0 || *frame==0) return;
|
|
i = 0L;
|
|
di = 0L;
|
|
mi = 0L;
|
|
lf = 0;
|
|
f = op->frames;
|
|
while (f) {
|
|
if (f->next==*frame) {
|
|
lf = f; /* next frame is to delete */
|
|
di = mi;
|
|
}
|
|
if (f->vardat==(*frame)->vardat) ++i;
|
|
f->vardat->refcnt = 0UL;
|
|
++mi;
|
|
f = f->next;
|
|
}
|
|
if (i==1L) freevardat((*frame)->vardat);
|
|
if (lf==0) op->frames = (*frame)->next;
|
|
else lf->next = (*frame)->next;
|
|
useri_debugmem.mon -= sizeof(struct aprsdecode_FRAMEHIST);
|
|
osic_free((char * *)frame, sizeof(struct aprsdecode_FRAMEHIST));
|
|
f = op->frames;
|
|
while (f) {
|
|
if (f->vardat->refcnt<65535UL) ++f->vardat->refcnt;
|
|
f->vardat->lastref = f;
|
|
f->nodraw = 0U; /* mark errors new later */
|
|
f = f->next;
|
|
}
|
|
aprsdecode_Checktrack(op, 0);
|
|
i = 0L; /* set new marker to the nearest from deleted with error */
|
|
mi = X2C_max_longint;
|
|
*frame = 0;
|
|
lf = 0;
|
|
lastf = 0;
|
|
f = op->frames;
|
|
while (f) {
|
|
if ((!aprsdecode_lums.errorstep || (f->nodraw&~0x40U)!=0U)
|
|
&& labs(i-di)<mi) {
|
|
mi = labs(i-di);
|
|
*frame = f;
|
|
}
|
|
if (i==di) lf = f;
|
|
++i;
|
|
lastf = f;
|
|
f = f->next;
|
|
}
|
|
if (*frame==0) *frame = lf;
|
|
if (lastf) {
|
|
if (aprsdecode_Decode(lastf->vardat->raw, 500ul, &dat)>=0L) {
|
|
settempspeed(op, dat);
|
|
}
|
|
op->lasttime = lastf->time0;
|
|
/* deleted last frame so correct op time */
|
|
}
|
|
} /* end delwaypoint() */
|
|
|
|
|
|
static char cmpfrom(const char a[], uint32_t a_len,
|
|
uint32_t from, const char b[], uint32_t b_len)
|
|
{
|
|
uint32_t i;
|
|
i = 0UL;
|
|
while (from<=a_len-1 && b[i]) {
|
|
if (a[from]!=b[i]) return 0;
|
|
++i;
|
|
++from;
|
|
}
|
|
return 1;
|
|
} /* end cmpfrom() */
|
|
|
|
/*
|
|
PROCEDURE AppQ(VAR h:ARRAY OF CHAR; q-:ARRAY OF CHAR; appcall:BOOLEAN);
|
|
BEGIN
|
|
Append(h, ">"+TOCALL+",");
|
|
Append(h, q);
|
|
IF appcall THEN Append(h, servercall) END;
|
|
Append(h, ":");
|
|
END AppQ;
|
|
*/
|
|
|
|
static char callchk(uint32_t * qpos, char * tablechk,
|
|
char buf[], uint32_t buf_len, uint32_t * p,
|
|
uint32_t tablen, uint32_t * pssid, char withstar,
|
|
char iscall0)
|
|
{
|
|
uint32_t lit;
|
|
uint32_t num1;
|
|
uint32_t u;
|
|
uint32_t j;
|
|
uint32_t i;
|
|
char c;
|
|
*pssid = 0UL;
|
|
u = 0UL;
|
|
for (;;) {
|
|
if (u>=tablen) break;
|
|
j = 0UL;
|
|
i = *p;
|
|
while (ungate[u][j]==buf[i]) {
|
|
++i;
|
|
++j;
|
|
if (ungate[u][j]==0) {
|
|
*tablechk = 1;
|
|
goto loop_exit;
|
|
}
|
|
}
|
|
++u;
|
|
}
|
|
loop_exit:;
|
|
if (iscall0) {
|
|
/* we want a callsign */
|
|
num1 = 0UL;
|
|
lit = 0UL;
|
|
for (;;) {
|
|
c = buf[*p];
|
|
if ((uint8_t)c>='0' && (uint8_t)c<='9') ++num1;
|
|
else if ((uint8_t)c>='A' && (uint8_t)c<='Z') ++lit;
|
|
else break;
|
|
++*p;
|
|
}
|
|
if ((lit<2UL || num1==0UL) || num1>2UL) return 0;
|
|
*pssid = *p;
|
|
if (buf[*p]=='-') {
|
|
++*p;
|
|
if (buf[*p]=='1') {
|
|
++*p;
|
|
if ((uint8_t)buf[*p]>='0' && (uint8_t)buf[*p]<='5') ++*p;
|
|
}
|
|
else {
|
|
if ((uint8_t)buf[*p]<'1' || (uint8_t)buf[*p]>'9') return 0;
|
|
++*p;
|
|
}
|
|
}
|
|
}
|
|
else if ((buf[*p]=='q' && buf[*p+1UL]=='A') && (uint8_t)
|
|
buf[*p+2UL]>='A') {
|
|
/* qAx */
|
|
*qpos = *p+2UL;
|
|
*p += 3UL;
|
|
}
|
|
else {
|
|
/* we skip any text */
|
|
for (;;) {
|
|
c = buf[*p];
|
|
if (c=='-') *pssid = *p;
|
|
if (((((uint8_t)c<=' ' || c=='>') || c=='*') || c==',') || c==':')
|
|
break;
|
|
++*p;
|
|
}
|
|
}
|
|
if (*pssid==0UL) *pssid = *p;
|
|
if (buf[*p]=='*' && withstar) ++*p;
|
|
return 1;
|
|
} /* end callchk() */
|
|
|
|
|
|
static void Iconstruct(char qtext[32], uint32_t * pins,
|
|
char logcall[], uint32_t logcall_len, char buf[],
|
|
uint32_t buf_len, uint32_t * p)
|
|
{
|
|
uint32_t k;
|
|
uint32_t j;
|
|
uint32_t i;
|
|
if (*p<=4UL || buf[*p-2UL]!='I') return;
|
|
/* ,CALL,I: */
|
|
i = *p-4UL;
|
|
while (buf[i]!=',') {
|
|
/* hop back call */
|
|
if (i==0UL) return;
|
|
--i;
|
|
}
|
|
k = i; /* "," before call */
|
|
++i;
|
|
j = 0UL;
|
|
while (j<=logcall_len-1 && logcall[j]) {
|
|
if (logcall[j]!=buf[i]) return;
|
|
++i;
|
|
++j;
|
|
}
|
|
/* logcall = call,I */
|
|
*pins = k;
|
|
i = *p-1UL;
|
|
*p = k+1UL; /* payload */
|
|
for (;;) {
|
|
buf[k] = buf[i];
|
|
if (i>=buf_len-1 || buf[i]==0) break;
|
|
++k;
|
|
++i;
|
|
}
|
|
/* delete ,call,I */
|
|
strncpy(qtext,",qAR,",32u); /* insert ,qAR,call */
|
|
aprsstr_Append(qtext, 32ul, logcall, logcall_len);
|
|
/*
|
|
OE0AAA-9>T8SV40,WIDE1-1,DB0WGS,I:test
|
|
OE0AAA-9>T8SV40,WIDE1-1:test
|
|
OE0AAA-9>T8SV40,WIDE1-1,qAR,DB0WGS:test
|
|
*/
|
|
} /* end Iconstruct() */
|
|
|
|
|
|
static int32_t AprsIs(char buf[], uint32_t buf_len,
|
|
uint32_t tablen, const char logcall[],
|
|
uint32_t logcall_len, uint32_t udpchan,
|
|
char valid, char chkrfcall,
|
|
char * tablechk)
|
|
{
|
|
uint32_t qpos;
|
|
uint32_t ha;
|
|
uint32_t ilen;
|
|
uint32_t psum1;
|
|
uint32_t psum0;
|
|
uint32_t pssid;
|
|
uint32_t pins;
|
|
uint32_t len;
|
|
uint32_t p;
|
|
uint32_t i;
|
|
uint8_t hashh;
|
|
uint8_t hashl;
|
|
char qtext[32];
|
|
uint32_t tmp;
|
|
hashl = 0U;
|
|
hashh = 0U;
|
|
p = 0UL;
|
|
pins = 0UL;
|
|
pssid = 0UL; /* for savety */
|
|
len = 0UL;
|
|
while ((len<buf_len-1 && buf[len]) && buf[len]!='\015') ++len;
|
|
if (len==0UL || len+35UL>buf_len-1) return -2L;
|
|
qpos = 0UL;
|
|
*tablechk = 0;
|
|
for (;;) {
|
|
psum0 = p;
|
|
if (!callchk(&qpos, tablechk, buf, buf_len, &p, tablen, &pssid, 0,
|
|
udpchan && chkrfcall)) return -3L;
|
|
if (buf[p]!='>') return -1L;
|
|
++p;
|
|
if (!callchk(&qpos, tablechk, buf, buf_len, &p, tablen, &pssid, 0, 0)) {
|
|
return -3L;
|
|
}
|
|
psum1 = pssid;
|
|
while (buf[p]==',') {
|
|
++p;
|
|
if (!callchk(&qpos, tablechk, buf, buf_len, &p, tablen, &pssid, 1,
|
|
0)) return -3L;
|
|
}
|
|
if (buf[p]!=':') return -1L;
|
|
if (pins==0UL) pins = p;
|
|
++p;
|
|
if (buf[p]!='}') break;
|
|
++p;
|
|
}
|
|
if (p>=len) return -2L;
|
|
qtext[0U] = 0;
|
|
if (qpos>0UL) {
|
|
/* qA */
|
|
if (X2C_CAP(buf[qpos])=='Z') return -3L;
|
|
if (X2C_CAP(buf[qpos])=='I') {
|
|
aprsstr_Append(qtext, 32ul, ",", 2ul); /* qAI */
|
|
useri_confappend(useri_fMYCALL, qtext, 32ul);
|
|
}
|
|
}
|
|
else if (udpchan) {
|
|
aprsstr_Append(qtext, 32ul, ",qAU,", 6ul);
|
|
useri_confappend(useri_fMYCALL, qtext, 32ul);
|
|
}
|
|
else if (logcall[0UL]) {
|
|
if (cmpfrom(buf, buf_len, 0UL, logcall, logcall_len)) {
|
|
strncpy(qtext,",qAC,",32u);
|
|
}
|
|
else strncpy(qtext,",qAS,",32u);
|
|
useri_confappend(useri_fMYCALL, qtext, 32ul);
|
|
Iconstruct(qtext, &pins, logcall, logcall_len, buf, buf_len, &p);
|
|
}
|
|
if (buf[p]=='?') return -4L;
|
|
tmp = psum1-1UL;
|
|
i = psum0;
|
|
if (i<=tmp) for (;; i++) {
|
|
aprsstr_HashCh(buf[i], &hashl, &hashh);
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
while ((p<len && buf[p]!='\015') && buf[p]!='\012') {
|
|
aprsstr_HashCh(buf[p], &hashl, &hashh);
|
|
++p;
|
|
}
|
|
ha = (uint32_t)(uint8_t)(char)hashl+(uint32_t)(uint8_t)
|
|
(char)hashh*256UL&65535UL;
|
|
if (timehash[ha]+dupetime>aprsdecode_realtime) return -5L;
|
|
/* a duplicate */
|
|
if (udpchan || valid) timehash[ha] = aprsdecode_realtime;
|
|
if (udpchan==0UL && !valid) return -1L;
|
|
buf[p] = '\015';
|
|
++p;
|
|
buf[p] = '\012';
|
|
++p;
|
|
buf[p] = 0;
|
|
++p;
|
|
ilen = aprsstr_Length(qtext, 32ul);
|
|
if (ilen>0UL) {
|
|
while (p>pins) {
|
|
--p;
|
|
buf[p+ilen] = buf[p];
|
|
}
|
|
i = 0UL;
|
|
while (i<ilen) {
|
|
buf[p] = qtext[i];
|
|
++p;
|
|
++i;
|
|
}
|
|
}
|
|
return 0L;
|
|
} /* end AprsIs() */
|
|
|
|
|
|
static void connstr(aprsdecode_pTCPSOCK cp, char s[], uint32_t s_len)
|
|
{
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = cp;
|
|
useri_confstr(useri_fMYCALL, s, s_len);
|
|
aprsstr_Append(s, s_len, " connected to ", 15ul);
|
|
aprsstr_Append(s, s_len, anonym->ipnum, 64ul);
|
|
aprsstr_Append(s, s_len, ":", 2ul);
|
|
aprsstr_Append(s, s_len, anonym->port, 6ul);
|
|
}
|
|
} /* end connstr() */
|
|
|
|
|
|
static void wrconnected(aprsdecode_pTCPSOCK cp)
|
|
{
|
|
char h[301];
|
|
connstr(cp, h, 301ul);
|
|
useri_textautosize(0L, 5L, 6UL, 5UL, 'b', h, 301ul);
|
|
} /* end wrconnected() */
|
|
|
|
|
|
extern void aprsdecode_tcpconnstat(char s[], uint32_t s_len)
|
|
{
|
|
aprsdecode_pTCPSOCK tcp0;
|
|
char h[100];
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
tcp0 = aprsdecode_tcpsocks;
|
|
while (tcp0) {
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = tcp0;
|
|
if (anonym->connt>0UL && anonym->connt<aprsdecode_realtime) {
|
|
if (s[0UL]) aprsstr_Append(s, s_len, "\012", 2ul);
|
|
aprsstr_Append(s, s_len, "TCP:", 5ul);
|
|
aprsstr_Append(s, s_len, anonym->ipnum, 64ul);
|
|
aprsstr_Append(s, s_len, ":", 2ul);
|
|
aprsstr_Append(s, s_len, anonym->port, 6ul);
|
|
aprsstr_Append(s, s_len, "\012 Connecttime:", 16ul);
|
|
aprsstr_TimeToStr(aprsdecode_realtime-anonym->connt, h, 100ul);
|
|
aprsstr_Append(s, s_len, h, 100ul);
|
|
if (aprsdecode_lasttcprx<=aprsdecode_realtime && aprsdecode_realtime-aprsdecode_lasttcprx<3600UL)
|
|
{
|
|
aprsstr_Append(s, s_len, "\012 No rx since:", 16ul);
|
|
aprsstr_TimeToStr(aprsdecode_realtime-aprsdecode_lasttcprx, h,
|
|
100ul);
|
|
aprsstr_Append(s, s_len, h, 100ul);
|
|
}
|
|
aprsstr_Append(s, s_len, "\012 Rx Frames:", 14ul);
|
|
aprsstr_IntToStr((int32_t)anonym->rxframes, 1UL, h, 100ul);
|
|
aprsstr_Append(s, s_len, h, 100ul);
|
|
aprsstr_Append(s, s_len, "\012 Rx Bytes:", 13ul);
|
|
aprsstr_IntToStr((int32_t)anonym->rxbytes, 1UL, h, 100ul);
|
|
aprsstr_Append(s, s_len, h, 100ul);
|
|
aprsstr_Append(s, s_len, "\012 Tx Frames:", 14ul);
|
|
aprsstr_IntToStr((int32_t)anonym->txframes, 1UL, h, 100ul);
|
|
aprsstr_Append(s, s_len, h, 100ul);
|
|
aprsstr_Append(s, s_len, "\012 Tx Bytes:", 13ul);
|
|
aprsstr_IntToStr((int32_t)anonym->txbytes, 1UL, h, 100ul);
|
|
aprsstr_Append(s, s_len, h, 100ul);
|
|
}
|
|
tcp0 = anonym->next;
|
|
}
|
|
}
|
|
} /* end tcpconnstat() */
|
|
|
|
|
|
extern void aprsdecode_udpconnstat(uint32_t port, char s[],
|
|
uint32_t s_len)
|
|
{
|
|
char h[51];
|
|
uint32_t i;
|
|
struct aprsdecode_UDPSOCK * anonym;
|
|
if (port<=3UL) {
|
|
{ /* with */
|
|
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[port];
|
|
if (anonym->starttime>0UL) {
|
|
if (aprsdecode_realtime<anonym->starttime) {
|
|
anonym->starttime = aprsdecode_realtime;
|
|
}
|
|
if (s[0UL]) aprsstr_Append(s, s_len, "\012", 2ul);
|
|
aprsstr_Append(s, s_len, "Rf ", 4ul);
|
|
aprsstr_IntToStr((int32_t)(port+1UL), 1UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
aprsstr_Append(s, s_len, ":", 2ul);
|
|
i = 1UL;
|
|
for (;;) {
|
|
useri_conf2str((uint8_t)(36UL+port), i, h, 51ul);
|
|
if (h[0U]==0) break;
|
|
if (i>1UL) aprsstr_Append(s, s_len, " ", 2ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
++i;
|
|
}
|
|
aprsstr_Append(s, s_len, "\012 ", 4ul);
|
|
aprsstr_ipv4tostr(anonym->ip, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
aprsstr_Append(s, s_len, ":", 2ul);
|
|
aprsstr_IntToStr((int32_t)anonym->dport, 0UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
if (anonym->checkip) aprsstr_Append(s, s_len, "/", 2ul);
|
|
else aprsstr_Append(s, s_len, ":", 2ul);
|
|
aprsstr_IntToStr((int32_t)anonym->bindport, 0UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
aprsstr_Append(s, s_len, "\012 Uptime :", 12ul);
|
|
aprsstr_TimeToStr(aprsdecode_realtime-anonym->starttime, h,
|
|
51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
if (anonym->lastudprx>0UL && anonym->lastudprx<=aprsdecode_realtime)
|
|
{
|
|
aprsstr_Append(s, s_len, "\012 Last rx:", 12ul);
|
|
aprsstr_TimeToStr(aprsdecode_realtime-anonym->lastudprx, h,
|
|
51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
}
|
|
if (anonym->lastudptx>0UL && anonym->lastudptx<=aprsdecode_realtime)
|
|
{
|
|
aprsstr_Append(s, s_len, "\012 Last tx:", 12ul);
|
|
aprsstr_TimeToStr(aprsdecode_realtime-anonym->lastudptx, h,
|
|
51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
}
|
|
if (aprsdecode_realtime<anonym->bpstime && anonym->bpstime-aprsdecode_realtime<3600UL)
|
|
{
|
|
aprsstr_Append(s, s_len, "\012 Next net>rf(s):", 19ul);
|
|
aprsstr_IntToStr((int32_t)
|
|
(anonym->bpstime-aprsdecode_realtime), 1UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
}
|
|
aprsstr_Append(s, s_len, "\012 Rx Frames:", 14ul);
|
|
aprsstr_IntToStr((int32_t)anonym->rxframes, 1UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
aprsstr_Append(s, s_len, "\012 Rx Bytes:", 13ul);
|
|
aprsstr_IntToStr((int32_t)anonym->rxbytes, 1UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
aprsstr_Append(s, s_len, "\012 Tx Frames:", 14ul);
|
|
aprsstr_IntToStr((int32_t)anonym->txframes, 1UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
aprsstr_Append(s, s_len, "\012 Tx Bytes:", 13ul);
|
|
aprsstr_IntToStr((int32_t)anonym->txbytes, 1UL, h, 51ul);
|
|
aprsstr_Append(s, s_len, h, 51ul);
|
|
}
|
|
}
|
|
}
|
|
} /* end udpconnstat() */
|
|
|
|
|
|
extern void aprsdecode_tcpclose(aprsdecode_pTCPSOCK w, char fin)
|
|
{
|
|
char h[201];
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = w;
|
|
if ((int32_t)anonym->fd>=0L) osic_CloseSock(anonym->fd);
|
|
anonym->fd = -1L;
|
|
aprsdecode_lasttcprx = 0UL;
|
|
strncpy(h,"\012TCP Close ",201u);
|
|
aprsstr_Append(h, 201ul, anonym->ipnum, 64ul);
|
|
aprsstr_Append(h, 201ul, ":", 2ul);
|
|
aprsstr_Append(h, 201ul, anonym->port, 6ul);
|
|
aprsstr_Append(h, 201ul, "\012", 2ul);
|
|
useri_textautosize(0L, 5L, 6UL, 4UL, 'e', h, 201ul);
|
|
}
|
|
} /* end tcpclose() */
|
|
|
|
|
|
static void Watchbeacon(aprsdecode_pTCPSOCK cp)
|
|
{
|
|
char ok0;
|
|
aprsdecode_FRAMEBUF tmp;
|
|
ok0 = Sendtcp(cp, *(aprsdecode_FRAMEBUF *)memcpy(&tmp,"# watchbeacon\015\01\
|
|
2",16u));
|
|
cp->watchtime = aprsdecode_realtime;
|
|
} /* end Watchbeacon() */
|
|
|
|
|
|
static void appfilter(char s[], uint32_t s_len, char nulltoo)
|
|
/* build string "filter m/300" */
|
|
{
|
|
char h[1000];
|
|
useri_confstr(useri_fSERVERFILT, h, 1000ul);
|
|
if (nulltoo || h[0U]) {
|
|
aprsstr_Append(s, s_len, " filter ", 9ul);
|
|
aprsstr_Append(s, s_len, h, 1000ul);
|
|
}
|
|
} /* end appfilter() */
|
|
|
|
|
|
static void updatefilters(aprsdecode_pTCPSOCK cp)
|
|
{
|
|
char ok0;
|
|
aprsdecode_FRAMEBUF s;
|
|
strncpy(s,"#",512u);
|
|
appfilter(s, 512ul, 1);
|
|
aprsstr_Append(s, 512ul, "\015\012", 3ul);
|
|
ok0 = Sendtcp(cp, s);
|
|
strncpy(s,"Sent to Server",512u);
|
|
appfilter(s, 512ul, 1);
|
|
useri_textautosize(0L, 5L, 6UL, 4UL, 'b', s, 512ul);
|
|
} /* end updatefilters() */
|
|
|
|
|
|
static char tcpconn(aprsdecode_pTCPSOCK * sockchain, int32_t f)
|
|
{
|
|
aprsdecode_pTCPSOCK cp;
|
|
aprsdecode_FRAMEBUF h;
|
|
int32_t res;
|
|
char ok0;
|
|
char s[100];
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
if ((int32_t)f<0L) return 0;
|
|
osic_alloc((char * *) &cp, sizeof(struct aprsdecode_TCPSOCK));
|
|
useri_debugmem.req = sizeof(struct aprsdecode_TCPSOCK);
|
|
useri_debugmem.mon += useri_debugmem.req;
|
|
if (cp==0) {
|
|
osic_CloseSock(f);
|
|
if (aprsdecode_verb) osi_WrStrLn("tcp conn out of memory", 23ul);
|
|
return 0;
|
|
}
|
|
memset((char *)cp,(char)0,sizeof(struct aprsdecode_TCPSOCK));
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = cp;
|
|
anonym->fd = f;
|
|
res = socknonblock(f);
|
|
/* txbuf:=NIL; */
|
|
anonym->watchtime = aprsdecode_realtime;
|
|
}
|
|
cp->next = *sockchain;
|
|
*sockchain = cp;
|
|
useri_confstr(useri_fMYCALL, s, 100ul);
|
|
if (s[0U]) {
|
|
if (aprstext_callwrong(s, 100ul)) {
|
|
useri_xerrmsg("illegal \'My Call\' in login", 27ul);
|
|
}
|
|
aprsstr_Assign(h, 512ul, "user ", 6ul);
|
|
aprsstr_Append(h, 512ul, s, 100ul);
|
|
useri_confstr(useri_fPW, s, 100ul);
|
|
if (s[0U]) {
|
|
/* & configon(fPW)*/
|
|
aprsstr_Append(h, 512ul, " pass ", 7ul);
|
|
aprsstr_Append(h, 512ul, s, 100ul);
|
|
}
|
|
aprsstr_Append(h, 512ul, " vers ", 7ul);
|
|
aprsstr_Append(h, 512ul, "aprsmap(cu) 0.66", 17ul);
|
|
appfilter(h, 512ul, 0);
|
|
/* IF filter[0]<>0C THEN Append(h, " filter ");
|
|
Append(h, filter) END; */
|
|
aprsstr_Append(h, 512ul, "\015\012", 3ul);
|
|
ok0 = Sendtcp(cp, h);
|
|
}
|
|
cp->txframes = 0UL;
|
|
cp->txbytes = 0UL;
|
|
return 1;
|
|
} /* end tcpconn() */
|
|
|
|
/*
|
|
PROCEDURE Gateconn(VAR cp:pTCPSOCK);
|
|
VAR fd:SOCKET;
|
|
p, act, try, kill:pTCPSOCK;
|
|
max:CARDINAL;
|
|
BEGIN
|
|
--WrStrLn(" gateconn");
|
|
(*
|
|
IF cp<>NIL THEN
|
|
IF (cp^.fd<>CAST(SOCKET,-1)) & NOT configon(fSERVERURL) THEN
|
|
saybusy(kill^.fd, "");
|
|
END;
|
|
ELSIF
|
|
*)
|
|
act:=NIL;
|
|
try:=NIL;
|
|
p:=cp;
|
|
WHILE p<>NIL DO
|
|
IF p^.connt>0 THEN (* we have gate connect *)
|
|
IF act<>NIL THEN (* we have 2 connects *)
|
|
IF act^.gatepri>p^.gatepri THEN (* stop second best *)
|
|
kill:=act;
|
|
act:=p;
|
|
ELSE kill:=p END; (* stop second best *)
|
|
saybusy(kill^.fd, "# remove double connect"+CR+LF)
|
|
ELSE act:=p END;
|
|
ELSE try:=p END; (* trying to connect *)
|
|
p:=p^.next;
|
|
END;
|
|
IF (try=NIL) & Watchclock(connecttime,
|
|
GATECONNDELAY) THEN (* no trials *)
|
|
IF act=NIL THEN max:=HIGH(gateways) ELSE max:=act^.gatepri END;
|
|
(* try only better *)
|
|
IF (trygate>=max) OR (trygate>HIGH(gateways))
|
|
OR (gateways[trygate].url[0]=0C) THEN trygate:=0 END;
|
|
(* loop thru table *)
|
|
|
|
IF trygate<max THEN
|
|
WITH gateways[trygate] DO
|
|
IF url[0]<>0C THEN
|
|
fd:=connectto(url, port);
|
|
--WrInt(fd, 1);WrStrLn(" connfd");
|
|
|
|
IF CAST(INTEGER,fd)>=0 THEN
|
|
IF tcpconn(cp, fd, filterst) THEN
|
|
Assign(cp^.ipnum, url);
|
|
Assign(cp^.port, port);
|
|
cp^.gatepri:=trygate;
|
|
-- Assign(h, servercall);
|
|
-- Append(h, " connected to "); Append(h, url); Append(h, ":");
|
|
Append(h, port);
|
|
-- xerrmsg(h);
|
|
END;
|
|
END;
|
|
END;
|
|
END;
|
|
END;
|
|
INC(trygate);
|
|
|
|
END;
|
|
END Gateconn;
|
|
*/
|
|
|
|
static void urlport(char s[], uint32_t s_len, char url[],
|
|
uint32_t url_len, char port[], uint32_t port_len)
|
|
/* url:port to url port */
|
|
{
|
|
int32_t i;
|
|
X2C_PCOPY((void **)&s,s_len);
|
|
aprsstr_Assign(url, url_len, s, s_len);
|
|
i = aprsstr_InStr(url, url_len, ":", 2ul);
|
|
if (i>0L) {
|
|
url[i] = 0;
|
|
aprsstr_Delstr(s, s_len, 0UL, (uint32_t)(i+1L));
|
|
aprsstr_Assign(port, port_len, s, s_len);
|
|
}
|
|
else port[0UL] = 0;
|
|
X2C_PFREE(s);
|
|
} /* end urlport() */
|
|
|
|
#define aprsdecode_DEFAULTPORT "14580"
|
|
|
|
|
|
static void Gateconn(aprsdecode_pTCPSOCK * cp)
|
|
{
|
|
int32_t fd;
|
|
char port[1000];
|
|
char ip[1000];
|
|
char s[1000];
|
|
/*WrInt(cycleservers, 5); WrStrLn(" gateconn"); */
|
|
if (*cp) {
|
|
if ((int32_t)(*cp)->fd>=0L && !useri_configon(useri_fCONNECT)) {
|
|
saybusy(&(*cp)->fd, "", 1ul);
|
|
}
|
|
}
|
|
else if (useri_configon(useri_fCONNECT) && Watchclock(&connecttime,
|
|
30UL)) {
|
|
for (;;) {
|
|
useri_confstrings(useri_fSERVERURL, cycleservers, 0, s, 1000ul);
|
|
if (s[0U] || cycleservers==0UL) break;
|
|
cycleservers = 0UL;
|
|
}
|
|
if (s[0U]) {
|
|
++cycleservers;
|
|
urlport(s, 1000ul, ip, 1000ul, port, 1000ul);
|
|
if (port[0U]==0) strncpy(port,"14580",1000u);
|
|
/*WrInt(cycleservers, 5);WrStr(" <"); WrStr(ip);WrStr("><");
|
|
WrStr(port);WrStrLn(">"); */
|
|
fd = connectto(ip, port);
|
|
if ((int32_t)fd>=0L) {
|
|
if (tcpconn(cp, fd)) {
|
|
aprsstr_Assign((*cp)->ipnum, 64ul, ip, 1000ul);
|
|
aprsstr_Assign((*cp)->port, 6ul, port, 1000ul);
|
|
(*cp)->beacont = 0UL; /* send next beacon now */
|
|
}
|
|
}
|
|
}
|
|
else useri_xerrmsg("Net: No Online/Server URL configured", 37ul);
|
|
}
|
|
} /* end Gateconn() */
|
|
|
|
|
|
static void porttext(uint32_t p, char s[], uint32_t s_len)
|
|
{
|
|
char h[31];
|
|
aprsstr_IntToStr((int32_t)(p+1UL), 1UL, h, 31ul);
|
|
aprsstr_Assign(s, s_len, "UDP ", 5ul);
|
|
aprsstr_Append(s, s_len, h, 31ul);
|
|
} /* end porttext() */
|
|
|
|
|
|
static void rfbeacons(void)
|
|
{
|
|
uint32_t i;
|
|
uint32_t nb;
|
|
int32_t j;
|
|
uint32_t shift;
|
|
uint32_t bshift;
|
|
uint32_t bn;
|
|
uint32_t bt;
|
|
aprsdecode_FRAMEBUF s;
|
|
char h[101];
|
|
char says[101];
|
|
char port;
|
|
struct aprsdecode_DAT dat;
|
|
char tmp;
|
|
nb = 0UL;
|
|
shift = beaconrandomstart;
|
|
bshift = (uint32_t)useri_conf2int(useri_fRFBTSHIFT, 0UL, 0L, 86400L,
|
|
120L);
|
|
if (rfbecondone==0UL || rfbecondone>aprsdecode_realtime) {
|
|
rfbecondone = aprsdecode_realtime;
|
|
}
|
|
for (;;) {
|
|
if (aprsdecode_testbeaconbuf[0UL]) {
|
|
/* manual sent beacon */
|
|
aprsstr_Assign(s, 512ul, aprsdecode_testbeaconbuf, 512ul);
|
|
aprsdecode_testbeaconbuf[0UL] = 0;
|
|
strncpy(says,"Sent: ",101u);
|
|
aprsstr_Append(says, 101ul, s, 512ul);
|
|
if (getbeaconparm(s, 512ul, &bt, &port)) bt = 1UL;
|
|
else bt = 0UL;
|
|
}
|
|
else {
|
|
useri_confstrings(useri_fRBTEXT, nb, 0, s, 512ul);
|
|
if (s[0UL]==0) break;
|
|
if (!getbeaconparm(s, 512ul, &bt, &port)) bt = 0UL;
|
|
says[0U] = 0;
|
|
}
|
|
if (bt>0UL) {
|
|
/* valid time */
|
|
bn = (aprsdecode_realtime+shift)%bt;
|
|
/*WrInt(realtime MOD 86400, 10); WrInt(realtime-rfbecondone, 4);
|
|
WrInt(bshift, 4); WrInt(shift, 14); WrStrLn(" bshift"); */
|
|
if (bn<aprsdecode_realtime-rfbecondone) {
|
|
beaconmacros(s, 512ul, "", 1ul, "", 1ul, 1);
|
|
if (s[0UL]) {
|
|
if (aprsdecode_Decode(s, 512ul, &dat)>=0L) {
|
|
if ((uint8_t)dat.symt<' ') {
|
|
strncpy(h,"beacon warning: no symbol: ",101u);
|
|
aprsstr_Append(h, 101ul, s, 512ul);
|
|
useri_xerrmsg(h, 101ul);
|
|
}
|
|
if (X2C_CAP(port)=='N') {
|
|
/* beacon to net */
|
|
if (dat.type!=aprsdecode_MICE) {
|
|
j = aprsstr_InStr(s, 512ul, ":", 2ul);
|
|
if (j>=0L) {
|
|
aprsstr_Delstr(s, 512ul, 0UL, (uint32_t)(j+1L));
|
|
/* remove rf adress */
|
|
SendNet(aprsdecode_tcpsocks, dat.srcall, 9ul, s,
|
|
512ul, 1, h, 101ul);
|
|
if (h[0U]) {
|
|
strncpy(says,"beacon: not sent ",101u);
|
|
aprsstr_Append(says, 101ul, h, 101ul);
|
|
}
|
|
}
|
|
}
|
|
else strncpy(says,"beacon: not sent mic-e to Net",101u);
|
|
}
|
|
else if ((uint8_t)port>='1') {
|
|
if (s[0UL]) {
|
|
i = (uint32_t)(uint8_t)port-49UL;
|
|
if (i<4UL && useri_configon((uint8_t)(36UL+i))) {
|
|
if (Sendudp(s, 512ul, i, 1UL)<0L) {
|
|
strncpy(says,"beacon: Rfport ",101u);
|
|
aprsstr_Append(says, 101ul,
|
|
(char *)(tmp = (char)(i+49UL),&tmp), 1u/1u);
|
|
aprsstr_Append(says, 101ul, " not configured to\
|
|
send", 24ul);
|
|
}
|
|
}
|
|
else {
|
|
strncpy(says,"beacon: Rfport ",101u);
|
|
aprsstr_Append(says, 101ul,
|
|
(char *)(tmp = (char)(i+49UL),&tmp), 1u/1u);
|
|
aprsstr_Append(says, 101ul, " not enabled", 13ul);
|
|
}
|
|
}
|
|
}
|
|
if (says[0U]) useri_say(says, 101ul, 2UL, 'b');
|
|
}
|
|
else {
|
|
strncpy(h,"rfbeacon not decodeable: ",101u);
|
|
aprsstr_Append(h, 101ul, s, 512ul);
|
|
useri_xerrmsg(h, 101ul);
|
|
}
|
|
}
|
|
}
|
|
shift += bshift; /* delay next beacon by shift time to before beacon */
|
|
}
|
|
++nb;
|
|
}
|
|
rfbecondone = aprsdecode_realtime;
|
|
} /* end rfbeacons() */
|
|
|
|
|
|
static void startserial(struct xosi_PROCESSHANDLE * pid, uint8_t cfg)
|
|
{
|
|
char h[1001];
|
|
char s[1001];
|
|
if (useri_configon(cfg)) {
|
|
if (!(pid->runs || pid->started)) {
|
|
useri_confstr(cfg, s, 1001ul);
|
|
if (s[0U]) {
|
|
xosi_StartProg(s, 1001ul, pid);
|
|
pid->started = 1;
|
|
if (pid->runs) {
|
|
useri_say("Start Serial Interface", 23ul, 3UL, 'g');
|
|
}
|
|
else {
|
|
strncpy(h,"can not start ",1001u);
|
|
aprsstr_Append(h, 1001ul, s, 1001ul);
|
|
useri_xerrmsg(h, 1001ul);
|
|
useri_configbool(cfg, 0);
|
|
useri_refresh = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else pid->started = 0;
|
|
} /* end startserial() */
|
|
|
|
|
|
extern void aprsdecode_tcpjobs(void)
|
|
{
|
|
aprsdecode_pTCPSOCK acttcp;
|
|
int32_t i;
|
|
int32_t len;
|
|
char ok0;
|
|
char s[1000];
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
struct aprsdecode_UDPSOCK * anonym0;
|
|
if (qwatchtime!=aprsdecode_realtime) {
|
|
acttcp = aprsdecode_tcpsocks;
|
|
while (acttcp) {
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = acttcp;
|
|
Timebeacon(acttcp);
|
|
if (anonym->watchtime+180UL<aprsdecode_realtime) {
|
|
Watchbeacon(acttcp);
|
|
}
|
|
if (useri_configon(useri_fALLOWGATE)) WatchTXQ(acttcp);
|
|
if (useri_isupdated(useri_fSERVERFILT)) updatefilters(acttcp);
|
|
acttcp = anonym->next;
|
|
}
|
|
}
|
|
qwatchtime = aprsdecode_realtime;
|
|
Gateconn(&aprsdecode_tcpsocks);
|
|
rfbeacons();
|
|
}
|
|
/*UDP */
|
|
for (i = 0L; i<=3L; i++) {
|
|
{ /* with */
|
|
struct aprsdecode_UDPSOCK * anonym0 = &aprsdecode_udpsocks0[i];
|
|
if (useri_configon((uint8_t)(36UL+(uint32_t)i))
|
|
&& !useri_isupdated((uint8_t)(36UL+(uint32_t)i))) {
|
|
if ((int32_t)anonym0->fd<0L) {
|
|
ok0 = 0;
|
|
useri_confstr((uint8_t)(36UL+(uint32_t)i), s, 1000ul);
|
|
if (s[0U]) {
|
|
memset((char *) &aprsdecode_udpsocks0[i],(char)0,
|
|
sizeof(struct aprsdecode_UDPSOCK));
|
|
anonym0->fd = -1L;
|
|
if (aprsstr_GetIp2(s, 1000ul, &anonym0->ip,
|
|
&anonym0->dport, &anonym0->bindport, &anonym0->checkip)<0L) {
|
|
anonym0->rawread = 1;
|
|
porttext((uint32_t)i, s, 1000ul);
|
|
aprsstr_Append(s, 1000ul, " Config Error <IPNumber:TxPor\
|
|
t:RxPort>", 39ul);
|
|
/* textautosize(0, 5, 6, 10, "e", s); */
|
|
useri_xerrmsg(s, 1000ul);
|
|
}
|
|
else {
|
|
anonym0->fd = openudp();
|
|
anonym0->rawread = 1;
|
|
porttext((uint32_t)i, s, 1000ul);
|
|
if ((int32_t)anonym0->fd<0L || bindudp(anonym0->fd,
|
|
anonym0->bindport)<0L) {
|
|
aprsstr_Append(s, 1000ul, " Bindport Error, Illegal (\
|
|
Rx)Port or in Use", 44ul);
|
|
/* textautosize(0, 5, 6, 10, "e", s);
|
|
*/
|
|
useri_xerrmsg(s, 1000ul);
|
|
osic_CloseSock(anonym0->fd);
|
|
anonym0->fd = -1L;
|
|
}
|
|
else {
|
|
aprsstr_Append(s, 1000ul, " Open", 6ul);
|
|
len = socknonblock(anonym0->fd);
|
|
useri_textautosize(0L, 5L, 6UL, 5UL, 'b', s, 1000ul);
|
|
ok0 = 1;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
porttext((uint32_t)i, s, 1000ul);
|
|
aprsstr_Append(s, 1000ul, " Not Configured", 16ul);
|
|
/* textautosize(0, 5, 6, 10, "e", s); */
|
|
useri_xerrmsg(s, 1000ul);
|
|
}
|
|
if (!ok0) {
|
|
useri_configbool((uint8_t)(36UL+(uint32_t)i), 0);
|
|
}
|
|
}
|
|
}
|
|
else if ((int32_t)anonym0->fd>=0L) {
|
|
osic_CloseSock(anonym0->fd);
|
|
anonym0->fd = -1L;
|
|
anonym0->starttime = 0UL;
|
|
porttext((uint32_t)i, s, 1000ul);
|
|
aprsstr_Append(s, 1000ul, " Close", 7ul);
|
|
/* textautosize(0, 5, 6, 4, "e", s); */
|
|
useri_xerrmsg(s, 1000ul);
|
|
}
|
|
}
|
|
} /* end for */
|
|
startserial(&aprsdecode_serialpid, useri_fSERIALTASK);
|
|
startserial(&aprsdecode_serialpid2, useri_fSERIALTASK2);
|
|
sendmsg();
|
|
/*WrInt(tickertime, 15); WrInt(realtime, 15); WrLn; */
|
|
if (tickertime+60UL<aprsdecode_realtime) Stopticker();
|
|
} /* end tcpjobs() */
|
|
|
|
|
|
static void beepprox(float d, float km)
|
|
{
|
|
if ((useri_configon(useri_fBEEPPROX) && km!=0.0f) && d<km) {
|
|
d = 1.0f-X2C_DIVR(d,km);
|
|
d = d*d;
|
|
d = d*d;
|
|
aprsdecode_beeplim(100L, aprsdecode_trunc((1.0f-d)*(float)useri_conf2int(useri_fBEEPPROX,
|
|
0UL, 20L, 8000L,
|
|
400L)+d*(float)useri_conf2int(useri_fBEEPPROX, 2UL, 20L,
|
|
8000L, 400L)), aprsdecode_trunc((1.0f-d)*(float)useri_conf2int(useri_fBEEPPROX,
|
|
1UL, 0L, 5000L, 40L)+d*(float)useri_conf2int(useri_fBEEPPROX,
|
|
3UL, 0L, 5000L, 1000L)));
|
|
}
|
|
} /* end beepprox() */
|
|
|
|
#define aprsdecode_WARNFN "proxwarn"
|
|
|
|
#define aprsdecode_LOOKBACK 180
|
|
/* last s look if nearest pos is last */
|
|
|
|
|
|
static void approxywarn(struct aprspos_POSITION pos, const char call[],
|
|
uint32_t call_len)
|
|
{
|
|
char s[31];
|
|
char h[101];
|
|
float d;
|
|
float mino;
|
|
float mind;
|
|
float km;
|
|
struct aprspos_POSITION mypos;
|
|
aprsdecode_pOPHIST op;
|
|
aprsdecode_pFRAMEHIST pf;
|
|
int32_t fd;
|
|
km = useri_conf2real(useri_fAPPROXY, 0UL, 0.0f, 30000.0f, 0.0f);
|
|
if (km!=0.0f) {
|
|
if (aprstext_getmypos(&mypos)) {
|
|
d = aprspos_distance(pos, mypos);
|
|
if (d<=km) {
|
|
/* quick check if it is in radius */
|
|
op = aprsdecode_ophist0;
|
|
while (op && X2C_STRCMP(op->call,9u,call,call_len)) {
|
|
op = op->next;
|
|
}
|
|
if (op) {
|
|
mino = 30000.0f;
|
|
mind = 30000.0f;
|
|
pf = op->frames;
|
|
while (pf) {
|
|
if (pf->time0+180UL>aprsdecode_realtime && (pf->nodraw&0x4FU)
|
|
==0U) {
|
|
d = aprspos_distance(pf->vardat->pos, mypos);
|
|
/*
|
|
FixToStr(distance(pf^.vardat^.pos, mypos), 4, s);
|
|
WrStr(s); WrStr(" ");
|
|
FixToStr(distance(mypos, pf^.vardat^.pos), 4, s);
|
|
WrStr(s); WrStr(" ");
|
|
postostr(pf^.vardat^.pos, s); WrStr(s); WrStr(" ");
|
|
postostr(mypos, s); WrStrLn(s);
|
|
*/
|
|
mino = mind;
|
|
if (d<mind) mind = d;
|
|
}
|
|
pf = pf->next;
|
|
}
|
|
if ((mino<29000.0f && mino!=d) && mino>d) {
|
|
beepprox(d, km);
|
|
strncpy(h,"approach ",101u);
|
|
aprsstr_FixToStr(d, 3UL, s, 31ul);
|
|
aprsstr_Append(h, 101ul, s, 31ul);
|
|
aprsstr_Append(h, 101ul, "km ", 4ul);
|
|
aprsstr_Append(h, 101ul, call, call_len);
|
|
useri_textautosize(0L, 5L, 6UL, 120UL, 'r', h, 101ul);
|
|
if (!osi_Exists("proxwarn", 9ul)) {
|
|
fd = osi_OpenWrite("proxwarn", 9ul);
|
|
if (osic_FdValid(fd)) {
|
|
aprsstr_Assign(h, 101ul, call, call_len);
|
|
aprsstr_IntToStr((int32_t)
|
|
aprsdecode_trunc(d*1000.0f), 0UL, s, 31ul);
|
|
aprsstr_Append(h, 101ul, " p ", 4ul);
|
|
aprsstr_Append(h, 101ul, s, 31ul);
|
|
osi_WrBin(fd, (char *)h, 101u/1u,
|
|
aprsstr_Length(h, 101ul));
|
|
osic_Close(fd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} /* end approxywarn() */
|
|
|
|
#define aprsdecode_DUPTIME 27
|
|
|
|
#define aprsdecode_NN "n"
|
|
|
|
#define aprsdecode_BAD "x"
|
|
|
|
#define aprsdecode_VIA "v"
|
|
|
|
|
|
static void app0(uint32_t * viac, aprsdecode_FRAMEBUF tb, uint32_t * tp,
|
|
char c)
|
|
{
|
|
if (*tp<511UL) {
|
|
tb[*tp] = c;
|
|
++*tp;
|
|
}
|
|
if (c==',') ++*viac;
|
|
} /* end app() */
|
|
|
|
|
|
static char via(char words[], uint32_t words_len,
|
|
aprsdecode_FRAMEBUF b, char typ, uint32_t from,
|
|
uint32_t to)
|
|
{
|
|
uint32_t i;
|
|
char h[31];
|
|
if (from>=to) return 0;
|
|
h[0U] = typ;
|
|
i = 1UL;
|
|
while (i<28UL && from<to) {
|
|
h[i] = b[from];
|
|
++from;
|
|
++i;
|
|
}
|
|
h[i] = ' ';
|
|
h[i+1UL] = 0;
|
|
return aprsstr_InStr(words, words_len, h, 31ul)>=0L;
|
|
} /* end via() */
|
|
|
|
|
|
static char num0(aprsdecode_FRAMEBUF b, uint32_t i, uint32_t * n)
|
|
{
|
|
if ((i<511UL && (uint8_t)b[i]>='0') && (uint8_t)b[i]<='9') {
|
|
*n = (uint32_t)(uint8_t)b[i]-48UL;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
} /* end num() */
|
|
|
|
|
|
static char scanpath(char words[], uint32_t words_len,
|
|
uint32_t * tp, aprsdecode_FRAMEBUF tb, uint32_t * viac,
|
|
aprsdecode_FRAMEBUF b, uint32_t * p, uint32_t to,
|
|
char store)
|
|
{
|
|
uint32_t hp;
|
|
hp = *p;
|
|
while (*p<to) {
|
|
if (store) app0(viac, tb, tp, b[*p]);
|
|
if (*p+1UL>=to || b[*p]==',') {
|
|
if (via(words, words_len, b, 'x', hp+1UL,
|
|
*p+(uint32_t)(*p+1UL>=to))) return 0;
|
|
/* bad word */
|
|
hp = *p;
|
|
}
|
|
++*p;
|
|
}
|
|
return 1;
|
|
} /* end scanpath() */
|
|
|
|
|
|
static void digi(const aprsdecode_FRAMEBUF b, char fromrf,
|
|
uint32_t outport, char directonly,
|
|
char appendrest, uint32_t nomovetime,
|
|
uint32_t radius, char words[], uint32_t words_len,
|
|
int32_t * txbyte)
|
|
{
|
|
struct aprsdecode_DAT dat;
|
|
uint32_t pn;
|
|
uint32_t viac;
|
|
uint32_t n2;
|
|
uint32_t n1;
|
|
uint32_t n;
|
|
uint32_t ssid;
|
|
uint32_t len;
|
|
uint32_t tp;
|
|
uint32_t p;
|
|
aprsdecode_FRAMEBUF tb;
|
|
/* hashl, hashh:SET8; */
|
|
uint32_t dt;
|
|
char norout;
|
|
struct aprspos_POSITION mypos;
|
|
char s2[31];
|
|
char s1[31];
|
|
char mycall[31];
|
|
*txbyte = 0L;
|
|
if (nomovetime<27UL) nomovetime = 27UL;
|
|
if (fromrf) {
|
|
tp = 0UL;
|
|
p = 0UL;
|
|
len = 0UL;
|
|
ssid = 0UL;
|
|
viac = 0UL;
|
|
useri_confstr(useri_fMYCALL, mycall, 31ul);
|
|
if (aprstext_callwrong(mycall, 31ul)) {
|
|
useri_xerrmsg("Digi needs \'My Call\'", 21ul); /* no mycall */
|
|
return;
|
|
}
|
|
norout = aprsstr_InStr(words, words_len, " x-", 4ul)>=0L;
|
|
/* ssid routing off */
|
|
if (aprsstr_InStr(words, words_len, " xi", 4ul)<0L) {
|
|
aprsstr_Append(words, words_len, " v", 3ul);
|
|
/* if not disabled append mycall for via */
|
|
aprsstr_Append(words, words_len, mycall, 31ul);
|
|
}
|
|
aprsstr_Append(words, words_len, " x", 3ul); /* mycall as badword */
|
|
aprsstr_Append(words, words_len, mycall, 31ul);
|
|
aprsstr_Append(words, words_len, " ", 2ul);
|
|
while ((len<511UL && b[len]) && b[len]!=':') ++len;
|
|
while (p<len && b[p]!='>') {
|
|
app0(&viac, tb, &tp, b[p]); /* end of src call */
|
|
++p;
|
|
}
|
|
if (via(words, words_len, b, 'x', 0UL, p)) return;
|
|
/* bad src call */
|
|
if (useri_configon(useri_fMUSTBECALL)) {
|
|
tb[tp] = 0;
|
|
if (!aprstext_isacall(tb, 512ul)) return;
|
|
}
|
|
n = p+1UL;
|
|
while ((p<len && b[p]!='-') && b[p]!=',') {
|
|
app0(&viac, tb, &tp, b[p]); /* ssid or end of dst call */
|
|
++p;
|
|
}
|
|
if (via(words, words_len, b, 'x', n, p)) return;
|
|
/* bad dest call */
|
|
if (b[p]=='-') {
|
|
/* we have a ssid */
|
|
++p;
|
|
if (num0(b, p, &n)) {
|
|
ssid = n;
|
|
++p;
|
|
if (num0(b, p, &n)) {
|
|
ssid = ssid*10UL+n;
|
|
++p;
|
|
}
|
|
}
|
|
}
|
|
if (ssid==0UL || ssid>7UL) norout = 1;
|
|
n = p;
|
|
while (n<len && b[n]!='*') ++n;
|
|
if (n+1UL<len) norout = 1;
|
|
if (!norout) {
|
|
/* use ssid routing */
|
|
if (appendrest) --ssid;
|
|
else ssid = 0UL;
|
|
}
|
|
if (ssid>0UL) {
|
|
/* write old or new ssid */
|
|
app0(&viac, tb, &tp, '-');
|
|
if (ssid>=10UL) app0(&viac, tb, &tp, '1');
|
|
app0(&viac, tb, &tp, (char)(ssid%10UL+48UL));
|
|
}
|
|
if (n<len) {
|
|
if (directonly) return;
|
|
/* not direct heard */
|
|
if (!scanpath(words, words_len, &tp, tb, &viac, b, &p, n, 1)) {
|
|
return;
|
|
}
|
|
/* append path till * and find badwords */
|
|
++p;
|
|
}
|
|
app0(&viac, tb, &tp, ',');
|
|
n = 0UL;
|
|
while (mycall[n]) {
|
|
app0(&viac, tb, &tp, mycall[n]); /* append mycall */
|
|
++n;
|
|
}
|
|
app0(&viac, tb, &tp, '*');
|
|
if (p<len) {
|
|
/* look for via routing */
|
|
norout = 1;
|
|
if (b[p]==',') ++p;
|
|
n = p;
|
|
while (p<len && b[p]!=',') ++p;
|
|
if (((((((via(words, words_len, b, 'n', n, p-3UL) && num0(b, p-3UL,
|
|
&n1)) && n1>0UL) && n1<=7UL) && b[p-2UL]=='-') && num0(b,
|
|
p-1UL, &n2)) && n2>0UL) && n2<=n1) {
|
|
if (directonly && n1!=n2) {
|
|
return;
|
|
}
|
|
/* not direct heard */
|
|
if (appendrest && n2>1UL) {
|
|
/* append not n-0 */
|
|
app0(&viac, tb, &tp, ',');
|
|
pn = n;
|
|
while (pn+3UL<p) {
|
|
app0(&viac, tb, &tp, b[pn]); /* append via word */
|
|
++pn;
|
|
}
|
|
app0(&viac, tb, &tp, (char)(n1+48UL)); /* append n-n */
|
|
app0(&viac, tb, &tp, '-');
|
|
app0(&viac, tb, &tp, (char)(n2+47UL));
|
|
}
|
|
norout = 0; /* append rest path later*/
|
|
}
|
|
else if (via(words, words_len, b, 'v', n, p)) norout = 0;
|
|
}
|
|
if (norout) return;
|
|
/* nothing to digipeat */
|
|
if (!scanpath(words, words_len, &tp, tb, &viac, b, &p, len,
|
|
appendrest)) return;
|
|
/* append rest path and find badwords */
|
|
if (viac>7UL) return;
|
|
/* too much via */
|
|
p = len;
|
|
while (p<511UL && b[p]) {
|
|
app0(&viac, tb, &tp, b[p]);
|
|
++p;
|
|
}
|
|
app0(&viac, tb, &tp, 0);
|
|
}
|
|
else memcpy(tb,b,512u);
|
|
if (aprsdecode_Decode(tb, 512ul, &dat)<0L) return;
|
|
/*radius */
|
|
if (dat.type!=aprsdecode_MSG && radius>0UL) {
|
|
if (!aprstext_getmypos(&mypos)) {
|
|
useri_xerrmsg("Digi with Radius needs MY Position", 35ul);
|
|
return;
|
|
}
|
|
if (!aprspos_posvalid(dat.pos) || aprspos_distance(mypos,
|
|
dat.pos)>(float)radius) return;
|
|
}
|
|
if (dat.type==aprsdecode_MSG && aprstext_isacall(dat.msgto, 9ul)) {
|
|
dt = 27UL; /* real messages fast dupetime */
|
|
}
|
|
else dt = nomovetime;
|
|
if (outport>0UL && outport-1UL<=3UL) {
|
|
*txbyte = Sendudp(tb, 512ul, outport-1UL, dt);
|
|
if (*txbyte<0L) {
|
|
strncpy(s1,"aprsdigi:can not send to port ",31u);
|
|
aprsstr_IntToStr((int32_t)outport, 0UL, s2, 31ul);
|
|
aprsstr_Append(s1, 31ul, s2, 31ul);
|
|
useri_xerrmsg(s1, 31ul);
|
|
}
|
|
}
|
|
} /* end digi() */
|
|
|
|
#define aprsdecode_MAXPAYLOAD 200
|
|
/* spare min 36 byte for 3rd party header */
|
|
|
|
#define aprsdecode_MSGMHTIME 3600
|
|
/* last heard age for msgs sending */
|
|
|
|
|
|
static void digitorf(const aprsdecode_FRAMEBUF b, uint32_t outport,
|
|
uint32_t nomovetime, uint32_t radius, int32_t maxbps,
|
|
char words[], uint32_t words_len)
|
|
{
|
|
uint32_t j;
|
|
uint32_t i;
|
|
int32_t sentbytes;
|
|
aprsdecode_pOPHIST op;
|
|
char ok0;
|
|
aprsdecode_FRAMEBUF tb;
|
|
struct aprsdecode_DAT dat;
|
|
char via0[201];
|
|
char ww[201];
|
|
char w[201];
|
|
/*"OH4ZZZ-5>APZ123,WIDE2-2:}OH2XYZ-11>APZYXW-4,TCPIP,OH4ZZZ-5*:>packet "*/
|
|
/*WrStr(words); WrStrLn(b); */
|
|
if (aprsdecode_Decode(b, 512ul, &dat)<0L || dat.igatep==0UL) return;
|
|
aprsstr_Assign(w, 201ul, words, words_len);
|
|
do {
|
|
aprsstr_Extractword(w, 201ul, ww, 201ul);
|
|
} while (!(ww[0U]==0 || ww[0U]=='n'));
|
|
if (ww[0U]==0) return;
|
|
aprsstr_Delstr(ww, 201ul, 0UL, 1UL);
|
|
if (!aprsstr_StrToInt(ww, 201ul, &maxbps)) return;
|
|
aprsstr_Extractword(w, 201ul, via0, 201ul); /* via path */
|
|
if (via0[0U]=='n') aprsstr_Delstr(via0, 201ul, 0UL, 1UL);
|
|
else via0[0U] = 0;
|
|
if (maxbps<0L) {
|
|
if (dat.type!=aprsdecode_MSG) return;
|
|
/* if neg bps send msg only */
|
|
/*WrStr(dat.msgto); WrStrLn(" msgto"); */
|
|
op = findop(dat.msgto, 1);
|
|
/*IF (op<>NIL) THEN WrStr(op^.lastrxport); WrStrLn(" opok") END; */
|
|
if ((op==0 || op->lastrxport!=(char)(outport+48UL))
|
|
|| op->lasttime+3600UL<aprsdecode_realtime) return;
|
|
}
|
|
/* user not heard on this port */
|
|
if (!Checkbps(outport-1UL, (uint32_t)labs(maxbps), 0UL,
|
|
dat.type==aprsdecode_MSG)) return;
|
|
/* -bps only msg */
|
|
useri_confstr(useri_fMYCALL, tb, 512ul);
|
|
if (aprstext_callwrong(tb, 512ul)) {
|
|
useri_xerrmsg("Gate to rf needs valid \'My Call\'", 33ul);
|
|
return;
|
|
}
|
|
aprsstr_Append(tb, 512ul, ">APLM01", 8ul);
|
|
if (via0[0U]) {
|
|
if (via0[0U]!='-') aprsstr_Append(tb, 512ul, ",", 2ul);
|
|
else if (((uint8_t)via0[1U]<'1' || (uint8_t)via0[1U]>'9')
|
|
|| via0[2U]) return;
|
|
/* not correct ssid */
|
|
aprsstr_Append(tb, 512ul, via0, 201ul);
|
|
}
|
|
aprsstr_Append(tb, 512ul, ":}", 3ul);
|
|
aprsstr_Append(tb, 512ul, dat.srcall, 9ul);
|
|
aprsstr_Append(tb, 512ul, ">", 2ul);
|
|
aprsstr_Append(tb, 512ul, dat.dstcall, 9ul);
|
|
aprsstr_Append(tb, 512ul, ",TCPIP,", 8ul);
|
|
aprsstr_Append(tb, 512ul, dat.viacalls[dat.igatep], 9ul);
|
|
aprsstr_Append(tb, 512ul, "*:", 3ul);
|
|
i = dat.payload;
|
|
j = aprsstr_Length(tb, 512ul);
|
|
while (((i<=511UL && b[i]) && b[i]!='\015') && j<511UL) {
|
|
tb[j] = b[i];
|
|
++j;
|
|
++i;
|
|
}
|
|
tb[j] = 0;
|
|
if (i-dat.payload>200UL) return;
|
|
/* frame too long */
|
|
w[0] = 0;
|
|
digi(tb, 0, outport, 0, 1, nomovetime, radius, w, 201ul, &sentbytes);
|
|
if (sentbytes>0L) {
|
|
ok0 = Checkbps(outport-1UL, (uint32_t)labs(maxbps),
|
|
(uint32_t)sentbytes, 0); /* sum up txbytes */
|
|
}
|
|
} /* end digitorf() */
|
|
|
|
|
|
static void digipeat(const aprsdecode_FRAMEBUF b, uint32_t udpch)
|
|
{
|
|
uint32_t line;
|
|
uint32_t outport;
|
|
uint32_t radius;
|
|
int32_t sentbytes;
|
|
uint32_t nomovetime;
|
|
char directonly;
|
|
char appendrest;
|
|
char words[201];
|
|
char word[11];
|
|
char cin;
|
|
char c;
|
|
line = 0UL;
|
|
for (;;) {
|
|
useri_confstrings(useri_fDIGI, line, 0, words, 201ul);
|
|
if (words[0U]==0) break;
|
|
cin = words[0U]; /* input port */
|
|
if ((cin=='*' && udpch>0UL || cin==(char)(udpch+48UL))
|
|
|| cin=='N' && udpch==0UL) {
|
|
/* input port, 0 is from net */
|
|
c = words[1U]; /* output port */
|
|
if ((uint8_t)c>='1') outport = (uint32_t)(uint8_t)c-48UL;
|
|
else outport = 0UL;
|
|
directonly = 1;
|
|
appendrest = 0;
|
|
switch ((unsigned)words[2U]) { /* direct/delpath */
|
|
case '1':
|
|
appendrest = 1;
|
|
break;
|
|
case '2':
|
|
directonly = 0;
|
|
break;
|
|
case '3':
|
|
directonly = 0;
|
|
appendrest = 1;
|
|
break;
|
|
} /* end switch */
|
|
aprsstr_Extractword(words, 201ul, word, 11ul);
|
|
aprsstr_Extractword(words, 201ul, word, 11ul);
|
|
if (aprsstr_StrToCard(word, 11ul, &nomovetime)) {
|
|
aprsstr_Extractword(words, 201ul, word, 11ul);
|
|
if (aprsstr_StrToCard(word, 11ul, &radius)) {
|
|
if (cin=='N') {
|
|
digitorf(b, outport, nomovetime, radius, -5L, words,
|
|
201ul);
|
|
}
|
|
else if (udpch>0UL) {
|
|
digi(b, 1, outport, directonly, appendrest, nomovetime,
|
|
radius, words, 201ul, &sentbytes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
++line;
|
|
}
|
|
} /* end digipeat() */
|
|
|
|
#define aprsdecode_PURGEINTERVALL 10
|
|
/* seconds+1 with no purge */
|
|
|
|
|
|
static void storedata(aprsdecode_FRAMEBUF mb, aprsdecode_pTCPSOCK cp,
|
|
uint32_t udpch, const struct UDPSET modeminfo,
|
|
char valid, char local)
|
|
{
|
|
int32_t res;
|
|
char fn[1000];
|
|
char s[21];
|
|
aprsdecode_MONCALL server;
|
|
char tabchk;
|
|
char ok0;
|
|
aprsdecode_pTCPSOCK tp;
|
|
struct aprsdecode_DAT dat;
|
|
char dir;
|
|
uint32_t otime;
|
|
char tmp;
|
|
if (aprsdecode_lastpurge!=aprsdecode_realtime/10UL) {
|
|
if (aprsdecode_lums.logmode) {
|
|
aprsdecode_purge(&aprsdecode_ophist2,
|
|
aprsdecode_realtime-aprsdecode_lums.purgetime,
|
|
aprsdecode_realtime-aprsdecode_lums.purgetimeobj);
|
|
}
|
|
else {
|
|
aprsdecode_purge(&aprsdecode_ophist0,
|
|
aprsdecode_realtime-aprsdecode_lums.purgetime,
|
|
aprsdecode_realtime-aprsdecode_lums.purgetimeobj);
|
|
}
|
|
aprsdecode_lastpurge = aprsdecode_realtime/10UL;
|
|
}
|
|
if (cp) memcpy(server,cp->user.call,9u);
|
|
else server[0UL] = 0;
|
|
/*WrInt(rxidle, 15); WrInt(lastlooped+IGATEMAXDELAY, 15);
|
|
WrInt(time(), 15); WrStrLn(" ig"); */
|
|
if (local) res = 0L;
|
|
else if (aprsdecode_rxidle>=3UL && aprsdecode_lastlooped+5UL>=osic_time())
|
|
{
|
|
/* not too long delayd data */
|
|
digipeat(mb, udpch);
|
|
res = AprsIs(mb, 512ul, 6UL, server, 9ul, udpch, valid,
|
|
useri_configon(useri_fMUSTBECALL), &tabchk);
|
|
if (((res>=0L && useri_configon(useri_fALLOWGATE)) && !tabchk)
|
|
&& udpch>0UL) {
|
|
useri_confstr(useri_fALLOWGATE, s, 21ul);
|
|
if (aprsstr_InStr(s, 21ul,
|
|
(char *)(tmp = (char)(udpch+48UL),&tmp), 1u/1u)>=0L) {
|
|
tp = aprsdecode_tcpsocks;
|
|
while (tp) {
|
|
if (tp->lastping>0UL && (tp->waitpong==1U && tp->lastping+10UL<aprsdecode_realtime || tp->waitpong>1U)
|
|
) {
|
|
if (tp->lastpong>0UL) {
|
|
saylinkbad((int32_t)(aprsdecode_realtime-tp->lastpong)
|
|
);
|
|
}
|
|
useri_xerrmsg("Ping-Timeout, Rf to AprsIs transfer stopped \
|
|
temporarily", 56ul);
|
|
}
|
|
else ok0 = Sendtcp(tp, mb);
|
|
tp = tp->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* delayed */
|
|
res = 0L;
|
|
if (aprsdecode_verb) {
|
|
osi_WrStrLn("---discarded delayed digpeat-frame", 35ul);
|
|
}
|
|
}
|
|
otime = 0UL;
|
|
if (aprsdecode_verb && udpch>0UL) {
|
|
osic_WrINT32((uint32_t)res, 3UL);
|
|
osi_WrStr(" udp ", 6ul);
|
|
osi_WrStrLn(mb, 512ul);
|
|
}
|
|
if (res>=0L && aprsdecode_Decode(mb, 512ul, &dat)>=0L) {
|
|
if (udpch>0UL) dat.lastrxport = (char)(udpch+48UL);
|
|
else dat.lastrxport = 'N';
|
|
if (dat.type==aprsdecode_MSG) {
|
|
if (udpch>0UL) getmessage(0, udpch, dat);
|
|
else getmessage(cp, 0UL, dat);
|
|
}
|
|
if (aprsdecode_lums.logmode) {
|
|
res = aprsdecode_Stoframe(&aprsdecode_ophist2, mb, 512ul,
|
|
aprsdecode_realtime, 0, &otime, dat);
|
|
}
|
|
else {
|
|
res = aprsdecode_Stoframe(&aprsdecode_ophist0, mb, 512ul,
|
|
aprsdecode_realtime, 0, &otime, dat);
|
|
}
|
|
if (!local) {
|
|
if (useri_configon(useri_fLOGWFN)) {
|
|
useri_confstr(useri_fLOGWFN, fn, 1000ul);
|
|
aprstext_logfndate(aprsdecode_realtime, fn, 1000ul);
|
|
if (!wrlog(mb, 512ul, aprsdecode_realtime, fn, 1000ul, res)) {
|
|
poplogerr(fn, 1000ul);
|
|
}
|
|
}
|
|
if (aprspos_posvalid(dat.pos) && useri_configon(useri_fAPPROXY)) {
|
|
approxywarn(dat.pos, dat.symcall, 9ul);
|
|
}
|
|
}
|
|
}
|
|
if (res==-2L) {
|
|
dir = '#';
|
|
}
|
|
else if (res<0L) dir = '-';
|
|
else dir = '>';
|
|
if (udpch>0UL) wrmon(udpch, dir, modeminfo, otime, mb, 512ul);
|
|
else wrmon(0UL, dir, modeminfo, otime, mb, 512ul);
|
|
} /* end storedata() */
|
|
|
|
|
|
extern void aprsdecode_drawbeacon(char raw[], uint32_t raw_len)
|
|
{
|
|
aprsdecode_FRAMEBUF b;
|
|
char port;
|
|
uint32_t time0;
|
|
struct UDPSET modeminfo;
|
|
aprsstr_Assign(b, 512ul, raw, raw_len);
|
|
if (getbeaconparm(b, 512ul, &time0, &port)) {
|
|
beaconmacros(b, 512ul, "", 1ul, "", 1ul, 1);
|
|
if (b[0UL]) {
|
|
memset((char *) &modeminfo,(char)0,sizeof(struct UDPSET));
|
|
storedata(b, 0, 0UL, modeminfo, 0, 1);
|
|
if (aprsdecode_lums.logmode) {
|
|
useri_say("drawn to Realtime Data not to imported Log!", 44ul,
|
|
5UL, 'r');
|
|
}
|
|
else if (aprsdecode_click.mhop[0UL]) {
|
|
useri_say("switch to \"show all\" to see new object", 39ul, 5UL,
|
|
'r');
|
|
}
|
|
}
|
|
}
|
|
else useri_xerrmsg("decode error", 13ul);
|
|
aprsdecode_tracenew.winevent = 2000UL;
|
|
} /* end drawbeacon() */
|
|
|
|
static aprsstr_GHOSTSET _cnst2 = {0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
|
|
0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,0xFFFFFFFFUL,
|
|
0xFFFFFFFFUL,0x00000001UL};
|
|
static aprsstr_GHOSTSET _cnst1 = {0x00000000UL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL,0x00000000UL,0x00000000UL,0x00000000UL,
|
|
0x00000000UL,0x00000000UL};
|
|
|
|
static void getghostset(uint32_t port, aprsstr_GHOSTSET g)
|
|
{
|
|
uint32_t n;
|
|
uint32_t i;
|
|
char s[11];
|
|
char p;
|
|
p = (char)(port+49UL);
|
|
memcpy(g,_cnst1,36u);
|
|
i = 0UL;
|
|
for (;;) {
|
|
useri_conf2str(useri_fFINGERPRINT, i, s, 11ul);
|
|
if (s[0U]==0) break;
|
|
if (s[0U]==p) {
|
|
if (s[1U]==':') {
|
|
aprsstr_Delstr(s, 11ul, 0UL, 2UL);
|
|
if (aprsstr_StrToCard(s, 11ul, &n) && n<=256UL) {
|
|
X2C_INCL(g,n,257);
|
|
}
|
|
}
|
|
else if (s[1U]==0) memcpy(g,_cnst2,36u);
|
|
}
|
|
++i;
|
|
}
|
|
} /* end getghostset() */
|
|
|
|
|
|
extern void aprsdecode_udpin(uint32_t port)
|
|
{
|
|
aprsdecode_FRAMEBUF mbuf;
|
|
struct UDPSET modeminfo;
|
|
aprsstr_GHOSTSET gs;
|
|
struct aprsdecode_UDPSOCK * anonym;
|
|
getghostset(port, gs);
|
|
while (getudp(port, mbuf, &modeminfo, gs)) {
|
|
if (mbuf[0UL]) {
|
|
{ /* with */
|
|
struct aprsdecode_UDPSOCK * anonym = &aprsdecode_udpsocks0[port];
|
|
|
|
anonym->lastudprx = aprsdecode_realtime;
|
|
++anonym->rxframes;
|
|
anonym->rxbytes += aprsstr_Length(mbuf, 512ul);
|
|
if (anonym->starttime==0UL) {
|
|
anonym->starttime = aprsdecode_realtime;
|
|
}
|
|
}
|
|
aprsdecode_lastanyudprx = aprsdecode_realtime;
|
|
storedata(mbuf, 0, port+1UL, modeminfo, 0, 0);
|
|
}
|
|
else if (aprsdecode_verb) osi_WrStrLn("axudp decode error", 19ul);
|
|
}
|
|
} /* end udpin() */
|
|
|
|
|
|
extern int32_t aprsdecode_tcpout(aprsdecode_pTCPSOCK acttcp)
|
|
{
|
|
int32_t i;
|
|
int32_t res;
|
|
struct aprsdecode_TCPSOCK * anonym;
|
|
int32_t tmp;
|
|
if ((int32_t)acttcp->fd>=0L) {
|
|
{ /* with */
|
|
struct aprsdecode_TCPSOCK * anonym = acttcp;
|
|
res = sendsock(anonym->fd, anonym->tbuf, anonym->tlen);
|
|
if (res>0L) {
|
|
tmp = anonym->tlen-1L;
|
|
i = res;
|
|
if (i<=tmp) for (;; i++) {
|
|
anonym->tbuf[i-res] = anonym->tbuf[i];
|
|
if (i==tmp) break;
|
|
} /* end for */
|
|
anonym->tlen -= res;
|
|
if (anonym->connt==0UL) {
|
|
anonym->connt = aprsdecode_realtime;
|
|
wrconnected(acttcp);
|
|
}
|
|
anonym->watchtime = aprsdecode_realtime;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/* ELSE tlen:=0; (* should not happen *) */
|
|
res = -1L;
|
|
}
|
|
return res;
|
|
} /* end tcpout() */
|
|
|
|
|
|
extern void aprsdecode_tcpin(aprsdecode_pTCPSOCK acttcp)
|
|
{
|
|
int32_t res;
|
|
aprsdecode_FRAMEBUF mbuf;
|
|
struct UDPSET modeminfo;
|
|
if ((int32_t)acttcp->fd>=0L) {
|
|
for (;;) {
|
|
res = Gettcp(acttcp->fd, mbuf, acttcp->rbuf, &acttcp->rpos);
|
|
/*WrInt(res, 1);WrStrLn(" gettcp"); */
|
|
if (res<0L) {
|
|
/*WrStrLn("closesock"); */
|
|
osic_CloseSock(acttcp->fd);
|
|
acttcp->fd = -1L;
|
|
break;
|
|
}
|
|
if (res<=0L) break;
|
|
++acttcp->rxframes;
|
|
acttcp->rxbytes += aprsstr_Length(mbuf, 512ul);
|
|
acttcp->watchtime = aprsdecode_realtime;
|
|
/* WrMon(mbuf); */
|
|
if (mbuf[0UL]=='#') getpong(acttcp, mbuf, 512ul);
|
|
memset((char *) &modeminfo,(char)0,sizeof(struct UDPSET));
|
|
storedata(mbuf, acttcp, 0UL, modeminfo, 1, 0);
|
|
aprsdecode_lasttcprx = aprsdecode_realtime;
|
|
}
|
|
}
|
|
} /* end tcpin() */
|
|
|
|
|
|
extern void aprsdecode_initparms(void)
|
|
{
|
|
uint32_t i;
|
|
struct aprsdecode__D1 * anonym;
|
|
initcrc12();
|
|
memset((char *)aprsdecode_gateways,(char)0,
|
|
sizeof(struct aprsdecode__D3 [10]));
|
|
memset((char *)aprsdecode_udpsocks0,(char)0,
|
|
sizeof(struct aprsdecode_UDPSOCK [4]));
|
|
for (i = 0UL; i<=3UL; i++) {
|
|
aprsdecode_udpsocks0[i].fd = -1L;
|
|
} /* end for */
|
|
connecttime = 0UL;
|
|
cycleservers = 0UL;
|
|
logframename[0UL] = 0;
|
|
logframes = 6L;
|
|
aprsdecode_testbeaconbuf[0UL] = 0;
|
|
/* servercall[0]:=0C; */
|
|
/* passwd[0]:=0C; */
|
|
/* igatedelay:=TRUE; */
|
|
rfbeacont = 0UL;
|
|
qas = 0UL;
|
|
qasc = 0UL;
|
|
aprsdecode_initxsize = 0L;
|
|
aprsdecode_initysize = 0L;
|
|
aprsdecode_initzoom = 0L;
|
|
aprsdecode_finezoom = 1.0f;
|
|
aprsdecode_posinval(&aprsdecode_mappos);
|
|
aprsdecode_spikesens = 2.0f;
|
|
aprsdecode_maxhop = 100.0f;
|
|
maxspeed = 1000.0f;
|
|
nextbeep = 0UL;
|
|
{ /* with */
|
|
struct aprsdecode__D1 * anonym = &aprsdecode_lums;
|
|
anonym->map = 350L;
|
|
anonym->rfbri = 350L;
|
|
anonym->track = 1000L;
|
|
anonym->waypoint = 800L;
|
|
anonym->sym = 1000L;
|
|
anonym->obj = 1000L;
|
|
anonym->text = 750L;
|
|
anonym->nomov = 90L;
|
|
anonym->maxdim = 3600UL;
|
|
anonym->firstdim = 82800UL;
|
|
anonym->purgetime = 90000UL;
|
|
anonym->purgetimeobj = 90000UL;
|
|
anonym->dupemaxtime = 10800UL;
|
|
anonym->fps = 0L;
|
|
/* mapmode:=REFLATER; */
|
|
strncpy(anonym->mapname,"tiles",41u);
|
|
anonym->maplumcorr = -128L;
|
|
anonym->gamma = 2.2f;
|
|
anonym->centering = 40L;
|
|
anonym->movestep = 10UL;
|
|
strncpy(anonym->configfn,"aprsmap.cfg",257u);
|
|
anonym->wxcol = 0;
|
|
}
|
|
aprsdecode_lastpurge = 0UL;
|
|
aprsdecode_lastanyudprx = 0UL;
|
|
aprsdecode_lasttcprx = 0UL;
|
|
strncpy(aprsdecode_mapdir,"osm",1025u);
|
|
parms();
|
|
aprsdecode_ophist0 = 0;
|
|
aprsdecode_ophist2 = 0;
|
|
aprsdecode_txmessages = 0;
|
|
aprsdecode_msgfifo0 = 0;
|
|
msgmid = 0UL;
|
|
aprsdecode_realtime = osic_time();
|
|
uptime = aprsdecode_realtime;
|
|
trygate = 0UL;
|
|
dupetime = 60UL;
|
|
ungate[0U][0] = 0;
|
|
strncpy(ungate[1U],"NOGATE",9u);
|
|
strncpy(ungate[2U],"RFONLY",9u);
|
|
strncpy(ungate[3U],"TCPIP",9u);
|
|
strncpy(ungate[4U],"TCPXX",9u);
|
|
strncpy(ungate[5U],"q",9u);
|
|
ungate[6U][0] = 0;
|
|
aprsdecode_tcpsocks = 0;
|
|
Stopticker();
|
|
tickertime = 0UL;
|
|
sentemptymsg = 0;
|
|
beaconrandomstart = osic_time();
|
|
/* set a beacon scheduler start second in minute */
|
|
beaconrandomstart = (beaconrandomstart/60UL)%60UL+(beaconrandomstart%60UL)
|
|
*60UL;
|
|
} /* end initparms() */
|
|
|
|
|
|
extern void aprsdecode_BEGIN(void)
|
|
{
|
|
static int aprsdecode_init = 0;
|
|
if (aprsdecode_init) return;
|
|
aprsdecode_init = 1;
|
|
if (sizeof(aprsdecode_SET256)!=32) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_MONCALL)!=9) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_FRAMEBUF)!=512) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_WWWB)!=1401) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_FILENAME)!=1024) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_DUPETIMES)!=262144) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_MSGTEXT)!=67) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_ACKTEXT)!=5) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_ACKREPTEXT)!=2) X2C_ASSERT(0);
|
|
if (sizeof(uint8_t)!=1) X2C_ASSERT(0);
|
|
if (sizeof(uint8_t)!=1) X2C_ASSERT(0);
|
|
if (sizeof(uint16_t)!=2) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_TELEMETRY)!=14) X2C_ASSERT(0);
|
|
if (sizeof(uint16_t)!=2) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_MAPNAME)!=41) X2C_ASSERT(0);
|
|
if (sizeof(aprsdecode_SYMBOLSET)!=24) X2C_ASSERT(0);
|
|
if (sizeof(CHSET)!=16) X2C_ASSERT(0);
|
|
if (sizeof(TICKERCALL)!=31) X2C_ASSERT(0);
|
|
aprstext_BEGIN();
|
|
useri_BEGIN();
|
|
aprspos_BEGIN();
|
|
aprsstr_BEGIN();
|
|
osi_BEGIN();
|
|
xosi_BEGIN();
|
|
}
|
|
|