RFXCOM changes for FHEM2FHEM, DevIO.pm usage, minor changes

git-svn-id: https://fhem.svn.sourceforge.net/svnroot/fhem/trunk/fhem@1474 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
wherzig
2012-04-22 14:17:47 +00:00
parent acc9a52412
commit 2c8c606f5a
5 changed files with 112 additions and 282 deletions

View File

@@ -8,13 +8,11 @@
# define RFXCOM RFXCOM /dev/ttyUSB0 # define RFXCOM RFXCOM /dev/ttyUSB0
# #
# The module also has code to access LAN based RFXCOM receivers like 81003 and 83003. # The module also has code to access LAN based RFXCOM receivers like 81003 and 83003.
# This was tested by me with the help of the RFXCOM people (Thanks to Bert!) and works
# for the basic functions. However a disconnect of the TCP connection is currectly
# not detected.
# #
# To use it define the IP-Adresss and the Port: # To use it define the IP-Adresss and the Port:
# define RFXCOM RFXCOM 192.168.169.111:10001 # define RFXCOM RFXCOM 192.168.169.111:10001
# optionally you may issue not to initialize the device (useful if you share an RFXCOM device with other programs) # optionally you may issue not to initialize the device (useful for FHEM2FHEM raw
# and if you share an RFXCOM device with other programs)
# define RFXCOM RFXCOM 192.168.169.111:10001 noinit # define RFXCOM RFXCOM 192.168.169.111:10001 noinit
# #
# The RFXCOM receivers supports lots of protocols that may be implemented for FHEM # The RFXCOM receivers supports lots of protocols that may be implemented for FHEM
@@ -26,15 +24,25 @@
# It is derived from xPL Perl (http://www.xpl-perl.org.uk/). I suggest to look there # It is derived from xPL Perl (http://www.xpl-perl.org.uk/). I suggest to look there
# if you want to implement other protocols. # if you want to implement other protocols.
# #
# Willi Herzig, 2010 ###########################
# #
# This script is distributed in the hope that it will be useful, # Copyright (C) 2010,2012 Willi Herzig
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# #
################################################################################# # This program is distributed in the hope that it will be useful,
# derived from 00_CUL.pm # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The GNU General Public License may also be found at http://www.gnu.org/licenses/gpl-2.0.html .
########################### ###########################
# $Id$ # $Id$
package main; package main;
@@ -62,27 +70,30 @@ RFXCOM_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
# Provider require "$attr{global}{modpath}/FHEM/DevIo.pm";
# Provider
$hash->{ReadFn} = "RFXCOM_Read"; $hash->{ReadFn} = "RFXCOM_Read";
$hash->{WriteFn} = "RFXCOM_Write";
$hash->{Clients} = $hash->{Clients} =
":RFXMETER:OREGON:RFXX10REC:RFXELSE:"; ":RFXMETER:OREGON:RFXX10REC:RFXELSE:";
my %mc = ( my %mc = (
"1:RFXMETER" => "^0.*", "1:RFXMETER" => "^30.*",
"2:OREGON" => "^[\x38-\x78].*", "2:OREGON" => "^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*", #38-78
"3:RFXX10REC" => "^(\\ |\\)).*", # 0x20 or 0x29 "3:RFXX10REC" => "^(20|29).*",
"4:RFXELSE" => "^.*", #"4:RFXELSE" => "^.*", # RFXELSE no longer after changing from bin to hexstring
); );
$hash->{MatchList} = \%mc; $hash->{MatchList} = \%mc;
$hash->{ReadyFn} = "RFXCOM_Ready"; $hash->{ReadyFn} = "RFXCOM_Ready";
# Normal devices # Normal devices
$hash->{DefFn} = "RFXCOM_Define"; $hash->{DefFn} = "RFXCOM_Define";
$hash->{UndefFn} = "RFXCOM_Undef"; $hash->{UndefFn} = "RFXCOM_Undef";
$hash->{GetFn} = "RFXCOM_Get"; $hash->{GetFn} = "RFXCOM_Get";
$hash->{SetFn} = "RFXCOM_Set"; $hash->{SetFn} = "RFXCOM_Set";
$hash->{StateFn} = "RFXCOM_SetState"; $hash->{StateFn} = "RFXCOM_SetState";
$hash->{AttrList}= "do_not_notify:1,0 do_not_init:1:0 loglevel:0,1,2,3,4,5,6"; $hash->{AttrList}= "do_not_notify:1,0 dummy:1,0 do_not_init:1:0 loglevel:0,1,2,3,4,5,6";
$hash->{ShutdownFn} = "RFXCOM_Shutdown"; $hash->{ShutdownFn} = "RFXCOM_Shutdown";
} }
@@ -96,7 +107,7 @@ RFXCOM_Define($$)
return "wrong syntax: define <name> RFXCOM devicename [noinit]" return "wrong syntax: define <name> RFXCOM devicename [noinit]"
if(@a != 3 && @a != 4); if(@a != 3 && @a != 4);
RFXCOM_CloseDev($hash); DevIo_CloseDev($hash);
my $name = $a[0]; my $name = $a[0];
my $dev = $a[2]; my $dev = $a[2];
@@ -108,6 +119,11 @@ RFXCOM_Define($$)
return undef; return undef;
} }
if($dev !~ /\@/) {
Log 1,"RFXCOM: added baudrate 4800 as default";
$dev .= "\@4800";
}
if(defined($opt)) { if(defined($opt)) {
if($opt eq "noinit") { if($opt eq "noinit") {
Log 1, "RFXCOM: $name no init is done"; Log 1, "RFXCOM: $name no init is done";
@@ -119,10 +135,27 @@ RFXCOM_Define($$)
$hash->{DeviceName} = $dev; $hash->{DeviceName} = $dev;
my $ret = RFXCOM_OpenDev($hash, 0); my $ret = DevIo_OpenDev($hash, 0, "RFXCOM_DoInit");
return $ret; return $ret;
} }
#####################################
# Input is hexstring
sub
RFXCOM_Write($$$)
{
my ($hash,$fn,$msg) = @_;
my $name = $hash->{NAME};
my $ll5 = GetLogLevel($name,5);
return if(!defined($fn));
my $bstring;
$bstring = "$fn$msg";
Log $ll5, "$hash->{NAME} sending $bstring";
DevIo_SimpleWrite($hash, $bstring, 1);
}
##################################### #####################################
sub sub
@@ -142,7 +175,7 @@ RFXCOM_Undef($$)
} }
} }
RFXCOM_CloseDev($hash); DevIo_CloseDev($hash);
return undef; return undef;
} }
@@ -164,7 +197,8 @@ RFXCOM_Set($@)
my $name=$a[0]; my $name=$a[0];
my $reading= $a[1]; my $reading= $a[1];
$msg="$name => No Set function ($reading) implemented"; $msg="$name => No Set function ($reading) implemented";
return $msg;
return $msg;
} }
##################################### #####################################
@@ -198,18 +232,13 @@ RFXCOM_Clear($)
# clear buffer: # clear buffer:
if($hash->{USBDev}) { if($hash->{USBDev}) {
while ($hash->{USBDev}->lookfor()) { while ($hash->{USBDev}->lookfor()) {
$buf = RFXCOM_SimpleRead($hash); $buf = DevIo_SimpleRead($hash);
} }
} }
if($hash->{TCPDev}) { if($hash->{TCPDev}) {
# TODO # TODO
# while ($hash->{USBDev}->lookfor()) {
# $buf = RFXCOM_SimpleRead($hash);
# }
return $buf; return $buf;
} }
} }
##################################### #####################################
@@ -223,8 +252,6 @@ RFXCOM_DoInit($)
my $buf; my $buf;
my $char = undef ; my $char = undef ;
RFXCOM_Clear($hash);
if(defined($attr{$name}) && defined($attr{$name}{"do_not_init"})) { if(defined($attr{$name}) && defined($attr{$name}{"do_not_init"})) {
Log 1, "RFXCOM: defined with noinit. Do not send init string to device."; Log 1, "RFXCOM: defined with noinit. Do not send init string to device.";
$hash->{STATE} = "Initialized" if(!$hash->{STATE}); $hash->{STATE} = "Initialized" if(!$hash->{STATE});
@@ -236,15 +263,18 @@ RFXCOM_DoInit($)
return undef; return undef;
} }
RFXCOM_Clear($hash);
# #
# Init # Init
my $init = pack('H*', 'F02C'); my $init = pack('H*', 'F02C');
RFXCOM_SimpleWrite($hash, $init); DevIo_SimpleWrite($hash, $init, 0);
sleep(1); sleep(1);
$buf = RFXCOM_SimpleRead($hash); $buf = DevIo_TimeoutRead($hash, 0.1);
if (defined($buf)) { $char = ord($buf); } if (defined($buf)) { $char = ord($buf); }
if (! $buf) { if (! $buf) {
Log 1, "RFXCOM: Initialization Error $name: no char read";
return "RFXCOM: Initialization Error $name: no char read"; return "RFXCOM: Initialization Error $name: no char read";
} elsif ($char ne 0x2c) { } elsif ($char ne 0x2c) {
my $hexline = unpack('H*', $buf); my $hexline = unpack('H*', $buf);
@@ -275,10 +305,10 @@ RFXCOM_Read($)
my $char; my $char;
my $mybuf = RFXCOM_SimpleRead($hash); my $mybuf = DevIo_SimpleRead($hash);
if(!defined($mybuf) || length($mybuf) == 0) { if(!defined($mybuf) || length($mybuf) == 0) {
RFXCOM_Disconnected($hash); DevIo_Disconnected($hash);
return ""; return "";
} }
@@ -303,7 +333,7 @@ RFXCOM_Read($)
#$hexline = unpack('H*', $rfxcom_data); #$hexline = unpack('H*', $rfxcom_data);
#Log 1, "RFXCOM_Read rfxcom_data '$hexline'"; #Log 1, "RFXCOM_Read rfxcom_data '$hexline'";
# #
RFXCOM_Parse($hash, $hash, $name, $rmsg); RFXCOM_Parse($hash, $hash, $name, unpack('H*', $rmsg));
$bits = ord(substr($rfxcom_data,0,1)); $bits = ord(substr($rfxcom_data,0,1));
$num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; } $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; }
} }
@@ -312,35 +342,31 @@ RFXCOM_Read($)
$hash->{PARTIAL} = $rfxcom_data; $hash->{PARTIAL} = $rfxcom_data;
} }
sub sub
RFXCOM_Parse($$$$) RFXCOM_Parse($$$$)
{ {
my ($hash, $iohash, $name, $rmsg) = @_; my ($hash, $iohash, $name, $rmsg) = @_;
my $hexline = unpack('H*', $rmsg); Log 5, "RFXCOM_Parse1 '$rmsg'";
Log 5, "RFXCOM_Parse1 '$hexline'";
my %addvals; my %addvals;
# Parse only if message is different within 2 seconds # Parse only if message is different within 2 seconds
# (some Oregon sensors always sends the message twice, X10 security sensors even sends the message five times) # (some Oregon sensors always sends the message twice, X10 security sensors even sends the message five times)
if (("$last_rmsg" ne "$rmsg") || (time() - $last_time) > 1) { if (("$last_rmsg" ne "$rmsg") || (time() - $last_time) > 1) {
Log 5, "RFXCOM_Dispatch '$hexline'"; Log 5, "RFXCOM_Dispatch '$rmsg'";
#Log 1, "RFXCOM_Dispatch '$hexline'";
Dispatch($hash, $rmsg, \%addvals); Dispatch($hash, $rmsg, \%addvals);
$hash->{"${name}_MSGCNT"}++; $hash->{"${name}_MSGCNT"}++;
$hash->{"${name}_TIME"} = TimeNow(); $hash->{"${name}_TIME"} = TimeNow();
$hash->{RAWMSG} = $rmsg; $hash->{RAWMSG} = $rmsg;
} else { } else {
#Log 1, "RFXCOM_Dispatch '$hexline' dup"; #Log 1, "RFXCOM_Dispatch '$rmsg' dup";
#Log 1, "<-duplicate->"; #Log 1, "<-duplicate->";
} }
$last_rmsg = $rmsg; $last_rmsg = $rmsg;
$last_time = time(); $last_time = time();
#$hexline = unpack('H*', $rmsg);
#Log 1, "RFXCOM_Parse2 '$hexline'";
} }
@@ -350,7 +376,7 @@ RFXCOM_Ready($)
{ {
my ($hash) = @_; my ($hash) = @_;
return RFXCOM_OpenDev($hash, 1) return DevIo_OpenDev($hash, 1, "RFXCOM_Ready")
if($hash->{STATE} eq "disconnected"); if($hash->{STATE} eq "disconnected");
# This is relevant for windows/USB only # This is relevant for windows/USB only
@@ -359,205 +385,4 @@ RFXCOM_Ready($)
return ($InBytes>0); return ($InBytes>0);
} }
########################
sub
RFXCOM_SimpleWrite(@)
{
my ($hash, $msg) = @_;
return if(!$hash);
$hash->{USBDev}->write($msg) if($hash->{USBDev});
syswrite($hash->{TCPDev}, $msg) if($hash->{TCPDev});
#my $hexline = unpack('H*', $msg);
#Log 1, "RFXCOM_SimpleWrite '$hexline'";
select(undef, undef, undef, 0.001);
}
########################
sub
RFXCOM_SimpleRead($)
{
my ($hash) = @_;
my $buf;
if($hash->{USBDev}) {
$buf = $hash->{USBDev}->read(1) ;
#my $hexline = unpack('H*', $buf);
#Log 1, "RFXCOM: RFXCOM_SimpleRead1 '$hexline'";
if (!defined($buf) || length($buf) == 0) {
#sleep(1);
$buf = $hash->{USBDev}->read(1) ;
}
return $buf;
}
if($hash->{TCPDev}) {
my $buf;
if(!defined(sysread($hash->{TCPDev}, $buf, 1))) {
RFXCOM_Disconnected($hash);
return undef;
}
return $buf;
}
return undef;
}
########################
sub
RFXCOM_CloseDev($)
{
my ($hash) = @_;
my $name = $hash->{NAME};
my $dev = $hash->{DeviceName};
return if(!$dev);
Log 1, "RFXCOM: closing $dev";
if($hash->{TCPDev}) {
$hash->{TCPDev}->close();
delete($hash->{TCPDev});
} elsif($hash->{USBDev}) {
$hash->{USBDev}->close() ;
delete($hash->{USBDev});
}
delete($selectlist{"$name.$dev"});
delete($readyfnlist{"$name.$dev"});
delete($hash->{FD});
}
########################
sub
RFXCOM_OpenDev($$)
{
my ($hash, $reopen) = @_;
my $dev = $hash->{DeviceName};
my $name = $hash->{NAME};
my $po;
$hash->{PARTIAL} = "";
Log 3, "RFXCOM opening $name device $dev"
if(!$reopen);
if($dev =~ m/^(.+):([0-9]+)$/) { # host:port
# This part is called every time the timeout (5sec) is expired _OR_
# somebody is communicating over another TCP connection. As the connect
# for non-existent devices has a delay of 3 sec, we are sitting all the
# time in this connect. NEXT_OPEN tries to avoid this problem.
if($hash->{NEXT_OPEN} && time() < $hash->{NEXT_OPEN}) {
return;
}
my $conn = IO::Socket::INET->new(PeerAddr => $dev);
if($conn) {
delete($hash->{NEXT_OPEN});
} else {
Log(3, "RFXCOM: Can't connect to $dev: $!") if(!$reopen);
$readyfnlist{"$name.$dev"} = $hash;
$hash->{STATE} = "disconnected";
$hash->{NEXT_OPEN} = time()+60;
RFXCOM_Disconnected($hash);
return "";
}
$hash->{TCPDev} = $conn;
$hash->{FD} = $conn->fileno();
delete($readyfnlist{"$name.$dev"});
$selectlist{"$name.$dev"} = $hash;
} else { # USB Device
if ($^O=~/Win/) {
require Win32::SerialPort;
$po = new Win32::SerialPort ($dev);
} else {
#Log(1, "RFXCOM: new Device");
require Device::SerialPort;
$po = new Device::SerialPort ($dev);
}
if(!$po) {
return undef if($reopen);
Log(3, "RFXCOM: Can't open $dev: $!");
$readyfnlist{"$name.$dev"} = $hash;
$hash->{STATE} = "disconnected";
return "";
}
$hash->{USBDev} = $po;
if( $^O =~ /Win/ ) {
$readyfnlist{"$name.$dev"} = $hash;
} else {
$hash->{FD} = $po->FILENO;
delete($readyfnlist{"$name.$dev"});
$selectlist{"$name.$dev"} = $hash;
}
#$po->reset_error || Log 1, "RFXCOM reset_error";
$po->databits(8) || Log 1, "RFXCOM could not set databits";
$po->baudrate(4800) || Log 1, "RFXCOM could not set baudrate";
$po->parity('none') || Log 1, "RFXCOM could not set parity";
$po->stopbits(1) || Log 1, "RFXCOM could not set stopbits";
$po->handshake('none') || Log 1, "RFXCOM could not set handshake";
$po->datatype('raw') || Log 1, "RFXCOM could not set datatype";
#$po->lookclear || Log 1, "RFXCOM could not set lookclear";
$po->write_settings || Log 1, "RFXCOM could not write_settings $dev";
$hash->{po} = $po;
$hash->{socket} = 0;
Log 1, "RFXCOM: RFXCOM_OpenDev $dev done";
}
if($reopen) {
Log 1, "RFXCOM: $dev reappeared ($name)";
} else {
Log 3, "RFXCOM: device opened";
}
$hash->{STATE}=""; # Allow InitDev to set the state
my $ret = RFXCOM_DoInit($hash);
if($ret) {
# try again
Log 1, "RFXCOM: Cannot init $dev, at first try. Trying again.";
my $ret = RFXCOM_DoInit($hash);
if($ret) {
RFXCOM_CloseDev($hash);
Log 1, "RFXCOM: Cannot init $dev, ignoring it";
return "RFXCOM: Error Init string.";
}
}
DoTrigger($name, "CONNECTED") if($reopen);
return $ret;
}
sub
RFXCOM_Disconnected($)
{
my $hash = shift;
my $dev = $hash->{DeviceName};
my $name = $hash->{NAME};
return if(!defined($hash->{FD})); # Already deleted or RFR
Log 1, "RFXCOM: $dev disconnected, waiting to reappear";
RFXCOM_CloseDev($hash);
$readyfnlist{"$name.$dev"} = $hash; # Start polling
$hash->{STATE} = "disconnected";
# Without the following sleep the open of the device causes a SIGSEGV,
# and following opens block infinitely. Only a reboot helps.
sleep(5);
DoTrigger($name, "DISCONNECTED");
}
1; 1;

