FHEM2FHEM and associated changes
git-svn-id: https://fhem.svn.sourceforge.net/svnroot/fhem/trunk/fhem@732 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
2
CHANGED
2
CHANGED
@@ -2,6 +2,8 @@
|
|||||||
- feature: smallscreen optimizations for iPhone
|
- feature: smallscreen optimizations for iPhone
|
||||||
- feature: FHT8V rewrite (and moved from contrib into the FHEM directory).
|
- feature: FHT8V rewrite (and moved from contrib into the FHEM directory).
|
||||||
- feature: PID rewrite (and moved from contrib into the FHEM directory).
|
- feature: PID rewrite (and moved from contrib into the FHEM directory).
|
||||||
|
- feature: FHEM2FHEM module
|
||||||
|
- bugfix: CUL get should not digest foreign events (fhtsoftbuffer)
|
||||||
|
|
||||||
- 2010-08-15 (5.0)
|
- 2010-08-15 (5.0)
|
||||||
- **NOTE*: The default installation path is changed to satisfy lintian
|
- **NOTE*: The default installation path is changed to satisfy lintian
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ CUL_RFR_Initialize($)
|
|||||||
$hash->{WriteFn} = "CUL_RFR_Write";
|
$hash->{WriteFn} = "CUL_RFR_Write";
|
||||||
$hash->{GetFn} = "CUL_Get";
|
$hash->{GetFn} = "CUL_Get";
|
||||||
$hash->{SetFn} = "CUL_Set";
|
$hash->{SetFn} = "CUL_Set";
|
||||||
|
$hash->{noRawInform} = 1; # Our message was already sent as raw.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ package main;
|
|||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
sub addToAttrList($);
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
structure_Initialize($)
|
structure_Initialize($)
|
||||||
@@ -199,20 +197,4 @@ structure_Attr($@)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
|
||||||
addToAttrList($)
|
|
||||||
{
|
|
||||||
my $arg = shift;
|
|
||||||
|
|
||||||
my $ua = "";
|
|
||||||
$ua = $attr{global}{userattr} if($attr{global}{userattr});
|
|
||||||
my @al = split(" ", $ua);
|
|
||||||
my %hash;
|
|
||||||
foreach my $a (@al) {
|
|
||||||
$hash{$a} = 1;
|
|
||||||
}
|
|
||||||
$hash{$arg} = 1;
|
|
||||||
$attr{global}{userattr} = join(" ", sort keys %hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@@ -121,6 +121,7 @@
|
|||||||
<b>Helper modules</b>
|
<b>Helper modules</b>
|
||||||
<ul>
|
<ul>
|
||||||
<a href="#DbLog">DbLog</a>
|
<a href="#DbLog">DbLog</a>
|
||||||
|
<a href="#FHEM2FHEM">FHEM2FHEM</a>
|
||||||
<a href="#FHEMRENDERER">FHEMRENDERER</a>
|
<a href="#FHEMRENDERER">FHEMRENDERER</a>
|
||||||
<a href="#FHEMWEB">FHEMWEB</a>
|
<a href="#FHEMWEB">FHEMWEB</a>
|
||||||
<a href="#FileLog">FileLog</a>
|
<a href="#FileLog">FileLog</a>
|
||||||
@@ -506,7 +507,7 @@ A line ending with \ will be concatenated with the next one, so long lines
|
|||||||
<a name="inform"></a>
|
<a name="inform"></a>
|
||||||
<h3>inform</h3>
|
<h3>inform</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<code>inform [on|off|timer]</code> <br>
|
<code>inform [on|off|timer|raw]</code> <br>
|
||||||
<br>
|
<br>
|
||||||
If set to on, and a device state changes, send a notification to the current
|
If set to on, and a device state changes, send a notification to the current
|
||||||
client. This command can be used by other programs/modules to receive a
|
client. This command can be used by other programs/modules to receive a
|
||||||
@@ -4694,6 +4695,66 @@ Terminating
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<a name="FHEM2FHEM"></a>
|
||||||
|
<h3>FHEM2FHEM</h3>
|
||||||
|
<ul>
|
||||||
|
FHEM2FHEM is a helper module to connect separate fhem installations.
|
||||||
|
|
||||||
|
<a name="FHEM2FHEMdefine"></a>
|
||||||
|
<b>Define</b>
|
||||||
|
<ul>
|
||||||
|
<code>define <name> FHEM2FHEM <host:portnr> [LOG:regexp|RAW:devicename]
|
||||||
|
</code>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
Conect to the <i>remote</i> fhem on host. portnr is the global port
|
||||||
|
attribute of the remote fhem. The next parameter specifies the connection
|
||||||
|
type:
|
||||||
|
<ul>
|
||||||
|
<li>LOG<br>
|
||||||
|
Using this type you will receive all events generated by the remote fhem,
|
||||||
|
just like when using the <a href="#inform">inform on</a> command, and you
|
||||||
|
can use these events just like any local event for <a
|
||||||
|
href="#FileLog">FileLog </a> or <a href="#notify">notify</a>.
|
||||||
|
The regexp will prefilter the events distributed locally, for the syntax
|
||||||
|
see the notify definition.<br>
|
||||||
|
Drawbacks: the remote devices wont be created locally, so list wont
|
||||||
|
show them and it is not possible to manipulate them from the local
|
||||||
|
fhem. It is possible to create a device with the same name on both fhem
|
||||||
|
instances, but if both of them receive the same event (e.g. because both
|
||||||
|
of them have a CUL attached), then all associated FileLogs/notifys will be
|
||||||
|
triggered twice. </li>
|
||||||
|
|
||||||
|
<li>RAW<br>
|
||||||
|
By using this type the local fhem will receive raw events from the remote
|
||||||
|
fhem device <i>devicename</i>, just like if it would be attached to the
|
||||||
|
local fhem.
|
||||||
|
Drawback: only devices using the Dispatch function (CUL, FHZ, CM11,
|
||||||
|
SISPM, RFXCOM) generate raw messages.
|
||||||
|
</ul>
|
||||||
|
Examples:
|
||||||
|
<ul>
|
||||||
|
<code>define ds1 FHEM2FHEM 192.168.0.1:7072 LOG:.*</code><br>
|
||||||
|
<code>define ds2 FHEM2FHEM 192.168.0.1:7072 RAW:CUL</code><br>
|
||||||
|
</ul>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<a name="FHEM2FHEMset"></a>
|
||||||
|
<b>Set</b> <ul>N/A</ul><br>
|
||||||
|
|
||||||
|
<a name="FHEM2FHEMget"></a>
|
||||||
|
<b>Get</b> <ul>N/A</ul><br>
|
||||||
|
|
||||||
|
<a name="FHEM2FHEMattr"></a>
|
||||||
|
<b>Attributes</b>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#dummy">dummy</a></li>
|
||||||
|
<li><a href="#loglevel">loglevel</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<a name="FHEMWEB"></a>
|
<a name="FHEMWEB"></a>
|
||||||
<h3>FHEMWEB</h3>
|
<h3>FHEMWEB</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
81
fhem.pl
81
fhem.pl
@@ -44,6 +44,7 @@ sub AnalyzeCommand($$);
|
|||||||
sub AnalyzeCommandChain($$);
|
sub AnalyzeCommandChain($$);
|
||||||
sub AnalyzeInput($);
|
sub AnalyzeInput($);
|
||||||
sub AssignIoPort($);
|
sub AssignIoPort($);
|
||||||
|
sub addToAttrList($);
|
||||||
sub CallFn(@);
|
sub CallFn(@);
|
||||||
sub CommandChain($$);
|
sub CommandChain($$);
|
||||||
sub CheckDuplicate($$);
|
sub CheckDuplicate($$);
|
||||||
@@ -87,6 +88,7 @@ sub CommandGet($$);
|
|||||||
sub CommandHelp($$);
|
sub CommandHelp($$);
|
||||||
sub CommandInclude($$);
|
sub CommandInclude($$);
|
||||||
sub CommandInform($$);
|
sub CommandInform($$);
|
||||||
|
sub CommandIOWrite($$);
|
||||||
sub CommandList($$);
|
sub CommandList($$);
|
||||||
sub CommandModify($$);
|
sub CommandModify($$);
|
||||||
sub CommandReload($$);
|
sub CommandReload($$);
|
||||||
@@ -142,6 +144,7 @@ use vars qw($internal_data); #
|
|||||||
use vars qw(%cmds); # Global command name hash. To be expanded
|
use vars qw(%cmds); # Global command name hash. To be expanded
|
||||||
use vars qw(%data); # Hash for user data
|
use vars qw(%data); # Hash for user data
|
||||||
use vars qw($devcount); # To sort the devices
|
use vars qw($devcount); # To sort the devices
|
||||||
|
use vars qw(%defaultattr); # Default attributes, used by FHEM2FHEM
|
||||||
|
|
||||||
use vars qw($reread_active);
|
use vars qw($reread_active);
|
||||||
|
|
||||||
@@ -154,13 +157,12 @@ my %client; # Client array
|
|||||||
my $rcvdquit; # Used for quit handling in init files
|
my $rcvdquit; # Used for quit handling in init files
|
||||||
my $sig_term = 0; # if set to 1, terminate (saving the state)
|
my $sig_term = 0; # if set to 1, terminate (saving the state)
|
||||||
my $modpath_set; # Check if modpath was used, and report if not.
|
my $modpath_set; # Check if modpath was used, and report if not.
|
||||||
my %defaultattr; # Default attributes
|
|
||||||
my %intAt; # Internal at timer hash.
|
my %intAt; # Internal at timer hash.
|
||||||
my $nextat; # Time when next timer will be triggered.
|
my $nextat; # Time when next timer will be triggered.
|
||||||
my $intAtCnt=0;
|
my $intAtCnt=0;
|
||||||
my %duplicate; # Pool of received msg for multi-fhz/cul setups
|
my %duplicate; # Pool of received msg for multi-fhz/cul setups
|
||||||
my $duplidx=0; # helper for the above pool
|
my $duplidx=0; # helper for the above pool
|
||||||
my $cvsid = '$Id: fhem.pl,v 1.113 2010-10-10 08:23:29 rudolfkoenig Exp $';
|
my $cvsid = '$Id: fhem.pl,v 1.114 2010-10-24 16:08:48 rudolfkoenig Exp $';
|
||||||
my $namedef =
|
my $namedef =
|
||||||
"where <name> is either:\n" .
|
"where <name> is either:\n" .
|
||||||
"- a single device name\n" .
|
"- a single device name\n" .
|
||||||
@@ -201,7 +203,9 @@ $modules{_internal_}{AttrFn} = "GlobalAttr";
|
|||||||
"include" => { Fn=>"CommandInclude",
|
"include" => { Fn=>"CommandInclude",
|
||||||
Hlp=>"<filename>,read the commands from <filenname>" },
|
Hlp=>"<filename>,read the commands from <filenname>" },
|
||||||
"inform" => { Fn=>"CommandInform",
|
"inform" => { Fn=>"CommandInform",
|
||||||
Hlp=>"{on|timer|off},echo all commands and events to this client" },
|
Hlp=>"{on|timer|raw|off},echo all events to this client" },
|
||||||
|
"iowrite" => { Fn=>"CommandIOWrite",
|
||||||
|
Hlp=>"<iodev> <data>,write raw data with iodev" },
|
||||||
"list" => { Fn=>"CommandList",
|
"list" => { Fn=>"CommandList",
|
||||||
Hlp=>"[devspec],list definitions and status info" },
|
Hlp=>"[devspec],list definitions and status info" },
|
||||||
"modify" => { Fn=>"CommandModify",
|
"modify" => { Fn=>"CommandModify",
|
||||||
@@ -533,6 +537,33 @@ IOWrite($@)
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
sub
|
||||||
|
CommandIOWrite($$)
|
||||||
|
{
|
||||||
|
my ($cl, $param) = @_;
|
||||||
|
my @a = split(" ", $param);
|
||||||
|
|
||||||
|
return "Usage: iowrite <iodev> <param> ..." if(int(@a) <= 2);
|
||||||
|
|
||||||
|
my $name = shift(@a);
|
||||||
|
my $hash = $defs{$name};
|
||||||
|
return "$name not found" if(!$hash);
|
||||||
|
return undef if(IsDummy($name) || IsIgnored($name));
|
||||||
|
if(!$hash->{TYPE} ||
|
||||||
|
!$modules{$hash->{TYPE}} ||
|
||||||
|
!$modules{$hash->{TYPE}}{WriteFn}) {
|
||||||
|
Log 1, "No IO device or WriteFn found for $name";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unshift(@a, "") if(int(@a) == 1);
|
||||||
|
no strict "refs";
|
||||||
|
my $ret = &{$modules{$hash->{TYPE}}{WriteFn}}($hash, @a);
|
||||||
|
use strict "refs";
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
sub
|
sub
|
||||||
AnalyzeInput($)
|
AnalyzeInput($)
|
||||||
@@ -1135,10 +1166,12 @@ AssignIoPort($)
|
|||||||
{
|
{
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
# Set the I/O device
|
# Set the I/O device, search for the last compatible one.
|
||||||
for my $p (sort { $defs{$b}{NR} <=> $defs{$a}{NR} } keys %defs) {
|
for my $p (sort { $defs{$b}{NR} <=> $defs{$a}{NR} } keys %defs) {
|
||||||
my $cl = $modules{$defs{$p}{TYPE}}{Clients};
|
my $cl = $modules{$defs{$p}{TYPE}}{Clients};
|
||||||
if(defined($cl) && $cl =~ m/:$hash->{TYPE}:/ &&
|
my $re = $modules{$defs{$p}{TYPE}}{regexpClients};
|
||||||
|
if(((defined($cl) && $cl =~ m/:$hash->{TYPE}:/) ||
|
||||||
|
(defined($re) && $hash->{TYPE} =~ m/$re/)) &&
|
||||||
$defs{$p}{NAME} ne $hash->{NAME}) { # e.g. RFR
|
$defs{$p}{NAME} ne $hash->{NAME}) { # e.g. RFR
|
||||||
$hash->{IODev} = $defs{$p};
|
$hash->{IODev} = $defs{$p};
|
||||||
last;
|
last;
|
||||||
@@ -1675,7 +1708,8 @@ CommandInform($$)
|
|||||||
|
|
||||||
$param = lc($param);
|
$param = lc($param);
|
||||||
|
|
||||||
return "Usage: inform {on|off|timer}" if($param !~ m/^(on|off|timer)$/);
|
return "Usage: inform {on|timer|raw|off}"
|
||||||
|
if($param !~ m/^(on|off|raw|timer)$/);
|
||||||
if($param =~ m/off/) {
|
if($param =~ m/off/) {
|
||||||
delete($client{$cl}{inform});
|
delete($client{$cl}{inform});
|
||||||
} else {
|
} else {
|
||||||
@@ -1922,7 +1956,7 @@ DoTrigger($$)
|
|||||||
################
|
################
|
||||||
# Inform
|
# Inform
|
||||||
foreach my $c (keys %client) { # Do client loop first, is cheaper
|
foreach my $c (keys %client) { # Do client loop first, is cheaper
|
||||||
next if(!$client{$c}{inform});
|
next if(!$client{$c}{inform} || $client{$c}{inform} eq "raw");
|
||||||
my $tn = TimeNow();
|
my $tn = TimeNow();
|
||||||
if($attr{global}{mseclog}) {
|
if($attr{global}{mseclog}) {
|
||||||
my ($seconds, $microseconds) = gettimeofday();
|
my ($seconds, $microseconds) = gettimeofday();
|
||||||
@@ -1930,7 +1964,6 @@ DoTrigger($$)
|
|||||||
}
|
}
|
||||||
for(my $i = 0; $i < $max; $i++) {
|
for(my $i = 0; $i < $max; $i++) {
|
||||||
my $state = $defs{$dev}{CHANGED}[$i];
|
my $state = $defs{$dev}{CHANGED}[$i];
|
||||||
my $fe = "$dev:$state";
|
|
||||||
syswrite($client{$c}{fd},
|
syswrite($client{$c}{fd},
|
||||||
($client{$c}{inform} eq "timer" ? "$tn " : "") .
|
($client{$c}{inform} eq "timer" ? "$tn " : "") .
|
||||||
"$defs{$dev}{TYPE} $dev $state\n");
|
"$defs{$dev}{TYPE} $dev $state\n");
|
||||||
@@ -2125,7 +2158,11 @@ Dispatch($$$)
|
|||||||
my @found;
|
my @found;
|
||||||
foreach my $m (sort { $modules{$a}{ORDER} cmp $modules{$b}{ORDER} }
|
foreach my $m (sort { $modules{$a}{ORDER} cmp $modules{$b}{ORDER} }
|
||||||
grep {defined($modules{$_}{ORDER})} keys %modules) {
|
grep {defined($modules{$_}{ORDER})} keys %modules) {
|
||||||
next if($iohash->{Clients} !~ m/:$m:/);
|
|
||||||
|
my $cl = $iohash->{Clients};
|
||||||
|
my $re = $iohash->{regexpClients};
|
||||||
|
next if(!(defined($cl) && $cl =~ m/:$m:/) ||
|
||||||
|
(defined($re) && $m =~ m/$re/));
|
||||||
|
|
||||||
# Module is not loaded or the message is not for this module
|
# Module is not loaded or the message is not for this module
|
||||||
next if(!$modules{$m}{Match} || $dmsg !~ m/$modules{$m}{Match}/i);
|
next if(!$modules{$m}{Match} || $dmsg !~ m/$modules{$m}{Match}/i);
|
||||||
@@ -2170,6 +2207,15 @@ Dispatch($$$)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################
|
||||||
|
# Inform raw
|
||||||
|
if(!$iohash->{noRawInform}) {
|
||||||
|
foreach my $c (keys %client) {
|
||||||
|
next if(!$client{$c}{inform} || $client{$c}{inform} ne "raw");
|
||||||
|
syswrite($client{$c}{fd}, "$hash->{TYPE} $name $dmsg\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return undef if($found[0] eq ""); # Special return: Do not notify
|
return undef if($found[0] eq ""); # Special return: Do not notify
|
||||||
|
|
||||||
foreach my $found (@found) {
|
foreach my $found (@found) {
|
||||||
@@ -2270,3 +2316,20 @@ ReadingsVal($$$)
|
|||||||
}
|
}
|
||||||
return $default;
|
return $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
addToAttrList($)
|
||||||
|
{
|
||||||
|
my $arg = shift;
|
||||||
|
|
||||||
|
my $ua = "";
|
||||||
|
$ua = $attr{global}{userattr} if($attr{global}{userattr});
|
||||||
|
my @al = split(" ", $ua);
|
||||||
|
my %hash;
|
||||||
|
foreach my $a (@al) {
|
||||||
|
$hash{$a} = 1;
|
||||||
|
}
|
||||||
|
$hash{$arg} = 1;
|
||||||
|
$attr{global}{userattr} = join(" ", sort keys %hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user