Initial commit - acarsdec-1.1, upstream vanilla version

This commit is contained in:
Tomas Suchan 2012-07-18 01:20:23 +02:00
commit 8223d9e9c8
9 changed files with 1172 additions and 0 deletions

20
Makefile Normal file
View file

@ -0,0 +1,20 @@
INCLUDES=-I.
CFLAGS= -g -O2 -Wall $(INCLUDES)
OBJS= getbits.o input.o getmesg.o main.o serv.o
acarsdec: $(OBJS)
$(CC) -o $@ $(OBJS) -lm -lsndfile -lasound
main.o: main.c version.h
clean:
rm -f *.o acarsdec
getbits.o: acarsdec.h getbits.c
getmesg.o: acarsdec.h getmesg.c
main.o: acarsdec.h main.c
input.o: acarsdec.h input.c
serv.o: acarsdec.h serv.c

69
README Normal file
View file

@ -0,0 +1,69 @@
ACARSDEC
Acarsdec is an open source, realtime ACARS demodulator and position decoder for Linux.
Aircraft Communication Addressing and Reporting System (or ACARS) is a digital datalink system for transmission of small messages between aircraft and ground stations via VHF radio.
HOW DOES IT WORK ?
To receive ACARS you need at least an AM VHF air band receiver tuned to one of these frequencies :
131.725 Europe primary
131.525 European secondary
131.550 USA primary
130.025 USA secondary
131.450 Japan primary
(these are the most common, google is your friend for other frequencies)
Audio output from this receiver is send to the soundcard input of your PC under Linux.
Then, acarsdec will demodulate the signals sent by aircrafts and print the received messages on its standart output in airnav log text format.
BUILDING IT
On a Linux system, you will need libsnd librairy, alsa audio system and gcc/make installed.
Then just type :
make
USING IT
acarsdec could be called with the following options :
acarsdec [-LR][-s noport] -d alsapcmdevice | -f sndfile
-f sndfile : decode from file sndfile (ie: a .wav file)
-d alsapcmdevice : decode from soundcard input alsapcmdevice (ie: hw:0,0)
[-LR] : diseable left or right channel decoding of stereo signal (save cpu)
[-s noport ] : "xastir" mode : act as an APRS local server, on port : noport (see below)
Input could be mono or stereo but with 48Khz sampling frequency.
If stereo, acarsdec will demod the 2 channels independantly (if no L ou R options specified)
Typical usage for realtime decoding is :
acarsdec -d hw:0
Be sure that correct record level is set for the used soundcard input.
For testing, you could try to record your receiver output at 48khz sampling frequency with any audio recording tool.
Save as wav file, then decode it by :
acarsdec -f audiofile.wav.
USING IT WITH XASTIR
acarsdec have a special output mode to use it with APRS position reporting plotting program : xastir (www.xastir.org).
In this mode, acarsdec acts as a very basic local aprsd server.
ACARS messages, and in particular, position report messages are converted to APRS format, so you can plot aircraft positions on a map.
PS: position decoding is in experimental stage. Mail me if you find errors or lack of position reporting.
start acarsdec with the following option :
acarsdec -d hw:0 -s 14000
Then in xastir, choose : Interface->Interface Control->Add
Select : Internet Server, then Add
Set Host at 127.0.0.1, Port 14000, Don't allow transmitting, then Ok.
This will add an interface in the Interface Control dialog.
Then select this interface and press start.
To check that acarsdec send messages to xastir, select View->Incoming traffic
ACARS messages look like that in xastir :
F-XXYZ>ACARS:>Fid:AFXXXX Lbl:Q0
Lots of ACARS messages are messages without position report, so be patient before seeing aircraft plotted on the map.

26
acarsdec.h Normal file
View file

