diff --git a/fhem/contrib/HMRPC/00_HMRPC.pm b/fhem/contrib/HMRPC/00_HMRPC.pm index 1db7a4377..d10eda36d 100755 --- a/fhem/contrib/HMRPC/00_HMRPC.pm +++ b/fhem/contrib/HMRPC/00_HMRPC.pm @@ -1,11 +1,11 @@ -############################################## +########################################################### # # HomeMatic XMLRPC API Device Provider # Written by Oliver Wagner # -# V0.3 +# V0.4 # -############################################## +########################################################### # # This module implements the documented XML-RPC based API # of the Homematic system software (currently offered as @@ -46,7 +46,11 @@ HMRPC_Shutdown($) { my ($hash) = @_; # Uninitialize again - $hash->{client}->send_request("init",$hash->{callbackurl},""); + if($hash->{callbackurl}) + { + Log(2,"HMRPC unitializing callback ".$hash->{callbackurl}); + $hash->{client}->send_request("init",$hash->{callbackurl}); + } return undef; } @@ -81,7 +85,10 @@ HMRPC_Define($$) # Add the XMLRPC methods we do expose $hash->{server}->add_method( - {name=>"event",signature=> ["string string string string int","string string string string double","string string string string boolean"],code=>\&HMRPC_EventCB} + {name=>"event",signature=> ["string string string string int","string string string string double","string string string string boolean","string string string string i4"],code=>\&HMRPC_EventCB} + ); + $hash->{server}->add_method( + {name=>"newDevices",signature=>["array string array"],code=>\&HMRPC_NewDevicesCB } ); # # Dummy implementation, always return an empty array @@ -89,12 +96,6 @@ HMRPC_Define($$) $hash->{server}->add_method( {name=>"listDevices",signature=>["array string"],code=>sub{return RPC::XML::array->new()} } ); - # - # TOFIX! We can use this to store device types, autocreate devices and other niceties - # - $hash->{server}->add_method( - {name=>"newDevices",signature=>["array string array"],code=>sub{return RPC::XML::array->new()} } - ); $hash->{STATE} = "Initialized"; $hash->{SERVERSOCKET}=$hash->{server}->{__daemon}; @@ -143,18 +144,45 @@ HMRPC_RegisterCallback($) # and then look at the local socket address assigned to us. # my $dummysock=IO::Socket::INET->new(PeerAddr=>$hash->{serveraddr},PeerPort=>$hash->{serverport}); - $hash->{callbackurl}="http://".$dummysock->sockhost().":".$hash->{PORT}."/fhemhmrpc"; + if(!$dummysock) + { + Log(2,"HMRPC unable to connect to ".$hash->{serveraddr}.":".$hash->{serverport}." ($!), will retry later"); + return; + } + $hash->{callbackurl}="http://".$dummysock->sockhost().":".$hash->{PORT}."/fh"; $dummysock->close(); Log(2, "HMRPC callback listening on $hash->{callbackurl}"); # We need to fork here, as the xmlrpc server will synchronously call us if(!fork()) { - $hash->{client}->send_request("init",$hash->{callbackurl},"cb"); - Log(2, "HMRPC callback initialized"); + $hash->{client}->send_request("init",$hash->{callbackurl},"CB1"); + Log(2, "HMRPC callback with URL ".$hash->{callbackurl}." initialized"); exit(0); } } +##################################### +# Process device info +sub +HMRPC_NewDevicesCB($$$) +{ + my ($server, $cb, $a) = @_; + + my $hash=$server->{fhemdef}; + + Log(2,"HMRPC received ".scalar(@$a)." device specifications"); + + # We receive an array of hashes with the device information. We + # store those hashes again in a hash, keyed by address, for later + # use by the individual devices + for my $dev (@$a) + { + my $addr=$dev->{ADDRESS}; + $hash->{devicespecs}{$addr}=$dev; + } + return RPC::XML::array->new(); +} + ##################################### sub HMRPC_EventCB($$$$$) @@ -175,7 +203,7 @@ HMRPC_Read($) # Handle an incoming callback # my $conn=$hash->{server}->{__daemon}->accept(); - $conn->timeout(3); + $conn->timeout(20); $hash->{server}->process_request($conn); $conn->close; undef $conn; diff --git a/fhem/contrib/HMRPC/01_HMDEV.pm b/fhem/contrib/HMRPC/01_HMDEV.pm index b94913eb0..cfc33d4dd 100644 --- a/fhem/contrib/HMRPC/01_HMDEV.pm +++ b/fhem/contrib/HMRPC/01_HMDEV.pm @@ -1,10 +1,10 @@ -############################################## +################################################ # HMRPC Device Handler # Written by Oliver Wagner # -# V0.3 +# V0.4 # -############################################## +################################################ # # This module handles individual devices via the # HMRPC provider. @@ -43,7 +43,10 @@ HMDEV_Define($$) $modules{HMDEV}{defptr}{$addr} = $hash; AssignIoPort($hash); - Log 5,"Assigned $name to $hash->{IODev}->{NAME}"; + if($hash->{IODev}->{NAME}) + { + Log 5,"Assigned $name to $hash->{IODev}->{NAME}"; + } return undef; } @@ -58,8 +61,23 @@ HMDEV_Parse($$) my @mp=split(" ",$msg); my $addr=$mp[1]; + my $attrid=$mp[2]; $hash=$modules{HMDEV}{defptr}{$addr}; + + if(!$hash) + { + # If not explicitely defined, reroute this event to the main device + # with a suffixed attribute name + $addr=~s/:([0-9]{1,2})//; + my $subdev=$1; + if($subdev>0) + { + $attrid.="_$subdev"; + } + $hash=$modules{HMDEV}{defptr}{$addr}; + } + if(!$hash) { Log(2,"Received callback for unknown device $msg"); @@ -70,14 +88,17 @@ HMDEV_Parse($$) # Ok update the relevant reading # my @changed; - my $currentval=$hash->{READINGS}{$mp[2]}{VAL}; - $hash->{READINGS}{$mp[2]}{TIME}=TimeNow(); + my $currentval=$hash->{READINGS}{$attrid}{VAL}; + $hash->{READINGS}{$attrid}{TIME}=TimeNow(); # Note that we always trigger a change on PRESS_LONG/PRESS_SHORT events - # (they are sent whenever a button is presed, and there is no change back) - if(!defined $currentval || ($currentval ne $mp[3]) || ($currentval =~ m/^PRESS_/)) + # (they are sent whenever a button is pressed, and there is no change back) + if(!defined $currentval || ($currentval ne $mp[3]) || ($attrid =~ /^PRESS_/)) { - push @changed, "$mp[2]: $mp[3]"; - $hash->{READINGS}{$mp[2]}{VAL}=$mp[3]; + if(!($currentval =~ m/^RSSI_/)) + { + push @changed, "$attrid: $mp[3]"; + } + $hash->{READINGS}{$attrid}{VAL}=$mp[3]; } $hash->{CHANGED}=\@changed; diff --git a/fhem/contrib/HMRPC/HMRPC.txt b/fhem/contrib/HMRPC/HMRPC.txt index 2579c1c09..e5ad75b37 100644 --- a/fhem/contrib/HMRPC/HMRPC.txt +++ b/fhem/contrib/HMRPC/HMRPC.txt @@ -118,6 +118,20 @@ V0.3 - get-Methoden implementiert, als Aufruf von XML-RPC getValue() - bei Boolean-Werten wurde bei false bei jedem event-Empfang faelschlicherweise eine Notification ausgeloest +V0.4 - HMRPC: Fehlermeldung statt Abbruch, wenn eine Testverbindung zum + entsprechenden Daemon nicht moeglich ist + HMRPC: Beim Abmelden wird nun korrekterweise kein Callback-Parameter + uebergeben + HMRPC: Das Default-Timeout fuer eingehende Requests ist nun auf 20s + gesetzt, da die 3s bei sehr grossen eingehenden Requests offenbar + zu kurz war und so z.B. der initiale newDevices-Aufruf nach dem init + abgebrochen wurde, was zu einem Absturz des rfd fuehrt + HMRPC: Ist ein Channel unbekannt, wird nun der Event an das entsprechende + Device delegiert, fuer Channel != 0 dann mit dem Suffix _ChannelID + (z.B. STATE_1) + HMRPC: PRESS_ loest nun wirklich jedesmal ein changed aus. + import_webui: Pattern korrigiert, so dass nun auch die virtuellen + Taster erkannt werden Anhang ------ diff --git a/fhem/contrib/HMRPC/import_from_webui.bsh b/fhem/contrib/HMRPC/import_from_webui.bsh index a61870de7..c64825d5d 100644 --- a/fhem/contrib/HMRPC/import_from_webui.bsh +++ b/fhem/contrib/HMRPC/import_from_webui.bsh @@ -17,7 +17,7 @@ export LANG=de_DE.ISO-8859-1 wget http://$1:8181/tclrega.exe --post-data=' string id; string chid; -foreach(id, root.Devices().EnumUsedIDs()) +foreach(id, dom.GetObject(ID_DEVICES).EnumUsedIDs()) { var d=dom.GetObject(id); foreach(chid,d.Channels().EnumUsedIDs()) @@ -69,7 +69,7 @@ function roomName(n) return n; } -/^BidCos-|^[A-Z0-9]{10}(:[0-9]+)?/ { +/^BidCoS-|^[A-Z0-9]{10}(:[0-9]+)?/ { name=sanitizeName($3) while(usednames[name]) {