source: core/trunk/client/flarmclient.pl @ 223

Last change on this file since 223 was 223, checked in by smoser, 12 years ago

#139

  • Property svn:mime-type set to text/plain
File size: 5.4 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 POSIX qw(strftime);
28use POSIX qw(setsid);
29use LWP::UserAgent;
30
31my %config;
32my %options;
33my $ua;
34my $trace = 0;
35my $interval = 1;
36
37# default values
38my $log = "$ENV{'HOME'}/.flarmclient/client.trace";
39my $cfile = "$ENV{'HOME'}/.flarmclient/flarmclient.conf";
40my $fifo = "$ENV{'HOME'}/.flarmclient/client.fifo";
41
42# functions
43sub usage {
44  print <<EOF;
45NAME
46  $0 -- stream flarm data to server
47
48SYNOPSIS
49  $0 [-c config_file] [-f data_file] [-h]
50
51DESCRIPTION
52  The following options are available:
53 
54  -c    Use the specified configuration file. Use the default configuration
55                file as a starting point for customization.
56               
57  -i    Interval in seconds for sending data to the server. Defaults to one
58                second.
59               
60  -f    Read the data from the specified data file. This is mainly used for
61                testing and development.
62               
63  -h    Print this help.
64
65EOF
66  exit 0;
67}
68
69# print statistic information to logfile
70$SIG{USR1} = sub {
71        if ($trace) {
72                $trace = 0;
73                close(LOG);
74        } else {
75                open(LOG, ">> $log") || print "Failed to open trace file $log: $!";
76                $trace = 1;
77        }
78};
79
80sub logit {
81        my ($level, $msg) = @_;
82        if ($trace) {
83                #print LOG localtime() . " $level $msg\n";
84                print LOG "$msg\n";
85        }
86}
87
88sub cleanup {
89        if (-e "$fifo") {
90                unlink($fifo) || die("unable to remove $fifo: $!");
91        }
92        close(LOG);
93}
94
95sub readconfig {
96        open(CONF, "< $cfile") || die("failed to open config file for reading: $!");
97        while(my $line = <CONF>) {
98                chomp($line);
99                next if $line =~ /^\s*#/;
100                next if $line =~ /^\s*$/;
101                if ($line =~ /^\s*(\S*)\s*=\s*(\S*)\s*$/) {
102                        $config{$1} = $2;
103                }
104        }
105        close(CONF);
106}
107
108# send the records to the server. We don't make a request for each record for
109# performance reasons.
110sub flush {
111        my ($records, $url) = @_;
112        logit("TRACE", $records);
113        my $date = `date -u +%Y/%m/%d`;
114        my $resturl = $url . "/" . $date;
115        my $request = HTTP::Request->new('PUT');
116        $request->url($resturl);
117        $request->header('stationKey'=>$config{'key'});
118        $request->content(compress($records));
119        # run the request
120        my $response = $ua->request($request);
121        # analyze the response
122        my $code = $response->code;
123        $response->code == 200 || logit("ERROR", "error processing records (" . $response->code . ") records=[" . $records . "]");
124}
125
126# remove all unused records, debug information, etc.
127sub compress {
128        my ($records) = @_;
129        my $on_wire;
130        foreach my $record (split(';', $records)) {
131                if ($record =~ /^\$GPGGA,/ || $record =~ /^\$PFLAA,/) {
132                        $on_wire = (defined($on_wire)) ? $on_wire . ";" . $record : $record;
133                }               
134        }
135        return $on_wire;
136}
137
138# parse options
139getopts('c:i:f:h', \%options);
140
141# read config file
142if (defined($options{'c'})) {
143        $cfile = $options{'c'};
144}
145if (defined($options{'i'})) {
146        $interval = $options{'i'};
147}
148if (defined($options{'h'})) {
149        usage();
150}
151
152# read config file
153readconfig();
154
155# validation: key must be present in config file
156die("no key found in config file (option: key)") unless defined($config{'key'});
157
158# remove old leftovers
159cleanup();
160
161# create pipe
162die("no fifo found in config file (option: fifo)") unless defined($fifo);
163if (! -d dirname($fifo)) {
164        system("mkdir", "-p", dirname($fifo)) == 0 || die("failed to create fifo directory " . dirname($fifo) . ": $!")
165}
166system("mkfifo", $fifo) == 0 || die("failed to create fifo: $!");
167
168# force a flush right away and after every write or print
169local $| = 1;
170
171# fork minicom and write to pipe
172defined( my $pid = fork() ) or die "can't fork: $!";
173unless ($pid) {
174        # we're the child
175        # detach from session
176    setsid() or die "can't start a new session: $!";
177        close(STDIN);
178        close(STDOUT);
179        #close(STDERR);
180       
181        if (defined($options{'f'})) {
182                open(DATA, "< $options{'f'}") || die("failed to open data file $options{'f'}: $!");
183                open(FIFO, "> $fifo") || die("failed to open fifo for writing: $!");
184                while(my $line = <DATA>) {
185                        chomp($line);
186                        next if ($line =~ /^\s*$/);
187                        print FIFO $line, "\n" || die("failed to execute child command: $!");
188                }
189                close(DATA);
190                close(FIFO);
191        } else {
192                exec("minicom", "-t", "xterm-color", "-C", $fifo) == 0 || die("failed to run minicom: $!");
193        }
194        exit 0;
195}
196
197# create UserAgent object
198$ua = new LWP::UserAgent;
199my $buf;
200# read data from pipe
201open(FIFO, "< $fifo") || die("failed to open fifo for reading: $!");
202my $i = 0;
203while(my $record = <FIFO>) {
204        chomp($record);
205        $buf = (defined($buf)) ? "$buf;$record" : $record;
206        if ($record =~ /^\$GPGGA,/) {
207                flush($buf, $config{'url'}) if ($i % $interval == 0);
208                if (defined($options{'f'})) {
209                        sleep(1);
210                }
211                $buf = undef;
212                $i++;
213        }
214}
215close(FIFO);
216
217cleanup();
218exit 0;
219
Note: See TracBrowser for help on using the repository browser.