@ -0,0 +1,26 @@
typedef struct {
unsigned char mode;
unsigned char addr[8];
unsigned char ack;
unsigned char label[3];
unsigned char bid;
unsigned char no[5];
unsigned char fid[7];
char txt[256];
} msg_t;
extern int initsample(char *sourcename, int src);
extern int getsample(short *sample, int nb);
extern void endsample(void);
extern void init_bits(void);
extern void resetbits(int ch);
extern int getbit(short in, unsigned char *outbits, int ch);
extern void init_mesg(void);
extern int getmesg(unsigned char r, msg_t * msg, int ch);
extern int init_serv(short port);
extern int send_mesg(msg_t *msg);
extern void end_serv(void);

192
getbits.c Normal file
View file

@ -0,0 +1,192 @@
/*
* Copyright (c) 2007 by Thierry Leconte (F4DWV)
*
* $Id: getbits.c,v 1.4 2007/04/15 15:06:54 f4dwv Exp $
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "acarsdec.h"
#define Fe 48000.0
#define Freqh 4800.0/Fe*2.0*M_PI
#define Freql 2400.0/Fe*2.0*M_PI
#define BITLEN ((int)Fe/1200)
static float h[BITLEN];
static struct bstat_s {
float hsample[BITLEN];
float lsample[BITLEN];
float isample[BITLEN];
float qsample[BITLEN];
float csample[BITLEN];
int is;
int clock;
float lin;
float phih,phil;
float dfh,dfl;
float pC,ppC;
int sgI, sgQ;
float ea;
} bstat[2];
void init_bits(void)
{
int i;
for (i = 0; i < BITLEN; i++)
h[i] = sin(2.0 * M_PI * (float) i / (float) BITLEN);
for (i = 0; i < BITLEN; i++) {
bstat[0].hsample[i] = bstat[0].lsample[i] =
bstat[0].isample[i] = bstat[0].qsample[i] =
bstat[0].csample[i] = 0.0;
bstat[1].hsample[i] = bstat[1].lsample[i] =
bstat[1].isample[i] = bstat[1].qsample[i] =
bstat[1].csample[i] = 0.0;
}
bstat[0].is = bstat[0].clock = bstat[0].sgI = bstat[0].sgQ = 0;
bstat[1].is = bstat[1].clock = bstat[1].sgI = bstat[1].sgQ = 0;
bstat[0].phih = bstat[0].phil = bstat[0].dfh = bstat[0].dfl =
bstat[0].pC = bstat[0].ppC = bstat[0].ea = 0.0;
bstat[1].phih = bstat[1].phil = bstat[1].dfh = bstat[1].dfl =
bstat[1].pC = bstat[1].ppC = bstat[1].ea = 0.0;
bstat[0].lin=bstat[1].lin=1.0;
}
void resetbits(int ch)
{
bstat[ch].sgI = bstat[ch].sgQ = 0;
}
#define VFOPLL 0.7e-3
#define BITPLL 0.2
int getbit(short sample, unsigned char *outbits, int ch)
{
int i, bt;
float in, in2;
float C;
float I, Q;
float oscl, osch;
struct bstat_s *st;
bt = 0;
st = &bstat[ch];
in = (float) sample;
st->lin = 0.003 * fabs(in) + 0.997 * st->lin;
in /= st->lin;
in2 = in * in;
st->is--;
if (st->is < 0)
st->is = BITLEN - 1;
/* VFOs */
st->phih += Freqh - VFOPLL * st->dfh;
if (st->phih >= 4.0 * M_PI)
st->phih -= 4.0 * M_PI;
st->hsample[st->is] = in2 * sin(st->phih);
for (i = 0, st->dfh = 0.0; i < BITLEN / 2; i++) {
st->dfh += st->hsample[(st->is + i) % BITLEN];
}
osch = cos(st->phih / 2.0);
st->phil += Freql - VFOPLL * st->dfl;
if (st->phil >= 4.0 * M_PI)
st->phil -= 4.0 * M_PI;
st->lsample[st->is] = in2 * sin(st->phil);
for (i = 0, st->dfl = 0.0; i < BITLEN / 2; i++) {
st->dfl += st->lsample[(st->is + i) % BITLEN];
}
oscl = cos(st->phil / 2.0);
/* mix */
st->isample[st->is] = in * (oscl + osch);
st->qsample[st->is] = in * (oscl - osch);
st->csample[st->is] = oscl * osch;
/* bit clock */
st->clock++;
if (st->clock >= BITLEN/4 + st->ea) {
st->clock = 0;
/* clock filter */
for (i = 0, C = 0.0; i < BITLEN; i++) {
C += h[i] * st->csample[(st->is + i) % BITLEN];
}
if (st->pC < C && st->pC < st->ppC) {
/* integrator */
for (i = 0, Q = 0.0; i < BITLEN; i++) {
Q += st->qsample[(st->is + i) % BITLEN];
}
if (st->sgQ == 0) {
if (Q < 0)
st->sgQ = -1;
else
st->sgQ = 1;
}
*outbits =
((*outbits) >> 1) | (unsigned
char) ((Q * st->sgQ >
0) ? 0x80 : 0);
bt = 1;
st->ea = -BITPLL * (C - st->ppC);
if(st->ea > 2.0) st->ea=2.0;
if(st->ea < -2.0) st->ea=-2.0;
}
if (st->pC > C && st->pC > st->ppC) {
/* integrator */
for (i = 0, I = 0.0; i < BITLEN; i++) {
I += st->isample[(st->is + i) % BITLEN];
}
if (st->sgI == 0) {
if (I < 0)
st->sgI = -1;
else
st->sgI = 1;
}
*outbits =
((*outbits) >> 1) | (unsigned
char) ((I * st->sgI >
0) ? 0x80 : 0);
bt = 1;
st->ea = BITPLL * (C - st->ppC);
if(st->ea > 2.0) st->ea=2.0;
if(st->ea < -2.0) st->ea=-2.0;
}
st->ppC = st->pC;
st->pC = C;
}
return bt;
}

