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

Last change on this file since 310 was 296, checked in by smoser, 11 years ago

Update Copyright, fix encoding issue

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