source: core/trunk/client/adsbclient.pl @ 271

Last change on this file since 271 was 271, checked in by dominic, 11 years ago

Added ADS-B Clients

  • Property svn:executable set to *
File size: 7.6 KB
Line 
1#!/usr/bin/perl
2#-------------------------------------------------------------------------------
3# This file is part of the FLARM¨-Radar Project.
4#   
5#   Copyright 2013 Netzschmiede GmbH (http://www.netzschmiede.ch)
6#
7# Licensed under the Apache License, Version 2.0 (the "License");
8# you may not use this file except in compliance with the License.
9# You may obtain a copy of the License at
10#
11#   http://www.apache.org/licenses/LICENSE-2.0
12#
13# Unless required by applicable law or agreed to in writing, software
14# distributed under the License is distributed on an "AS IS" BASIS,
15# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16# See the License for the specific language governing permissions and
17# limitations under the License.
18#
19#   Project Website: www.flarmradar.ch
20#   Email: info@flarmradar.ch
21#-------------------------------------------------------------------------------
22
23use strict;
24use warnings;
25use Getopt::Std;
26use File::Basename;
27use Time::HiRes qw(gettimeofday);
28use POSIX qw(strftime);
29use POSIX qw(setsid);
30use LWP::UserAgent;
31
32my %config;
33my %options;
34my $ua;
35my $debug = 0;
36my $trace = 0;
37my $interval = 3;
38my $skip = 1;
39
40# default values
41my $cfile = "/etc/adsbclient.conf";
42my $log = "$ENV{'HOME'}/flarmclient.trace";
43my $fifo = "/tmp/my_fifo";
44
45# functions
46sub usage {
47  print <<EOF;
48NAME
49  $0 -- stream flarm data to server
50
51SYNOPSIS
52  $0 [-c config_file] [-d] [-f data_file] [-i n] [-j m] [-t] [-h]
53
54DESCRIPTION
55  The following options are available:
56 
57  -c    Use the specified configuration file. Use the default configuration
58                file as a starting point for customization.
59               
60  -d    Write debug information. The debug information is written to STDOUT
61                unless tracing (option -t) is turned on. With tracing switched on,
62                the debug information is written to the trace file (see below).                 
63               
64  -f    Read the data from the specified data file. This is mainly used for
65                testing and development.
66
67  -i    Bundle records, send a request to the server every i-th GPGGA record.
68                Used for bandwidth optimization. Defaults to 3.
69               
70  -j    Send every j-th record to the server. Used for bandwidth
71                optimization. Defaults to 1.
72               
73  -t    Trace client operations. A trace file is created in
74                \$HOME/flarmclient.trace
75                WARNING: Do not use that in Production, the trace file is not truncated
76                and might fill up the file system.
77               
78  -h    Print this help.
79
80EOF
81  exit 0;
82}
83
84# print statistic information to logfile
85$SIG{USR1} = sub {
86        if ($trace) {
87                $trace = 0;
88        } else {
89                $trace = 1;
90        }
91};
92
93
94sub openlog {
95        if (tell(LOG) == -1) {
96                open(LOG, ">> $log") || print "Failed to open trace file $log: $!";
97        }
98        return 1;
99}
100
101sub logit {
102        my ($target, $msg) = @_;
103        if ($trace && $target eq "TRACE") {
104                openlog() && print LOG "$msg\n";
105        }
106        if ($debug && $target eq "DEBUG") {
107                print "$msg\n";
108                # if tracing is turned on, write debug messages also to the trace file
109                if ($trace) {
110                        openlog() && print LOG "$msg\n";
111                } 
112        }
113        if ($target eq "ALL") {
114                print "$msg\n";
115                # if tracing is turned on, write debug messages also to the trace file
116                if ($trace) {
117                        openlog() && print LOG "$msg\n";
118                } 
119        }
120}
121
122sub cleanup {
123        if (-e "$fifo") {
124                # print "$fifo vorhanden\n"
125                # unlink($fifo) || die("unable to remove $fifo: $!");
126        }
127        close(LOG);
128}
129
130sub readconfig {
131        open(CONF, "< $cfile") || die("failed to open config file for reading: $!");
132        while(my $line = <CONF>) {
133                chomp($line);
134                next if $line =~ /^\s*#/;
135                next if $line =~ /^\s*$/;
136                if ($line =~ /^\s*(\S*)\s*=\s*(\S*)\s*$/) {
137                        $config{$1} = $2;
138                }
139        }
140        close(CONF);
141}
142
143sub exact_time {
144        return strftime("%H:%M:%S", localtime()) . "." . (gettimeofday())[1];
145}
146
147# send the records to the server. We don't make a request for each record for
148# performance reasons.
149sub flush {
150        my ($records, $url) = @_;
151        # print "$records\n";
152        logit("DEBUG", exact_time() . " Start flushing data to server");
153       
154        my $date = `date -u +%Y/%m/%d`;
155        chomp($date);
156        my $resturl = $url . "/" . $date;
157        logit("DEBUG", exact_time() . " Request resource: " . $resturl);
158       
159        # compose the request
160        my $request = HTTP::Request->new('PUT');
161        $request->url($resturl);
162        $request->header('stationKey'=>$config{'key'});
163        my $content = compress($records);
164        logit("DEBUG", exact_time() . " Put on wire: " . $content);
165        $request->content($content);
166        # print "Content: $request\n";
167        # print "Records: $records\n";
168       
169        # run the request
170        logit("DEBUG", exact_time() . " Start server push");
171        my $response = $ua->request($request);
172        logit("DEBUG", exact_time() . " End server push");
173       
174        # analyze the response
175        my $code = $response->code;
176        $response->code == 200 || logit("DEBUG", "Error processing records (" . $response->code . ") records=[" . $records . "]");
177        logit("DEBUG", exact_time() . " End flushing data");
178        # print "Data flushing done.\n";
179}
180
181# remove all unused records, debug information, etc.
182sub compress {
183        my ($records) = @_;
184        my $on_wire;
185        foreach my $record (split(';', $records)) {
186                # print "$record\n";
187                if ($record =~ /^\$GPGGA,/ || $record =~ /^\$PFLAA,/) {
188                        $on_wire = (defined($on_wire)) ? $on_wire . ";" . $record : $record;
189                }               
190        }
191        return $on_wire;
192}
193
194# remove old leftovers
195cleanup();
196
197# parse options
198getopts('c:di:j:f:th', \%options);
199
200# read config file
201if (defined($options{'c'})) {
202        $cfile = $options{'c'};
203}
204if (defined($options{'d'})) {
205        $debug = 1;
206}
207if (defined($options{'i'})) {
208        $interval = $options{'i'};
209}
210if (defined($options{'j'})) {
211        $skip = $options{'j'}
212}
213if (defined($options{'h'})) {
214        usage();
215}
216if (defined($options{'t'})) {
217        $trace = 1;
218}
219
220# read config file
221readconfig();
222
223# validation: key must be present in config file
224die("no key found in config file " . $cfile . " (option: key)") unless defined($config{'key'});
225
226logit("ALL", "Start client, connect to " . $config{'url'});
227
228# create pipe
229die("no fifo found in config file (option: fifo)") unless defined($fifo);
230if (! -d dirname($fifo)) {
231        # system("mkdir", "-p", dirname($fifo)) == 0 || die("failed to create fifo directory " . dirname($fifo) . ": $!")
232}
233# system("mkfifo", $fifo) == 0 || die("failed to create fifo: $!");
234# print "mkfifo erfolgreich\n";
235# force a flush right away and after every write or print
236local $| = 1;
237
238# let the kernel raper dead childs
239$SIG{CHLD} = 'IGNORE';
240
241#fork minicom and write to pipe
242#defined( my $pid = fork() ) or die "can't fork: $!";
243#unless ($pid) {
244        # we're the child
245        # detach from session
246#    setsid() or die "can't start a new session: $!";
247#    close(STDIN);
248#       close(STDOUT);
249#       close(STDERR);
250       
251#       if (defined($options{'f'})) {
252#               open(DATA, "< $options{'f'}") || die("failed to open data file $options{'f'}: $!");
253#               open(FIFO, "> $fifo") || die("failed to open fifo for writing: $!");
254#               while(my $line = <DATA>) {
255#                       chomp($line);
256#                       next if ($line =~ /^\s*$/);
257#                       print FIFO $line, "\n" || die("failed to execute child command: $!");
258#               }
259#               close(DATA);
260#               close(FIFO);
261#       } else {
262#               exec("exec minicom -t xterm-color -C $fifo> /dev/null 2>&1") == 0 || die("failed to run minicom: $!");
263#       }
264#       exit 0;
265#}
266
267# create UserAgent object
268$ua = new LWP::UserAgent;
269my $buf;
270# read data from pipe
271open(FIFO, "< $fifo") || die("failed to open fifo for reading: $!");
272my $i = 0;
273while(my $record = <FIFO>) {
274        # print "Read data from pipe\n";
275        # send only n-th record to the server (option -s)
276        if ($i % $skip == 0) {
277                chomp($record);
278                logit("TRACE", $record);
279                $buf = (defined($buf)) ? "$buf;$record" : $record;
280        }
281       
282        # a GPGGA record terminates the sequence
283        if ($record =~ /^\$GPGGA,/) {
284                if ($i % ($interval * $skip) == 0) {
285                        #print "Flushing ...\n";
286                        flush($buf, $config{'url'}) ;
287                        $buf = undef;
288                        sleep($interval * $skip) if (defined($options{'f'})); 
289                }
290               
291                $i++;
292        }
293}
294close(FIFO);
295
296cleanup();
297exit 0;
298
Note: See TracBrowser for help on using the repository browser.