218
getmesg.c Normal file
View file

@ -0,0 +1,218 @@
/*
* Copyright (c) 2007 by Thierry Leconte (F4DWV)
*
* $Id: getmesg.c,v 1.3 2007/03/28 06:26:05 f4dwv Exp $
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "acarsdec.h"
#define SYN 0x16
#define SOH 0x01
struct mstat_s {
enum { HEADL, HEADF, BSYNC1, BSYNC2, SYN1, SYN2, SOH1, TXT, CRC1,
CRC2, END } state;
int ind;
unsigned short crc;
char txt[243];
} mstat[2];
/* CCITT 16 CRC */
#define POLY 0x1021
static void update_crc(unsigned short *crc, unsigned char ch)
{
unsigned char v;
unsigned int i;
unsigned short flag;
v = 1;
for (i = 0; i < 8; i++) {
flag = (*crc & 0x8000);
*crc = *crc << 1;
if (ch & v)
*crc = *crc + 1;
if (flag != 0)
*crc = *crc ^ POLY;
v = v << 1;
}
}
static int build_mesg(char *txt, int len, msg_t * msg)
{
int i, k;
char r;
/* remove special chars */
for (i = 0; i < len; i++) {
r = txt[i];
if (r < ' ' && r != 0x0d && r != 0x0a)
r = 0xa4;
txt[i] = r;
}
txt[i] = '\0';
/* fill msg struct */
k = 0;
msg->mode = txt[k];
k++;
for (i = 0; i < 7; i++, k++) {
msg->addr[i] = txt[k];
}
msg->addr[7] = '\0';
/* ACK/NAK */
msg->ack = txt[k];
k++;
msg->label[0] = txt[k];
k++;
msg->label[1] = txt[k];
k++;
msg->label[2] = '\0';
msg->bid = txt[k];
k++;
k++;
for (i = 0; i < 4; i++, k++) {
msg->no[i] = txt[k];
}
msg->no[4] = '\0';
for (i = 0; i < 6; i++, k++) {
msg->fid[i] = txt[k];
}
msg->fid[6] = '\0';
strcpy(msg->txt, &(txt[k]));
return 1;
}
void init_mesg(void)
{
mstat[0].state = mstat[1].state = HEADL;
}
int getmesg(unsigned char r, msg_t * msg, int ch)
{
struct mstat_s *st;
st = &(mstat[ch]);
do {
switch (st->state) {
case HEADL:
if (r == 0xff) {
st->state = HEADF;
return 8;
}
resetbits(ch);
return 8;
break;
case HEADF:
if (r != 0xff) {
int i;
unsigned char m;
for (i = 0, m = 1; i < 7; i++, m = m << 1) {
if (!(r & m))
break;
}
if (i < 2) {
st->state = HEADL;
break;
}
st->state = BSYNC1;
st->ind = 0;
if (i != 2)
return (i - 2);
break;
}
return 6;
case BSYNC1:
if (r != 0x80 + '+')
st->ind++;
st->state = BSYNC2;
return 8;
case BSYNC2:
if (r != '*')
st->ind++;
st->state = SYN1;
return 8;
case SYN1:
if (r != SYN)
st->ind++;
st->state = SYN2;
return 8;
case SYN2:
if (r != SYN)
st->ind++;
st->state = SOH1;
return 8;
case SOH1:
if (r != SOH)
st->ind++;
if (st->ind > 2) {
st->state = HEADL;
break;
}
st->state = TXT;
st->ind = 0;
st->crc = 0;
return 8;
case TXT:
update_crc(&st->crc, r);
r = r & 0x7f;
if (r == 0x03 || r == 0x17) {
st->state = CRC1;
return 8;
}
st->txt[st->ind] = r;
st->ind++;
if (st->ind > 243) {
st->state = HEADL;
break;
}
return 8;
case CRC1:
update_crc(&st->crc, r);
st->state = CRC2;
return 8;
case CRC2:
update_crc(&st->crc, r);
st->state = END;
return 8;
case END:
st->state = HEADL;
if (st->crc == 0) {
build_mesg(st->txt, st->ind, msg);
return 0;
}
return 8;
}
} while (1);
}