View File

@@ -51,8 +51,7 @@ OREGON_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
$hash->{Match} = "^[\x38-\x78].*"; $hash->{Match} = "^(3[8-9A-F]|[4-6][0-9A-F]|7[0-8]).*", #38-78
#$hash->{Match} = "^[^\x30]";
$hash->{DefFn} = "OREGON_Define"; $hash->{DefFn} = "OREGON_Define";
$hash->{UndefFn} = "OREGON_Undef"; $hash->{UndefFn} = "OREGON_Undef";
$hash->{ParseFn} = "OREGON_Parse"; $hash->{ParseFn} = "OREGON_Parse";
@@ -204,6 +203,10 @@ my %types =
part => 'WGR918', checksum => \&checksum4, method => \&wgr918_anemometer, part => 'WGR918', checksum => \&checksum4, method => \&wgr918_anemometer,
}, },
# RGR126, RGR682, RGR918: # RGR126, RGR682, RGR918:
type_length_key(0x2a1d, 80) =>
{
part => 'RGR918', checksum => \&checksum6plus, method => \&common_rain,
},
type_length_key(0x2a1d, 84) => type_length_key(0x2a1d, 84) =>
{ {
part => 'RGR918', checksum => \&checksum6plus, method => \&common_rain, part => 'RGR918', checksum => \&checksum6plus, method => \&common_rain,
@@ -716,30 +719,32 @@ sub raw {
$_[0]->{raw} or $_[0]->{raw} = pack 'H*', $_[0]->{hex}; $_[0]->{raw} or $_[0]->{raw} = pack 'H*', $_[0]->{hex};
} }
# -----------------------------
# -----------------------------
sub sub
OREGON_Parse($$) OREGON_Parse($$)
{ {
my ($hash, $msg) = @_; my ($hash, $msg) = @_;
my $time = time(); my $time = time();
my $hexline = unpack('H*', $msg);
if ($time_old ==0) { if ($time_old ==0) {
Log 5, "OREGON: decoding delay=0 hex=$hexline"; Log 5, "OREGON: decoding delay=0 hex=$msg";
} else { } else {
my $time_diff = $time - $time_old ; my $time_diff = $time - $time_old ;
Log 5, "OREGON: decoding delay=$time_diff hex=$hexline"; Log 5, "OREGON: decoding delay=$time_diff hex=$msg";
} }
$time_old = $time; $time_old = $time;
# convert to binary
my $bin_msg = pack('H*', $msg);
# convert string to array of bytes. Skip length byte # convert string to array of bytes. Skip length byte
my @rfxcom_data_array = (); my @rfxcom_data_array = ();
foreach (split(//, substr($msg,1))) { foreach (split(//, substr($bin_msg,1))) {
push (@rfxcom_data_array, ord($_) ); push (@rfxcom_data_array, ord($_) );
} }
my $bits = ord($msg); my $bits = ord($bin_msg);
my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; } my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; }
my $type1 = $rfxcom_data_array[0]; my $type1 = $rfxcom_data_array[0];
@@ -754,8 +759,8 @@ OREGON_Parse($$)
my $rec = $types{$key} || $types{$key&0xfffff}; my $rec = $types{$key} || $types{$key&0xfffff};
unless ($rec) { unless ($rec) {
#Log 3, "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bits message='$hexline'."; #Log 1, "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bits message='$msg'.";
Log 4, "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bits message='$hexline'."; Log 4, "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bits message='$msg'.";
return "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bits.\n"; return "OREGON: ERROR: Unknown sensor_id=$sensor_id bits=$bits.\n";
} }
@@ -821,7 +826,7 @@ OREGON_Parse($$)
$sensor = "humidity"; $sensor = "humidity";
$def->{READINGS}{$sensor}{TIME} = $tm; $def->{READINGS}{$sensor}{TIME} = $tm;
$def->{READINGS}{$sensor}{VAL} = $i->{current}; $def->{READINGS}{$sensor}{VAL} = $i->{current};
$def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};; $def->{CHANGED}[$n++] = $sensor . ": " . $i->{current};
} }
elsif ($i->{type} eq "battery") { elsif ($i->{type} eq "battery") {
#printf "Batterie %d%s; ",$i->{current},$i->{units}; #printf "Batterie %d%s; ",$i->{current},$i->{units};

View File

@@ -34,7 +34,7 @@ RFXMETER_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
$hash->{Match} = "^0.*"; $hash->{Match} = "^30.*";
$hash->{DefFn} = "RFXMETER_Define"; $hash->{DefFn} = "RFXMETER_Define";
$hash->{UndefFn} = "RFXMETER_Undef"; $hash->{UndefFn} = "RFXMETER_Undef";
$hash->{ParseFn} = "RFXMETER_Parse"; $hash->{ParseFn} = "RFXMETER_Parse";
@@ -142,7 +142,7 @@ sub parse_RFXmeter {
} }
#my $kwh = ( ($bytes->[4]<<16) + ($bytes->[2]<<8) + ($bytes->[3]) ) / 100; #my $kwh = ( ($bytes->[4]<<16) + ($bytes->[2]<<8) + ($bytes->[3]) ) / 100;
#Log 1, "RFXMETER: kwh=$kwh"; #Log 1, "RFXMETER: kwh=$kwh";
my $current = ($bytes->[4]<<16) + ($bytes->[2]<<8) + ($bytes->[3]) ; my $current = ($bytes->[4] << 16) + ($bytes->[2] << 8) + ($bytes->[3]);
Log 4, "RFXMETER: current=$current"; Log 4, "RFXMETER: current=$current";
my $device_name = "RFXMeter".$DOT.$device; my $device_name = "RFXMeter".$DOT.$device;
@@ -194,24 +194,26 @@ RFXMETER_Parse($$)
my ($hash, $msg) = @_; my ($hash, $msg) = @_;
my $time = time(); my $time = time();
my $hexline = unpack('H*', $msg);
if ($time_old ==0) { if ($time_old ==0) {
Log 5, "RFXMETER: decoding delay=0 hex=$hexline"; Log 5, "RFXMETER: decoding delay=0 hex=$msg";
} else { } else {
my $time_diff = $time - $time_old ; my $time_diff = $time - $time_old ;
Log 5, "RFXMETER: decoding delay=$time_diff hex=$hexline"; Log 5, "RFXMETER: decoding delay=$time_diff hex=$msg";
} }
$time_old = $time; $time_old = $time;
# convert to binary
my $bin_msg = pack('H*', $msg);
# convert string to array of bytes. Skip length byte # convert string to array of bytes. Skip length byte
my @rfxcom_data_array = (); my @rfxcom_data_array = ();
foreach (split(//, substr($msg,1))) { foreach (split(//, substr($bin_msg,1))) {
push (@rfxcom_data_array, ord($_) ); push (@rfxcom_data_array, ord($_) );
} }
my $bits = ord($msg); my $bits = ord($bin_msg);
my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; } my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; }
Log 4, "RFXMETER: bits=$bits num_bytes=$num_bytes hex=$hexline"; Log 4, "RFXMETER: bits=$bits num_bytes=$num_bytes hex=$msg";
my @res = ""; my @res = "";
if ($bits == 48) { if ($bits == 48) {
@@ -219,8 +221,7 @@ RFXMETER_Parse($$)
#parse_RFXmeter(\@rfxcom_data_array); #parse_RFXmeter(\@rfxcom_data_array);
} else { } else {
# this should never happen as this module parses only RFXmeter messages # this should never happen as this module parses only RFXmeter messages
my $hexline = unpack('H*', $msg); Log 1, "RFXMETER: error unknown hex=$msg";
Log 1, "RFXMETER: error unknown hex=$hexline";
} }
return @res; return @res;

