2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 04:36:36 +00:00

FHEM2FHEM and associated changes

git-svn-id: https://svn.fhem.de/fhem/trunk@732 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig 2010-10-24 16:08:48 +00:00
parent b580c66189
commit 9dc00abe35
5 changed files with 137 additions and 28 deletions

View File

@ -2,6 +2,8 @@
- feature: smallscreen optimizations for iPhone
- feature: FHT8V 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)
- **NOTE*: The default installation path is changed to satisfy lintian

View File

@ -25,6 +25,7 @@ CUL_RFR_Initialize($)
$hash->{WriteFn} = "CUL_RFR_Write";
$hash->{GetFn} = "CUL_Get";
$hash->{SetFn} = "CUL_Set";
$hash->{noRawInform} = 1; # Our message was already sent as raw.
}

View File

@ -4,8 +4,6 @@ package main;
use strict;
use warnings;
sub addToAttrList($);
#####################################
sub
structure_Initialize($)
@ -199,20 +197,4 @@ structure_Attr($@)
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;

View File

@ -121,6 +121,7 @@
<b>Helper modules</b>
<ul>
<a href="#DbLog">DbLog</a> &nbsp;
<a href="#FHEM2FHEM">FHEM2FHEM</a> &nbsp;
<a href="#FHEMRENDERER">FHEMRENDERER</a> &nbsp;
<a href="#FHEMWEB">FHEMWEB</a> &nbsp;
<a href="#FileLog">FileLog</a> &nbsp;
@ -506,7 +507,7 @@ A line ending with \ will be concatenated with the next one, so long lines
<a name="inform"></a>
<h3>inform</h3>
<ul>
<code>inform [on|off|timer]</code> <br>
<code>inform [on|off|timer|raw]</code> <br>
<br>
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
@ -4694,6 +4695,66 @@ Terminating
</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 &lt;name&gt; FHEM2FHEM &lt;host:portnr&gt; [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>
<h3>FHEMWEB</h3>
<ul>

View File

@ -44,6 +44,7 @@ sub AnalyzeCommand($$);
sub AnalyzeCommandChain($$);
sub AnalyzeInput($);
sub AssignIoPort($);
sub addToAttrList($);
sub CallFn(@);
sub CommandChain($$);
sub CheckDuplicate($$);
@ -87,6 +88,7 @@ sub CommandGet($$);
sub CommandHelp($$);
sub CommandInclude($$);
sub CommandInform($$);
sub CommandIOWrite($$);
sub CommandList($$);
sub CommandModify($$);
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(%data); # Hash for user data
use vars qw($devcount); # To sort the devices
use vars qw(%defaultattr); # Default attributes, used by FHEM2FHEM
use vars qw($reread_active);
@ -154,13 +157,12 @@ my %client; # Client array
my $rcvdquit; # Used for quit handling in init files
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 %defaultattr; # Default attributes
my %intAt; # Internal at timer hash.
my $nextat; # Time when next timer will be triggered.
my $intAtCnt=0;
my %duplicate; # Pool of received msg for multi-fhz/cul setups
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 =
"where <name> is either:\n" .
"- a single device name\n" .
@ -201,7 +203,9 @@ $modules{_internal_}{AttrFn} = "GlobalAttr";
"include" => { Fn=>"CommandInclude",
Hlp=>"<filename>,read the commands from <filenname>" },
"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",
Hlp=>"[devspec],list definitions and status info" },
"modify" => { Fn=>"CommandModify",
@ -533,6 +537,33 @@ IOWrite($@)
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
AnalyzeInput($)
@ -1135,10 +1166,12 @@ AssignIoPort($)
{
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) {
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
$hash->{IODev} = $defs{$p};
last;
@ -1675,7 +1708,8 @@ CommandInform($$)
$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/) {
delete($client{$cl}{inform});
} else {
@ -1922,7 +1956,7 @@ DoTrigger($$)
################
# Inform
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();
if($attr{global}{mseclog}) {
my ($seconds, $microseconds) = gettimeofday();
@ -1930,7 +1964,6 @@ DoTrigger($$)
}
for(my $i = 0; $i < $max; $i++) {
my $state = $defs{$dev}{CHANGED}[$i];
my $fe = "$dev:$state";
syswrite($client{$c}{fd},
($client{$c}{inform} eq "timer" ? "$tn " : "") .
"$defs{$dev}{TYPE} $dev $state\n");
@ -2125,7 +2158,11 @@ Dispatch($$$)
my @found;
foreach my $m (sort { $modules{$a}{ORDER} cmp $modules{$b}{ORDER} }
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
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
foreach my $found (@found) {
@ -2270,3 +2316,20 @@ ReadingsVal($$$)
}
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);
}