166
input.c Normal file
View file

@ -0,0 +1,166 @@
/*
* Copyright (c) 2007 by Thierry Leconte (F4DWV)
*
* $Id: input.c,v 1.3 2007/03/29 16:21:49 f4dwv Exp $
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdlib.h>
#include <sndfile.h>
#include <alsa/asoundlib.h>
#include "acarsdec.h"
static int source = 0;
static int nbch = 0;
static SNDFILE *inwav;
static int initsnd(char *filename)
{
SF_INFO infwav;
/* open wav input file */
infwav.format = 0;
inwav = sf_open(filename, SFM_READ, &infwav);
if (inwav == NULL) {
fprintf(stderr, "could not open %s\n", filename);
return (0);
}
if (infwav.samplerate != 48000) {
fprintf(stderr,
"Bad Input File sample rate: %d. Must be 48000\n",
infwav.samplerate);
return (0);
}
nbch=infwav.channels;
return (infwav.channels);
}
static snd_pcm_t *capture_handle;
static int initalsa(char *filename)
{
snd_pcm_hw_params_t *hw_params;
int err;
if ((err =
snd_pcm_open(&capture_handle, filename,
SND_PCM_STREAM_CAPTURE, 0)) < 0) {
fprintf(stderr, "cannot open audio device %s (%s)\n",
filename, snd_strerror(err));
return 0;
}
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
fprintf(stderr,
"cannot allocate hardware parameter structure (%s)\n",
snd_strerror(err));
return 0;
}
if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) {
fprintf(stderr,
"cannot initialize hardware parameter structure (%s)\n",
snd_strerror(err));
return 0;
}
if ((err =
snd_pcm_hw_params_set_access(capture_handle, hw_params,
SND_PCM_ACCESS_RW_INTERLEAVED)) <
0) {
fprintf(stderr, "cannot set access type (%s)\n",
snd_strerror(err));
return 0;
}
if ((err =
snd_pcm_hw_params_set_format(capture_handle, hw_params,
SND_PCM_FORMAT_S16)) < 0) {
fprintf(stderr, "cannot set sample format (%s)\n",
snd_strerror(err));
return 0;
}
if ((err =
snd_pcm_hw_params_set_rate(capture_handle, hw_params, 48000,
0)) < 0) {
fprintf(stderr, "cannot set sample rate (%s)\n",
snd_strerror(err));
return 0;
}
for(nbch=2;nbch>0;nbch--) {
if (snd_pcm_hw_params_set_channels(capture_handle, hw_params, nbch)==0)
break;
}
if (nbch ==0) {
fprintf(stderr, "cannot set number of channels\n");
return 0;
}
if ((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0) {
fprintf(stderr, "cannot set parameters (%s)\n",
snd_strerror(err));
return 0;
}
snd_pcm_hw_params_free(hw_params);
if ((err = snd_pcm_prepare(capture_handle)) < 0) {
fprintf(stderr,
"cannot prepare audio interface for use (%s)\n",
snd_strerror(err));
return 0;
}
return nbch;
}
/* open input source*/
int initsample(char *sourcename, int src)
{
source = src;
if (src)
return initsnd(sourcename);
else
return initalsa(sourcename);
}
int getsample(short *sample, int nb)
{
int r;
if (source) {
r = sf_read_short(inwav, sample, nb);
if (r == 0)
r = -1; /* this is the end */
} else {
r = snd_pcm_readi(capture_handle, sample, nb/nbch);
if (r <= 0)
fprintf(stderr,
"cannot read from interface (%s)\n",
snd_strerror(r));
r=r*nbch;
}
return r;
}
void endsample(void)
{
if (source)
sf_close(inwav);
else
snd_pcm_close(capture_handle);
}

