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

Last change on this file since 386 was 345, checked in by smoser, 10 years ago

apply copyright

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