View File

@@ -63,8 +63,7 @@ RFXX10REC_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
#$hash->{Match} = "^\\).*"; # 0x29 $hash->{Match} = "^(20|29).*";
$hash->{Match} = "^(\\ |\\)).*"; # 0x20 or 0x29
$hash->{DefFn} = "RFXX10REC_Define"; $hash->{DefFn} = "RFXX10REC_Define";
$hash->{UndefFn} = "RFXX10REC_Undef"; $hash->{UndefFn} = "RFXX10REC_Undef";
$hash->{ParseFn} = "RFXX10REC_Parse"; $hash->{ParseFn} = "RFXX10REC_Parse";
@@ -525,37 +524,39 @@ RFXX10REC_Parse($$)
my ($hash, $msg) = @_; my ($hash, $msg) = @_;
my $time = time(); my $time = time();
my $hexline = unpack('H*', $msg);
if ($time_old ==0) { if ($time_old ==0) {
Log 5, "RFXX10REC: decoding delay=0 hex=$hexline"; Log 5, "RFXX10REC: decoding delay=0 hex=$msg";
} else { } else {
my $time_diff = $time - $time_old ; my $time_diff = $time - $time_old ;
Log 5, "RFXX10REC: decoding delay=$time_diff hex=$hexline"; Log 5, "RFXX10REC: decoding delay=$time_diff hex=$msg";
} }
$time_old = $time; $time_old = $time;
# convert to binary
my $bin_msg = pack('H*', $msg);
# convert string to array of bytes. Skip length byte # convert string to array of bytes. Skip length byte
my @rfxcom_data_array = (); my @rfxcom_data_array = ();
foreach (split(//, substr($msg,1))) { foreach (split(//, substr($bin_msg,1))) {
push (@rfxcom_data_array, ord($_) ); push (@rfxcom_data_array, ord($_) );
} }
my $bits = ord($msg); my $bits = ord($bin_msg);
my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; } my $num_bytes = $bits >> 3; if (($bits & 0x7) != 0) { $num_bytes++; }
my $res = ""; my $res = "";
if ($bits == 41) { if ($bits == 41) {
Log 1, "RFXX10REC: bits=$bits num_bytes=$num_bytes hex=$hexline" if ($RFXX10REC_debug == 1); Log 1, "RFXX10REC: bits=$bits num_bytes=$num_bytes hex=$msg" if ($RFXX10REC_debug == 1);
$res = RFXX10REC_parse_X10Sec(\@rfxcom_data_array); $res = RFXX10REC_parse_X10Sec(\@rfxcom_data_array);
Log 1, "RFXX10REC: unsupported hex=$hexline" if ($res ne "" && $res !~ /^UNDEFINED.*/); Log 1, "RFXX10REC: unsupported hex=$msg" if ($res ne "" && $res !~ /^UNDEFINED.*/);
return $res; return $res;
} elsif ($bits == 32) { } elsif ($bits == 32) {
Log 1, "RFXX10REC: bits=$bits num_bytes=$num_bytes hex=$hexline" if ($RFXX10REC_debug == 1); Log 1, "RFXX10REC: bits=$bits num_bytes=$num_bytes hex=$msg" if ($RFXX10REC_debug == 1);
$res = RFXX10REC_parse_X10(\@rfxcom_data_array); $res = RFXX10REC_parse_X10(\@rfxcom_data_array);
Log 1, "RFXX10REC: unsupported hex=$hexline" if ($res ne "" && $res !~ /^UNDEFINED.*/); Log 1, "RFXX10REC: unsupported hex=$msg" if ($res ne "" && $res !~ /^UNDEFINED.*/);
return $res; return $res;
} else { } else {
Log 0, "RFXX10REC: bits=$bits num_bytes=$num_bytes hex=$hexline"; Log 0, "RFXX10REC: bits=$bits num_bytes=$num_bytes hex=$msg";
} }
return ""; return "";