177
main.c Normal file
View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2007 by Thierry Leconte (F4DWV)
*
* $Id: main.c,v 1.5 2007/04/22 16:14:41 f4dwv Exp $
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "version.h"
#include "acarsdec.h"
extern int optind, opterr;
extern char *optarg;
static void usage(void)
{
fprintf(stderr, "Usage: acarsdec [-LR][-s noport] -d alsapcmdevice | -f sndfile \n");
fprintf(stderr, " -f sndfile :\t\tdecode from file sndfile (ie: a .wav file)\n");
fprintf(stderr, " -d alsapcmdevice :\tdecode from soundcard input alsapcmdevice (ie: hw:0,0)\n");
fprintf(stderr, " [-LR] :\t\tdiseable left or right channel decoding of stereo signal\n");
fprintf(stderr, " [-s noport ] :\t\tact as an APRS local server, on port : noport\n");
fprintf(stderr, "Input could be mono or stereo but with 48Khz sampling frequency.\nIf stereo, acarsdec will demod the 2 channels independantly (if no L ou R options specified)\n\n");
exit(1);
}
void print_mesg(msg_t * msg)
{
time_t t;
struct tm *tmp;
char pos[128];
printf("ACARS mode: %c", msg->mode);
printf(" Aircraft reg: %s\n", msg->addr);
printf("Message label: %s", msg->label);
printf(" Block id: %d", (int) msg->bid);
printf(" Msg. no: %s\n", msg->no);
printf("Flight id: %s\n", msg->fid);
printf("Message content:-\n%s", msg->txt);
if (posconv(msg->txt, msg->label, pos)==0)
printf("\nAPRS : Addr:%s Fid:%s Lbl:%s pos:%s\n", msg->addr, msg->fid,msg->label,pos);
t = time(NULL);
tmp = gmtime(&t);
printf
("\n----------------------------------------------------------[%02d/%02d/%04d %02d:%02d]\n\n",
tmp->tm_mday, tmp->tm_mon + 1, tmp->tm_year + 1900,
tmp->tm_hour, tmp->tm_min);
}
int main(int argc, char **argv)
{
int c;
msg_t msgl, msgr;
unsigned char rl, rr;
int nbitl, nbitr;
int nrbitl, nrbitr;
int nbch=0;
int el=1,er=1;
short port=0;
while ((c = getopt(argc, argv, "d:f:RLs:")) != EOF) {
switch (c) {
case 'd':
nbch = initsample(optarg, 0);
break;
case 'f':
nbch = initsample(optarg, 1);
break;
case 'L':
el=0;
break;
case 'R':
er=0;
break;
case 's':
port=atoi(optarg);
break;
default:
usage();
exit(1);
}
}
if (nbch == 0) {
usage();
exit(1);
}
if(port)
if(init_serv(port)) {
exit(1);
}
/* main loop */
init_bits();
init_mesg();
nbitl = nbitr = 0;
nrbitl = nrbitr = 8;
do {
short sample[4096];
int ind, len;
len = getsample(sample, 4096);
if (len < 0)
break;
for (ind = 0; ind < len;) {
if(el) {
nbitl += getbit(sample[ind], &rl, 0);
if (nbitl >= nrbitl) {
nrbitl = getmesg(rl, &msgl, 0);
nbitl = 0;
if (nrbitl == 0) {
if(port)
send_mesg(&msgl);
else
print_mesg(&msgl);
nrbitl = 8;
}
}
}
ind++;
if (nbch >= 2) {
if(er) {
nbitr += getbit(sample[ind], &rr, 1);
if (nbitr >= nrbitr) {
nrbitr = getmesg(rr, &msgr, 1);
nbitr = 0;
if (nrbitr == 0) {
if(port)
send_mesg(&msgl);
else
print_mesg(&msgl);
nrbitr = 8;
}
}
}
ind++;
}
}
} while (1);
if(port)
end_serv();
endsample();
exit(0);
}

