#!/usr/bin/perl # $Id$ # -*- perl -*- vim:set ft=perl sw=4 sts=4: # Monitors a bluetooth mobile phone for calls. You'll need to bind rfcomm1 to # your mobile phone's SP service. You'll also need my Device::Nokia module # (the name is misleading, it's not Nokia specific). use strict; use Device::Nokia; my $number; my %status; my $quiton; my $daemonize; my $last=0; my $gsm = new Device::Nokia( port => '/dev/rfcomm1', log => 'file,/dev/null'); $SIG{INT} = 'death'; $SIG{TERM} = 'death'; $SIG{QUIT} = 'death'; sub initialize { my $gsm=shift; $gsm->connect() || return 0; $gsm->atsend( 'AT+CLIP=1' . Device::Modem::CR ); $gsm->answer(); return 1; } initialize($gsm) || die "Could not initialize modem: $!"; while($_=shift) { $daemonize=1 if ($_ eq "-d"); $quiton=1 if ($_ eq "-b"); } daemonize() if $daemonize; $|=1; while(1) { %status=("is_active"=>1); while($status{"is_active"} ne 0) { for(my $i=0;$i<3;$i++) { sleep 1; $number = wait_for_ring(); if($number) { $status{"number"} = $number; output_status(%status); ring($number); last; } elsif(!defined($number)) { $status{"is_active"}=0; last; }; } my %newstatus=gather_data($gsm); ring() if($newstatus{"call"}!=0 && $status{"call"}==0 && !$status{"number"}); foreach (keys %newstatus) { $status{$_} = $newstatus{$_} if(defined ($newstatus{$_})); } undef $status{"number"} if (!$number && $status{"callsetup"}==0 && $status{"call"}==0); output_status(%status); if ($status{"source"}==0 && $status{"callsetup"}==0 && $status{"call"}==0 && $quiton) { death() if(time-$last>600); } elsif ($quiton) { $last=time; } } $gsm->disconnect(); output_status(is_active => 0); do {sleep (60-30*$quiton);} until(initialize($gsm)); } sub wait_for_ring { local $_; eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 5; $_ = $gsm->answer("\\+CLIP: \"[0-9]+\",[0-9]+\$", 30); alarm 0 }; if($@) { die unless $@ eq "alarm\n"; return undef; } else { m/CLIP: "([0-9]+)",/; return "$1"; } } sub ring { system($ENV{"HOME"} . "/bin/phone-call " . $_[0]); } sub gather_data { my %data; my $gsm=shift; eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 15; %data=$gsm->indicators(); my ($first, $second) = $gsm->battery_strength(); $data{"source"}=$first; #$data{"battery"}=$second; ($first, $second) = $gsm->signal_quality(); $data{"signal"}=$first; alarm 0; }; if($@) { die unless $@ eq "alarm\n"; return (is_active => 0); } else { $data{"is_active"}=$gsm->is_active() && $data{"signal"} && 1 || 0; return %data; } } sub output_status { my %status = @_; open STATUS, ">/tmp/.phone-status.new" || die $!; foreach my $indicator (sort keys %status) { print STATUS "$indicator=" . $status{$indicator} . "\n"; }; close STATUS; rename "/tmp/.phone-status.new", "/tmp/.phone-status" || die $!; } sub daemonize { chdir "/"; my $pid=fork(); if($pid) { exit(0) } elsif(defined($pid)) { close STDIN; close STDOUT; close STDERR; } else { exit(1); } } sub death { $gsm->disconnect() if($gsm); unlink "/tmp/.phone-status.new", "/tmp/.phone-status"; exit(0); }