From e65f8ea6496ca08e5a2a1d4f63c6a16eb04881f7 Mon Sep 17 00:00:00 2001 From: Wzut <> Date: Sat, 1 Apr 2017 17:28:10 +0000 Subject: [PATCH] 96_SIP: fix repeat function , add auto port git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@13872 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/96_SIP.pm | 123 ++++++++++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 53 deletions(-) diff --git a/FHEM/96_SIP.pm b/FHEM/96_SIP.pm index a15b68ca6..acb2b285a 100644 --- a/FHEM/96_SIP.pm +++ b/FHEM/96_SIP.pm @@ -54,7 +54,7 @@ use Net::Domain qw(hostname hostfqdn); use Blocking; # http://www.fhemwiki.de/wiki/Blocking_Call #use Data::Dumper; -my $sip_version ="V1.5 / 31.03.17"; +my $sip_version ="V1.51 / 01.04.17"; my $ua; # SIP user agent my @fifo; @@ -98,7 +98,7 @@ sub SIP_Initialize($$) "sip_listen:none,dtmf,wfp,echo ". # "sip_filter ". # "sip_blocking ". # - "sip_elbc:no,yes ". # + "sip_elbc:yes,no ". # "sip_force_interval ". # "T2S_Device ". # "T2S_Timeout ". # @@ -119,13 +119,12 @@ sub SIP_Define($$) $hash->{".reset"} = 0; $attr{$name}{sip_ringtime} = '3' unless (exists($attr{$name}{sip_ringtime})); $attr{$name}{sip_user} = '620' unless (exists($attr{$name}{sip_user})); - $attr{$name}{sip_port} = '5060' unless (exists($attr{$name}{sip_port})); $attr{$name}{sip_registrar} = 'fritz.box' unless (exists($attr{$name}{sip_registrar})); $attr{$name}{sip_listen} = 'none' unless (exists($attr{$name}{sip_listen})); $attr{$name}{sip_dtmf_size} = '2' unless (exists($attr{$name}{sip_dtmf_size})); $attr{$name}{sip_dtmf_loop} = 'once' unless (exists($attr{$name}{sip_dtmf_loop})); $attr{$name}{sip_dtmf_send} = 'audio' unless (exists($attr{$name}{sip_dtmf_send})); - $attr{$name}{sip_elbc} = 'no' unless (exists($attr{$name}{sip_elbc})); + $attr{$name}{sip_elbc} = 'yes' unless (exists($attr{$name}{sip_elbc})); $attr{$name}{sip_from} = 'sip:'.$attr{$name}{sip_user}.'@'.$attr{$name}{sip_registrar} unless (exists($attr{$name}{sip_from})); unless (exists($attr{$name}{sip_ip})) @@ -307,24 +306,23 @@ sub SIP_Register($$$) my $name = $hash->{NAME}; my $logname = $name."[".$$."]"; my $ip = AttrVal($name,"sip_ip",""); - return "missing attr sip_ip" if (!$ip); + return "missing attribute sip_ip" if (!$ip); + return "this is the IP address of your registrar , not your FHEM !" if ($ip eq AttrVal($name,"sip_registrar","")); + return "invalid IP address $ip" if (($ip eq "0.0.0.0") || ($ip eq "127.0.0.1")); - my $leg = IO::Socket::INET->new( - Proto => 'udp', - LocalHost => $ip, - LocalPort => $port); + my $leg = IO::Socket::INET->new(Proto => 'udp', LocalHost => $ip, LocalPort => $port); -# if port is already used try another one - if (!$leg) - { + # if port is already used try another one + if (!$leg) + { Log3 $name,2,"$logname, cannot open port $port at $ip: $!"; $port += 10; $leg = IO::Socket::INET->new( - Proto => 'udp', + Proto => 'udp', LocalHost => $ip, - LocalPort => $port) || return "cannot open port ".($port-10)." or $port at $ip: $!"; - Log3 $name,2,"$logname, using port $port"; - } + LocalPort => $port) || return "can't open port ".($port-10)." or $port at $ip: $!"; + Log3 $name,2,"$logname, using secundary port $port with IP $ip"; + } close($leg); $leg = $ip.":".$port; @@ -351,7 +349,7 @@ sub SIP_Register($$$) my $result = qx($cmd); if (index($result,"perl") == -1) { - Log3 $name, 2 , $logname.", can´t find my parent ".$hash->{parent}." in process list !"; + Log3 $name,1,"$logname, can´t find my parent ".$hash->{parent}." in process list !"; die; } Log3 $name,4,"$logname, register new expire : ".localtime(time()+$expire); @@ -383,7 +381,7 @@ sub SIP_CALLStart($) $ua = undef; my $rtp_done = 0; my $dtmf = 'ABCD*#123--4567890'; - my $port = AttrVal($name,"sip_port","5060"); + my $port = AttrVal($name,"sip_port",0); my $delay = AttrVal($name,"sip_call_audio_delay",0); # Verzoegerung in 1/4 Sekunden Schritten my $fi = 0; #$repeat = 0 if (!$repeat); @@ -412,6 +410,13 @@ sub SIP_CALLStart($) $hash->{telnetPort} = SIP_telnetPort(); return $name."|no telnet port without password found" if (!$hash->{telnetPort}); + if (!$port) + { + srand $$; + $port = int(rand(500)+44000); + Log3 $name,4,"$logname, using random port $port"; + } + my $error = SIP_Register($hash,$port,"calling"); return $name."|0|CallRegister: $error" if ($error); @@ -584,8 +589,8 @@ sub SIP_CALLDone($) Log3 $name, 4,"$name, CALLDone -> $string"; delete($hash->{helper}{CALL_PID}) if (defined($hash->{helper}{CALL_PID})); - delete($hash->{CPID}) if (defined($hash->{CPID})); - + delete($hash->{CPID}) if (defined($hash->{CPID})); + delete $hash->{lastnr} if (defined($hash->{lastnr})); if ($error ne "1") { @@ -651,6 +656,7 @@ sub SIP_Set($@) my $name = $hash->{NAME}; my $cmd = (defined($a[1])) ? $a[1] : "?"; my $subcmd; + my $ret; return join(" ", sort keys %sets) if ($cmd eq "?"); @@ -675,21 +681,19 @@ sub SIP_Set($@) if (exists($hash->{CPID})) { - #return "there is already a call activ for target $nr" if (defined($hash->{lastnr}) && ($hash->{lastnr} eq $nr)); + return "there is already a call activ for target $nr" if (defined($hash->{lastnr}) && ($hash->{lastnr} eq $nr)); my $call = join(" ",@a); push (@fifo,$call); - Log3 $name ,4,"$name, add call -> $call to fifo we will do it later"; + Log3 $name ,4,"$name, add call $call to fifo so we can do it later !"; return undef; } my $anz = @a; $anz--; # letztes Element my $force = ($a[$anz] eq "&") ? 1 : 0; - $anz-- if ($force); # checken wir dann noch auf repeat - my $repeat; - if (substr($a[$anz],0,1) ne "*") - { $repeat = 0; } - else + $anz-- if ($force == 1); # checken wir dann noch auf repeat + my $repeat = 0; + if (substr($a[$anz],0,1) eq "*") { $repeat = $a[$anz]; $repeat =~ s/^\*//; @@ -701,7 +705,7 @@ sub SIP_Set($@) if (exists($hash->{LPID}) && (AttrVal($name,"sip_elbc","no") ne "no")) { - Log3 $name,4,"$name, listen process $hash->{LPID} must be killed befor starting call !"; + Log3 $name,4,"$name, listen process $hash->{LPID} must be killed befor we start a new call !"; BlockingKill($hash->{helper}{LISTEN_PID}); delete $hash->{helper}{LISTEN_PID}; delete $hash->{LPID}; @@ -735,7 +739,6 @@ sub SIP_Set($@) readingsSingleUpdate($hash,"call_state","waiting T2S",0); - Log3 $name,1,"$name :set repeat $repeat"; RemoveInternalTimer($hash); # geben wir T2S mal ein paar Sekunden InternalTimer(gettimeofday()+int(AttrVal($name,"T2S_Timeout",5)), "SIP_wait_for_t2s", $hash); @@ -743,12 +746,14 @@ sub SIP_Set($@) } elsif (-e $msg) { - Log3 $name, 4, $name.", message $msg found"; - return "unknown message type, please use only .alaw or .ulaw" if (($msg !~ /\.al(.+)$/) && ($msg !~ /\.ul(.+)$/)); + Log3 $name, 4, $name.", audio file $msg found"; + return "unknown audio type, please use only .alaw or .ulaw" if (($msg !~ /\.al(.+)$/) && ($msg !~ /\.ul(.+)$/)); } else { - Log3 $name, 3, $name.", message $msg NOT found !"; + $ret = "audio file $msg not found"; + readingsBulkUpdate($hash, "last_error",$ret); + Log3 $name, 3, "$name, $ret !"; $hash->{repeat} = 0; $hash->{forcecall} = 0; $msg = ""; @@ -756,7 +761,9 @@ sub SIP_Set($@) } else { Log3 $name, 4, $name.", calling $nr, ringtime: $ringtime , no message"; } + $hash->{lastnr} = $nr; my $arg = "$name|$nr|$ringtime|$msg|$repeat"; # da muss force nicht mit + Log3 $name, 4, "$name, $arg"; #BlockingCall($blockingFn, $arg, $finishFn, $timeout, $abortFn, $abortArg); $hash->{helper}{CALL_PID} = BlockingCall("SIP_CALLStart",$arg, "SIP_CALLDone") unless(exists($hash->{helper}{CALL_PID})); @@ -764,8 +771,10 @@ sub SIP_Set($@) { $hash->{CPID} = $hash->{helper}{CALL_PID}{pid}; $hash->{CALL} = $arg."|$force"; # hier retten wir aber force + Log3 $name, 4, "$name, call -> ".$hash->{CALL}; Log3 $name, 5, "$name, call has pid ".$hash->{CPID}; + readingsBeginUpdate($hash); readingsBulkUpdate($hash, "call_state","invite"); readingsBulkUpdate($hash, "call",$nr); @@ -776,33 +785,30 @@ sub SIP_Set($@) else { # das war wohl nix :( Log3 $name, 3, "$name, CALL process start failed, arg : $arg"; - my $txt = "can't execute call number $nr as NonBlockingCall"; + $ret = "can't execute call number $nr as NonBlockingCall"; readingsBeginUpdate($hash); - readingsBulkUpdate($hash, "last_error",$txt); + readingsBulkUpdate($hash, "last_error",$ret); readingsBulkUpdate($hash, "call_state","fail"); readingsEndUpdate($hash, 1); delete $hash->{lastnr} if (defined($hash->{lastnr})); - return $txt; + return $ret; } } - elsif ($cmd eq "listen") { my $type = AttrVal($name,"sip_listen","none"); return "there is already a listen process running with pid ".$hash->{LPID} if exists($hash->{LPID}); return "please set attr sip_listen to dtmf or wfp or echo first" if (AttrVal($name,"sip_listen","none") eq "none"); - my $error = SIP_try_listen($hash); - if ($error) + $ret = SIP_try_listen($hash); + if ($ret) { - Log3 $name, 1, $name.", listen -> $error"; + Log3 $name, 1, $name.", listen -> $ret"; readingsBeginUpdate($hash); readingsBulkUpdate($hash,"state","error"); - readingsBulkUpdate($hash,"last_error",$error); + readingsBulkUpdate($hash,"last_error",$ret); readingsEndUpdate($hash, 1 ); - return $error; + return $ret; } - - #else {readingsSingleUpdate($hash, "state","listen_for_$type",1);} return undef; } elsif (($cmd eq "dtmf_event") && defined($a[2])) @@ -913,8 +919,14 @@ sub SIP_ListenStart($) return $name."|no telnet port without password found" if (!$hash->{telnetPort}); - my $port = AttrVal($name,"sip_port","5060"); - $port += 10; + my $port = AttrVal($name,"sip_port",0); + if (!$port) + { + srand $$; + $port = int(rand(500)+44500); + Log3 $name,4,"$logname, using random port $port"; + } + else { $port += 10; } $ua = undef; my $error = SIP_Register($hash,$port,"listen_".AttrVal($name,"sip_listen","")); return $name."|ListenRegister: $error" if ($error); @@ -1440,18 +1452,21 @@ sub SIP_wait_for_t2s($) } # nun aber calling - $hash->{repeat} = "*".$hash->{repeat}; - $hash->{forcecall} = ($hash->{forcecall}) ? "&" : ""; - my @a = ($name,"call",$hash->{callnr}, $hash->{ringtime},$msg,$hash->{repeat},$hash->{forcecall}) ; - my $test = join(" ",@a); - Log3 $name ,1,"$name, Test : $test"; + my $repeat = "*".$hash->{repeat}; + + my $force = ($hash->{forcecall}) ? "&" : ""; + my @a; + if ($force) + { @a = ($name,"call",$hash->{callnr}, $hash->{ringtime},$msg,$repeat,$force) ; } + else + { @a = ($name,"call",$hash->{callnr}, $hash->{ringtime},$msg,$repeat) ; } delete($hash->{callnr}); delete($hash->{ringtime}); delete($hash->{forcecall}); delete($hash->{repeat}); my $ret = SIP_Set($hash , @a); - Log3 $name,3,"$name, T2S Call : $ret" if defined($ret); + Log3 $name,3,"$name, error T2S Call : $ret" if defined($ret); return undef; } @@ -1731,7 +1746,8 @@ sub SIP_readPassword($) external IP address of the FHEM server.