View File

@@ -6225,7 +6225,6 @@ These receivers supports many protocols like Oregon Scientific weather sensors,
</li> </li>
<li> 42_RFXMETER.pm (see device <a href="#RFXMETER">RFXMETER</a>): Process RFXCOM RFXMeter devices. See <a href="http://www.rfxcom.com/sensors.htm">http://www.rfxcom.com/sensors.htm</a>.</li> <li> 42_RFXMETER.pm (see device <a href="#RFXMETER">RFXMETER</a>): Process RFXCOM RFXMeter devices. See <a href="http://www.rfxcom.com/sensors.htm">http://www.rfxcom.com/sensors.htm</a>.</li>
<li> 43_RFXX10REC.pm (see device <a href="#RFXX10REC">RFXX10REC</a>): Process X10 security and X10 lighting devices. </li> <li> 43_RFXX10REC.pm (see device <a href="#RFXX10REC">RFXX10REC</a>): Process X10 security and X10 lighting devices. </li>
<li> 44_RFXELSE.pm: Process and display all other messages. This module shows you messages that could not be handled by the other modules. It is useful to see RF receiption problems.</li>
</ul> </ul>
<br> <br>
Note: this module requires the Device::SerialPort or Win32::SerialPort module Note: this module requires the Device::SerialPort or Win32::SerialPort module
@@ -6253,7 +6252,7 @@ These receivers supports many protocols like Oregon Scientific weather sensors,
192.168.1.5:10001 192.168.1.5:10001
</ul> </ul>
<ul> <ul>
noninit is optional and issues that the RFXCOM device should not be initialized. This is useful if you share a RFXCOM device. It is also useful for testing to simulate a RFXCOM receiver via netcat. noninit is optional and issues that the RFXCOM device should not be initialized. This is useful if you share a RFXCOM device. It is also useful for testing to simulate a RFXCOM receiver via netcat or via FHEM2FHEM.
<br> <br>
<br> <br>
Example: <br> Example: <br>
@@ -7218,7 +7217,6 @@ AB600, Duewi, DomiaLite, COCO) and others. <br>
<li> 46_TRX_SECURITY.pm (see device <a href="#TRX_SECURITY">TRX_SECURITY</a>): Receive X10, KD101 and Visonic security sensors.</li> <li> 46_TRX_SECURITY.pm (see device <a href="#TRX_SECURITY">TRX_SECURITY</a>): Receive X10, KD101 and Visonic security sensors.</li>
<li> 46_TRX_LIGHT.pm (see device <a href="#RFXX10REC">RFXX10REC</a>): Process X10, ARC, ELRO AB400D, Waveman, Chacon EMW200, IMPULS, AC, HomeEasy EU and ANSLUT lighting devices (switches and remote control). ARC is a protocol used by devices from HomeEasy, KlikAanKlikUit, ByeByeStandBy, Intertechno, ELRO, AB600, Duewi, DomiaLite and COCO with address code wheels. AC is the protocol used by different brands with units having a learning mode button: <li> 46_TRX_LIGHT.pm (see device <a href="#RFXX10REC">RFXX10REC</a>): Process X10, ARC, ELRO AB400D, Waveman, Chacon EMW200, IMPULS, AC, HomeEasy EU and ANSLUT lighting devices (switches and remote control). ARC is a protocol used by devices from HomeEasy, KlikAanKlikUit, ByeByeStandBy, Intertechno, ELRO, AB600, Duewi, DomiaLite and COCO with address code wheels. AC is the protocol used by different brands with units having a learning mode button:
KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.</li> KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.</li>
<li> 46_TRX_ELSE.pm: Process and display all other messages. This module shows you messages that could not be handled by the other modules. It is useful to see RF receiption problems.</li>
</ul> </ul>
<br> <br>
Note: this module requires the Device::SerialPort or Win32::SerialPort module Note: this module requires the Device::SerialPort or Win32::SerialPort module
@@ -7246,7 +7244,7 @@ KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.</li>
192.168.1.5:10001 192.168.1.5:10001
</ul> </ul>
<ul> <ul>
noninit is optional and issues that the RFXtrx433 device should not be initialized. This is useful if you share a RFXtrx433 device via LAN. It is also useful for testing to simulate a RFXtrx433 receiver via netcat. noninit is optional and issues that the RFXtrx433 device should not be initialized. This is useful if you share a RFXtrx433 device via LAN. It is also useful for testing to simulate a RFXtrx433 receiver via netcat or via FHEM2FHEM.
<br> <br>
<br> <br>
Example: <br> Example: <br>
@@ -7705,7 +7703,7 @@ KlikAanKlikUit, NEXA, CHACON, HomeEasy UK. <br> You need to define an RFXtrx433
fhem device <i>devicename</i>, just like if it would be attached to the fhem device <i>devicename</i>, just like if it would be attached to the
local fhem. local fhem.
Drawback: only devices using the Dispatch function (CUL, FHZ, CM11, Drawback: only devices using the Dispatch function (CUL, FHZ, CM11,
SISPM, RFXCOM, TCM, TUL) generate raw messages.<br> SISPM, RFXCOM, TCM, TRX, TUL) generate raw messages.<br>
<i>devicename</i> must exist on the local <i>devicename</i> must exist on the local
fhem server too with the same name and same type as the remote device, but fhem server too with the same name and same type as the remote device, but
usually with the device-node "none", so it is only a dummy device. All usually with the device-node "none", so it is only a dummy device. All