303
serv.c Normal file
View file

@ -0,0 +1,303 @@
/*
* Copyright (c) 2007 by Thierry Leconte (F4DWV)
*
* $Id: serv.c,v 1.2 2007/04/22 16:14:41 f4dwv Exp $
*
* This code is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include "acarsdec.h"
static int sa, sc;
int init_serv(short port)
{
struct sockaddr_in locaddr, remaddr;
socklen_t len;
char c;
int res;
sa = socket(PF_INET, SOCK_STREAM, 0);
if (sa < 0) {
fprintf(stderr, "socket : %s\n", strerror(errno));
return -1;
}
memset(&locaddr, 0, sizeof(locaddr));
locaddr.sin_family = AF_INET;
locaddr.sin_port = htons(port);
locaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
len = sizeof(locaddr);
res = bind(sa, (struct sockaddr *) &locaddr, len);
if (res) {
fprintf(stderr, "bind : %s\n", strerror(errno));
return -1;
}
res = listen(sa, 1);
if (res) {
fprintf(stderr, "listen : %s\n", strerror(errno));
return -1;
}
memset(&remaddr, 0, sizeof(remaddr));
len = sizeof(remaddr);
sc = accept(sa, (struct sockaddr *) &remaddr, &len);
if (sc < 0) {
fprintf(stderr, "accept : %s\n", strerror(errno));
return -1;
}
do {
res = read(sc, &c, 1);
} while (res == 1 && c != '\n');
return 0;
}
/* convert ACARS position reports to APRS position */
static void toaprs(int la, char lac, int ln, char lnc, int prec, char *out)
{
int lad, lnd;
float lam, lnm;
lad = la / 10000;
lnd = ln / 10000;
lam = (float) (la - (lad * 10000)) * 60.0 / 10000.0;
lnm = (float) (ln - (lnd * 10000)) * 60.0 / 10000.0;
switch (prec) {
case 0:
sprintf(out, "%02d%02.0f. %c/%03d%02.0f. %c^", lad, lam, lac, lnd, lnm, lnc);
break;
case 1:
sprintf(out, "%02d%04.1f %c/%03d%04.1f %c^", lad, lam, lac, lnd, lnm, lnc);
break;
case 2:
default:
sprintf(out, "%02d%05.2f%c/%03d%05.2f%c^", lad, lam, lac, lnd, lnm, lnc);
break;
}
}
int posconv(char *txt, unsigned char *label, char *pos)
{
char lac, lnc;
int la, ln;
char las[7], lns[7];
int n;
char *p;
/*try different heuristics */
n = sscanf(txt, "#M1BPOS%c%05d%c%063d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "#M1AAEP%c%06d%c%07d", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
toaprs(la, lac, ln, lnc, 2, pos);
return 0;;
}
if (strncmp(txt, "#M1B", 4) == 0) {
if ((p = strstr(txt, "/FPO")) != NULL) {
n = sscanf(p, "/FPO%c%05d%c%06d", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S')
&& (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
}
if ((p = strstr(txt, "/PS")) != NULL) {
n = sscanf(p, "/PS%c%05d%c%06d", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S')
&& (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
}
}
n = sscanf(txt, "FST01%*8s%c%06d%c%07d", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
toaprs(la, lac, ln, lnc, 2, pos);
return 0;;
}
n = sscanf(txt, "(2%c%5c%c%6c", &lac, las, &lnc, lns);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
las[5] = 0;
lns[6] = 0;
la = 10 * atoi(las);
ln = 10 * atoi(lns);
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "(:2%c%5c%c%6c", &lac, las, &lnc, lns);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
las[5] = 0;
lns[6] = 0;
la = 10 * atoi(las);
ln = 10 * atoi(lns);
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "(2%*4s%c%5c%c%6c", &lac, las, &lnc, lns);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
las[5] = 0;
lns[6] = 0;
la = 10 * atoi(las);
ln = 10 * atoi(lns);
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "LAT %c%3c.%3c/LON %c%3c.%3c", &lac, las, &(las[3]),
&lnc, lns, &(lns[3]));
if (n == 6 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
las[6] = 0;
lns[6] = 0;
la = 10 * atoi(las);
ln = 10 * atoi(lns);
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "#DFB(POS-%*6s-%04d%c%05d%c/", &la, &lac, &ln, &lnc);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 100;
ln *= 100;
toaprs(la, lac, ln, lnc, 0, pos);
return 0;;
}
n = sscanf(txt, "#DFB*POS\a%*8s%c%04d%c%05d/", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 100;
ln *= 100;
toaprs(la, lac, ln, lnc, 0, pos);
return 0;;
}
n = sscanf(txt, "POS%c%05d%c%06d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "POS%*2s,%c%05d%c%06d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "RCL%*2s,%c%05d%c%06d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "TWX%*2s,%c%05d%c%06d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "CLA%*2s,%c%05d%c%06d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
n = sscanf(txt, "%c%05d/%c%06d,", &lac, &la, &lnc, &ln);
if (n == 4 && (lac == 'N' || lac == 'S') && (lnc == 'E' || lnc == 'W')) {
la *= 10;
ln *= 10;
toaprs(la, lac, ln, lnc, 1, pos);
return 0;;
}
return 1;
}
int send_mesg(msg_t * msg)
{
char apstr[512];
char txt[512];
char pos[64];
unsigned char *ind;
if(msg->label[0]=='_' && msg->label[1]==0x7f)
return 0;
strcpy(txt,msg->txt);
for(ind = txt;*ind != 0 ;ind++) {
if(*ind==0x0a || *ind == 0x0d) *ind=' ';
}
ind = msg->addr;
while (*ind == '.' && *ind != 0)
ind++;
if (posconv(msg->txt, msg->label, pos))
sprintf(apstr, "%s>ACARS:>Fid:%s Lbl:%s %s\n", ind, msg->fid,msg->label,txt);
else
sprintf(apstr, "%s>ACARS:!%sFid:%s Lbl:%s %s\n", ind, pos,msg->fid,msg->label,txt);
write(sc, apstr, strlen(apstr));
return 0;
}
void end_serv(void)
{
close(sc);
close(sa);
}

1
version.h Normal file
View file

@ -0,0 +1 @@
const char version[] = "Acarsdec 1.1 (c) 2007 Thierry Leconte F4DWV";