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



git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@1107 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
oliverwagner 2011-11-13 19:59:18 +00:00
parent 1341edef7a
commit 6871ed1e08
4 changed files with 90 additions and 27 deletions

View File

@ -1,11 +1,11 @@
############################################## ###########################################################
# #
# HomeMatic XMLRPC API Device Provider # HomeMatic XMLRPC API Device Provider
# Written by Oliver Wagner <owagner@vapor.com> # Written by Oliver Wagner <owagner@vapor.com>
# #
# V0.3 # V0.4
# #
############################################## ###########################################################
# #
# This module implements the documented XML-RPC based API # This module implements the documented XML-RPC based API
# of the Homematic system software (currently offered as # of the Homematic system software (currently offered as
@ -46,7 +46,11 @@ HMRPC_Shutdown($)
{ {
my ($hash) = @_; my ($hash) = @_;
# Uninitialize again # 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; return undef;
} }
@ -81,7 +85,10 @@ HMRPC_Define($$)
# Add the XMLRPC methods we do expose # Add the XMLRPC methods we do expose
$hash->{server}->add_method( $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 # Dummy implementation, always return an empty array
@ -89,12 +96,6 @@ HMRPC_Define($$)
$hash->{server}->add_method( $hash->{server}->add_method(
{name=>"listDevices",signature=>["array string"],code=>sub{return RPC::XML::array->new()} } {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->{STATE} = "Initialized";
$hash->{SERVERSOCKET}=$hash->{server}->{__daemon}; $hash->{SERVERSOCKET}=$hash->{server}->{__daemon};
@ -143,18 +144,45 @@ HMRPC_RegisterCallback($)
# and then look at the local socket address assigned to us. # and then look at the local socket address assigned to us.
# #
my $dummysock=IO::Socket::INET->new(PeerAddr=>$hash->{serveraddr},PeerPort=>$hash->{serverport}); 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(); $dummysock->close();
Log(2, "HMRPC callback listening on $hash->{callbackurl}"); Log(2, "HMRPC callback listening on $hash->{callbackurl}");
# We need to fork here, as the xmlrpc server will synchronously call us # We need to fork here, as the xmlrpc server will synchronously call us
if(!fork()) if(!fork())
{ {
$hash->{client}->send_request("init",$hash->{callbackurl},"cb"); $hash->{client}->send_request("init",$hash->{callbackurl},"CB1");
Log(2, "HMRPC callback initialized"); Log(2, "HMRPC callback with URL ".$hash->{callbackurl}." initialized");
exit(0); 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 sub
HMRPC_EventCB($$$$$) HMRPC_EventCB($$$$$)
@ -175,7 +203,7 @@ HMRPC_Read($)
# Handle an incoming callback # Handle an incoming callback
# #
my $conn=$hash->{server}->{__daemon}->accept(); my $conn=$hash->{server}->{__daemon}->accept();
$conn->timeout(3); $conn->timeout(20);
$hash->{server}->process_request($conn); $hash->{server}->process_request($conn);
$conn->close; $conn->close;
undef $conn; undef $conn;

View File

@ -1,10 +1,10 @@
############################################## ################################################
# HMRPC Device Handler # HMRPC Device Handler
# Written by Oliver Wagner <owagner@vapor.com> # Written by Oliver Wagner <owagner@vapor.com>
# #
# V0.3 # V0.4
# #
############################################## ################################################
# #
# This module handles individual devices via the # This module handles individual devices via the
# HMRPC provider. # HMRPC provider.
@ -43,7 +43,10 @@ HMDEV_Define($$)
$modules{HMDEV}{defptr}{$addr} = $hash; $modules{HMDEV}{defptr}{$addr} = $hash;
AssignIoPort($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; return undef;
} }
@ -58,8 +61,23 @@ HMDEV_Parse($$)
my @mp=split(" ",$msg); my @mp=split(" ",$msg);
my $addr=$mp[1]; my $addr=$mp[1];
my $attrid=$mp[2];
$hash=$modules{HMDEV}{defptr}{$addr}; $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) if(!$hash)
{ {
Log(2,"Received callback for unknown device $msg"); Log(2,"Received callback for unknown device $msg");
@ -70,14 +88,17 @@ HMDEV_Parse($$)
# Ok update the relevant reading # Ok update the relevant reading
# #
my @changed; my @changed;
my $currentval=$hash->{READINGS}{$mp[2]}{VAL}; my $currentval=$hash->{READINGS}{$attrid}{VAL};
$hash->{READINGS}{$mp[2]}{TIME}=TimeNow(); $hash->{READINGS}{$attrid}{TIME}=TimeNow();
# Note that we always trigger a change on PRESS_LONG/PRESS_SHORT events # 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) # (they are sent whenever a button is pressed, and there is no change back)
if(!defined $currentval || ($currentval ne $mp[3]) || ($currentval =~ m/^PRESS_/)) if(!defined $currentval || ($currentval ne $mp[3]) || ($attrid =~ /^PRESS_/))
{ {
push @changed, "$mp[2]: $mp[3]"; if(!($currentval =~ m/^RSSI_/))
$hash->{READINGS}{$mp[2]}{VAL}=$mp[3]; {
push @changed, "$attrid: $mp[3]";
}
$hash->{READINGS}{$attrid}{VAL}=$mp[3];
} }
$hash->{CHANGED}=\@changed; $hash->{CHANGED}=\@changed;

View File

@ -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 - bei Boolean-Werten wurde bei false bei jedem event-Empfang
faelschlicherweise eine Notification ausgeloest 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 Anhang
------ ------

View File

@ -17,7 +17,7 @@ export LANG=de_DE.ISO-8859-1
wget http://$1:8181/tclrega.exe --post-data=' wget http://$1:8181/tclrega.exe --post-data='
string id; string id;
string chid; string chid;
foreach(id, root.Devices().EnumUsedIDs()) foreach(id, dom.GetObject(ID_DEVICES).EnumUsedIDs())
{ {
var d=dom.GetObject(id); var d=dom.GetObject(id);
foreach(chid,d.Channels().EnumUsedIDs()) foreach(chid,d.Channels().EnumUsedIDs())
@ -69,7 +69,7 @@ function roomName(n)
return n; return n;
} }
/^BidCos-|^[A-Z0-9]{10}(:[0-9]+)?/ { /^BidCoS-|^[A-Z0-9]{10}(:[0-9]+)?/ {
name=sanitizeName($3) name=sanitizeName($3)
while(usednames[name]) while(usednames[name])
{ {