#!/usr/bin/perl # Playing with toys is much more fun than studying some boring exam... # FIXME TODO: # * detect handovers GPRS <-> UMTS? # * detect handovers from cells?? # * other nice commands from gpsd? use strict; use Device::Modem; use POSIX qw(strftime); use Net::Telnet(); sub GetSignalQuality { my $modem = shift; my $rssi = "-"; my $ber = "-"; my $tmp = $modem->atsend( "AT+CSQ" . "\r\n" ); split '\n', $modem->answer(); $_=@_[0]; split ' '; if ($_=="+CSQ") { (my $tmp, $_) = split ' '; ($rssi, $ber) = split ','; $rssi = $rssi + 0; $ber = $ber + 0; if ($rssi==99) { $rssi = "-"; } else { $rssi = $rssi+0; $rssi = -113 + 2*$rssi; # convert rssi to dBm if ($rssi == -113) { $rssi = "<= $rssi"; } elsif ($rssi == -51) { $rssi = ">= $rssi"; } $rssi = "$rssi dBm"; } if ($ber==99) { $ber = "-"; } else { # convert ber to % bit errors, according to # www.miccom.cc/handy/handytipps/umrechnungstabelle.html my $tmp = $ber; $ber = 0.2; while ($tmp>0) { $ber=$ber*2; $tmp=$tmp-1; } if ($ber==25.6) { $ber=">12.8%" } else { $ber="<$ber%" } } } elsif ($_=="+ERROR") { print STDERR "Error while trying AT+CSQ: @_\n"; } else { print "Error: unkown response from AT+CSQ: @_\n"; } return $rssi, $ber; } sub GetRegistrations { my $modem = shift; my $base = "-"; # base network registration my $psnet = "-"; # packet switched network registration $modem->atsend("AT+CREG?" . "\r\n"); split '\n', $modem->answer(); $_=@_[0]; chomp; split ' '; if ($_=="+CREG") { (my $tmp1, $base) = split ','; $base=$base+0; } elsif ($_=="+ERROR") { print STDERR "Error while trying AT+CREG?: @_\n"; } else { print STDERR "Error unknown response from AT+CREG?: @_\n"; } $modem->atsend("AT+CGREG?" . "\r\n"); split '\n', $modem->answer(); $_=@_[0]; chomp; split ' '; if ($_=="+CGREG") { (my $tmp1, $psnet) = split ','; $psnet=$psnet+0; } elsif ($_=="+ERROR") { print STDERR "Error while trying AT+CGREG?: @_\n"; } else { print STDERR "Error unknown response from AT+CGREG?: @_\n"; } return $base, $psnet } sub GetAccessTechnology { my $modem = shift; my $at = "-"; my $prov = "-"; $modem->atsend( "AT+COPS?" . "\r\n" ); split '\n', $modem->answer(); $_=@_[0]; split ' '; if ($_=="+COPS") { (my $tmp1, $_)=split ' '; $_ = join ' ', @_; (my $tmp1, my $tmp2, $prov, $at) = split ','; if ($at == 0) { $at = "GSM"; } elsif ($at == "1") { $at = "GSM Compact"; } elsif ($at == "2") { $at = "UMTS"; } else { print STDERR "Error: unkown access technology: $at\n"; } } elsif ($_=="+ERROR") { print STDERR "Error while trying AT+COPS?: @_\n"; } else { print "Error: unkown response from AT+COPS?: @_\n"; } return $prov, $at; } sub GetGPSLocation { my $gps = shift; my $lat = "-"; my $long = "-"; my $status = "-"; my $speed = "-"; $gps->print("s"); $_=$gps->getline; chomp; s/GPSD,S=//; $status=$_; $gps->print("v"); $_=$gps->getline; chomp; ($speed) = /V=(\d+\.\d*)/; $speed=0.514444444*$speed; # convert knots to m/s $speed="$speed m/s"; $gps->print("p"); $_=$gps->getline; chomp; s/GPSD,P=//; split; $lat = @_[0]; $long = @_[1]; if ($lat eq "") { print STDERR "Error: couldn't get current location from localhost:gps\n"; } return $lat,$long,$speed,$status; } sub GpsErrorHandler { my $gps = shift; $_ = $gps->errmsg; if ($_ eq "write error: filehandle isn't open") { print STDERR "Error: couldn't communicate with gpsd! Check if gpsd is running.\n"; # try to reopen gpsd connection... perhaps user has restarted # gpsd $gps->open(Host => "localhost", Port => "gps"); } elsif (/problem connecting to/) { # open failed... do nothing } else { print STDERR "Error: $_.\n"; } } my $port = '/dev/ttyUSB2'; my $delay = 1; my $baud = 19200; my $a=shift @ARGV; while (! "$a" eq "") { $_=$a; if (/^-d/) { $delay = shift @ARGV; $delay = $delay + 0; if ($delay <= 0) { die "Error: delay time <= 0 is invalid!"; } } elsif (/^-p/) { $port = shift @ARGV; if ($port eq "") { die "Error: no port specified!"; } } $a=shift @ARGV; } my $modem = new Device::Modem(port => $port); die "Could not connect to $port!\n" unless $modem->connect( baudrate => $baud ); my $gps = new Net::Telnet(Telnetmode => 0); my @GpsArrayRef=(\&GpsErrorHandler,$gps); $gps->errmode(\@GpsArrayRef); $gps->open(Host => "localhost", Port => "gps"); # print header print "date\tGPS: lat\tlong\tspeed\tstatus\tGSM rssi\tber\toperator\tbase registration\tpacket switched registration\taccess technology\n"; while() { my $t=time(); $t=strftime "%Y-%m-%d %H:%M:%S", localtime; (my $lat, my $long, my $speed, my $gpsstatus) = GetGPSLocation($gps); (my $rssi, my $ber) = GetSignalQuality($modem); (my $operator, my $at) = GetAccessTechnology($modem); (my $basereg, my $psreg) = GetRegistrations($modem); print "$t\t$lat\t$long\t$speed\t$gpsstatus\t$rssi\t$ber\t$operator\t$basereg\t$psreg\t$at\n"; sleep $delay; }