Commit cdd1807c authored by Admin's avatar Admin
Browse files

semi-automatic bump of 2 months diff; expect this to break;

parent 02489650
Pipeline #138 passed with stages
in 32 seconds
This diff is collapsed.
##############################################
# $Id: 00_MQTT2_CLIENT.pm 22454 2020-07-23 16:36:36Z rudolfkoenig $
# $Id: 00_MQTT2_CLIENT.pm 22830 2020-09-23 14:35:44Z rudolfkoenig $
package main;
use strict;
......@@ -39,6 +39,7 @@ sub MQTT2_CLIENT_Initialize($) {
clientId
disable:1,0
disabledForIntervals
disconnectAfter
ignoreRegexp
lwt
lwtRetain
......@@ -72,7 +73,7 @@ sub MQTT2_CLIENT_Define($$) {
$hash->{connecting} = 1;
InternalTimer( 1, "MQTT2_CLIENT_connect", $hash, 0 ); # need attributes
return;
return undef;
}
sub MQTT2_CLIENT_connect($) {
......@@ -179,10 +180,16 @@ sub MQTT2_CLIENT_doinit($) {
MQTT2_CLIENT_doPublish( $hash, $r->[0], $r->[1], $r->[2], 0 );
}
}
if ( $hash->{sendHash} ) {
map { MQTT2_CLIENT_doPublish( $hash, $_->[1], $_->[2], $_->[3] ) }
@{ $hash->{sendHash} };
delete( $hash->{sendHash} );
}
MQTT2_CLIENT_updateDisconnectTimer($hash);
}
return;
return undef;
}
sub MQTT2_CLIENT_keepalive($) {
......@@ -208,7 +215,7 @@ sub MQTT2_CLIENT_keepalive($) {
sub MQTT2_CLIENT_Undef($@) {
my ( $hash, $arg ) = @_;
MQTT2_CLIENT_Disco( $hash, 1 );
return;
return undef;
}
sub MQTT2_CLIENT_Disco($;$$) {
......@@ -224,12 +231,39 @@ sub MQTT2_CLIENT_Disco($;$$) {
}
$isUndef ? DevIo_CloseDev($hash) : DevIo_Disconnected($hash);
delete( $hash->{BUF} );
if ( $hash->{disconnectTimerHash} ) {
RemoveInternalTimer( $hash->{disconnectTimerHash} );
delete( $hash->{disconnectTimerHash} );
}
readingsSingleUpdate( $hash, "state", "disconnected", 1 );
}
sub MQTT2_CLIENT_updateDisconnectTimer($) {
my ($hash) = @_;
return if ( !$hash->{FD} || $hash->{connecting} );
if ( $hash->{disconnectTimerHash} ) {
RemoveInternalTimer( $hash->{disconnectTimerHash} );
delete( $hash->{disconnectTimerHash} );
delete( $hash->{disconnectAt} );
}
my $to = AttrVal( $hash->{NAME}, "disconnectAfter", 0 );
return if ( !$to );
$to += time();
$hash->{disconnectAt} = FmtDateTime($to);
$hash->{disconnectTimerHash} = { h => $hash };
InternalTimer(
$to,
sub { MQTT2_CLIENT_Disco( $_[0]->{h}, 1 ) },
$hash->{disconnectTimerHash}, 0
);
}
sub MQTT2_CLIENT_Delete($@) {
my ( $hash, $arg ) = @_;
setKeyValue( $hash->{NAME}, undef );
return;
return undef;
}
sub MQTT2_CLIENT_Attr(@) {
......@@ -287,17 +321,32 @@ sub MQTT2_CLIENT_Attr(@) {
}
}
return;
if ( $attrName eq "disconnectAfter" ) {
$hash->{devioLoglevel} = ( $type eq "set" ? 5 : 0 );
return undef if ( !$init_done );
InternalTimer(
0,
sub {
MQTT2_CLIENT_updateDisconnectTimer($hash);
MQTT2_CLIENT_connect($hash)
if ( !$hash->{FD} && ( $type ne "set" || $param[0] eq "0" ) );
},
undef,
0
);
}
return undef;
}
sub MQTT2_CLIENT_Set($@) {
my ( $hash, @a ) = @_;
my %sets = ( password => 2, publish => 2 );
my %sets = ( password => 2, publish => 2, connect => 0, disconnect => 0 );
my $name = $hash->{NAME};
shift(@a);
return "Unknown argument ?, choose one of " . join( " ", keys %sets )
if ( !$a[0] || !$sets{ $a[0] } );
if ( !$a[0] || !defined( $sets{ $a[0] } ) );
if ( $a[0] eq "publish" ) {
shift(@a);
......@@ -320,25 +369,33 @@ sub MQTT2_CLIENT_Set($@) {
MQTT2_CLIENT_Disco($hash) if ($init_done);
}
return;
elsif ( $a[0] eq "connect" ) {
MQTT2_CLIENT_connect($hash) if ( !$hash->{FD} );
}
elsif ( $a[0] eq "disconnect" ) {
MQTT2_CLIENT_Disco( $hash, 1 ) if ( $hash->{FD} );
}
return undef;
}
my %cptype = (
0 => "RESERVED_0",
1 => "CONNECT",
2 => "CONNACK", #
3 => "PUBLISH", #
4 => "PUBACK", #
2 => "CONNACK", #
3 => "PUBLISH", #
4 => "PUBACK", #
5 => "PUBREC",
6 => "PUBREL",
7 => "PUBCOMP",
8 => "SUBSCRIBE",
9 => "SUBACK", #
9 => "SUBACK", #
10 => "UNSUBSCRIBE",
11 => "UNSUBACK",
12 => "PINGREQ",
13 => "PINGRESP", #
14 => "DISCONNECT", #
13 => "PINGRESP", #
14 => "DISCONNECT", #
15 => "RESERVED_15",
);
......@@ -429,6 +486,7 @@ sub MQTT2_CLIENT_Read($@) {
$val = substr( $pl, $off );
MQTT2_CLIENT_send( $hash, pack( "CCnC*", 0x40, 2, $pid ) )
if ($qos); # PUBACK
MQTT2_CLIENT_updateDisconnectTimer($hash);
if ( !IsDisabled($name) ) {
$val = "" if ( !defined($val) );
......@@ -471,6 +529,21 @@ sub MQTT2_CLIENT_doPublish($@) {
return if ( IsDisabled($name) );
$val = "" if ( !defined($val) );
if ( ( !$hash->{FD} || $hash->{connecting} )
&& AttrVal( $name, "disconnectAfter", undef ) )
{
$hash->{sendHash} = [] if ( !defined( $hash->{sendHash} ) );
push( @{ $hash->{sendHash} }, \@_ );
MQTT2_CLIENT_connect($hash) if ( !$hash->{connecting} );
return;
}
MQTT2_CLIENT_updateDisconnectTimer($hash);
if ( !$hash->{FD} ) {
Log3 $name, 4, "$name: publish to $topic while not connected";
return;
}
my $hdr = 0x30;
my $pi = "";
$hdr += 1 if ($retain);
......@@ -542,7 +615,7 @@ sub MQTT2_CLIENT_Write($$$) {
my $name = $hash->{NAME};
Log3 $name, 1, "$name: ERROR: Ignoring function $function";
}
return;
return undef;
}
sub MQTT2_CLIENT_calcRemainingLength($) {
......@@ -617,6 +690,11 @@ sub MQTT2_CLIENT_getStr($$) {
<li>password &lt;password&gt; value<br>
set the password, which is stored in the FHEM/FhemUtils/uniqueID file.
If the argument is empty, the password will be deleted.
</li><br>
<li>connect<br>
disconnect<br>
manually connect or disconnect to the MQTT server. Needed for some
strange embedded server.
</li>
</ul>
<br>
......@@ -658,6 +736,12 @@ sub MQTT2_CLIENT_getStr($$) {
disable dispatching of messages.
</li><br>
<a name="MQTT2_CLIENTdisconnectAfter"></a>
<li>disconnectAfter &lt;seconds&gt;<br>
if set, the connection will be closed after &lt;seconds&gt; of
inactivity, and will be automatically reopened when sending a command.
</li>
<a name="MQTT2_CLIENTignoreRegexp"></a>
<li>ignoreRegexp<br>
if $topic:$message matches ignoreRegexp, then it will be silently ignored.
......
##############################################
# $Id: 00_MQTT2_SERVER.pm 22454 2020-07-23 16:36:36Z rudolfkoenig $
# $Id: 00_MQTT2_SERVER.pm 22594 2020-08-13 07:43:24Z rudolfkoenig $
package main;
use strict;
......@@ -77,7 +77,7 @@ sub MQTT2_SERVER_keepaliveChecker($) {
my $now = gettimeofday();
my $multiplier = AttrVal( $hash->{NAME}, "keepaliveFactor", 1.5 );
if ($multiplier) {
for my $clName ( keys %{ $hash->{clients} } ) {
foreach my $clName ( keys %{ $hash->{clients} } ) {
my $cHash = $defs{$clName};
next
if ( !$cHash
......@@ -97,7 +97,7 @@ sub MQTT2_SERVER_Undef($@) {
my ( $hash, $arg ) = @_;
my $ret = TcpServer_Close($hash);
my $sname = $hash->{SNAME};
return if ( !$sname );
return undef if ( !$sname );
my $shash = $defs{$sname};
delete( $shash->{clients}{ $hash->{NAME} } );
......@@ -144,7 +144,7 @@ sub MQTT2_SERVER_Attr(@) {
return "bad $devName ignoreRegexp: $re: $@" if ($@);
}
return;
return undef;
}
sub MQTT2_SERVER_Set($@) {
......@@ -181,7 +181,7 @@ sub MQTT2_SERVER_State() {
$hash->{retain}{$k} = \%h;
}
}
return;
return undef;
}
my %cptype = (
......@@ -386,7 +386,7 @@ sub MQTT2_SERVER_Read($@) {
sub() {
delete( $hash->{answerScheduled} );
my $r = $defs{$sname}{retain};
for my $tp ( sort { $r->{$a}{ts} <=> $r->{$b}{ts} }
foreach my $tp ( sort { $r->{$a}{ts} <=> $r->{$b}{ts} }
keys %{$r} )
{
MQTT2_SERVER_sendto( $defs{$sname}, $hash, $tp,
......@@ -440,7 +440,7 @@ sub MQTT2_SERVER_Read($@) {
}
# Allow some IO inbetween, for overloaded systems
InternalTimer( 0, sub { MQTT2_SERVER_Read( $_[0], 1 ) }, $hash, 0 )
InternalTimer( 0, sub { MQTT2_SERVER_Read( $hash, 1 ) }, $hash, 0 )
if ( length( $hash->{BUF} ) > 0 );
}
......@@ -472,7 +472,7 @@ sub MQTT2_SERVER_doPublish($$$$;$) {
);
}
for my $clName ( keys %{ $server->{clients} } ) {
foreach my $clName ( keys %{ $server->{clients} } ) {
MQTT2_SERVER_sendto( $server, $defs{$clName}, $tp, $val );
}
......@@ -509,7 +509,7 @@ sub MQTT2_SERVER_sendto($$$$) {
$val = "" if ( !defined($val) );
my $dump =
( AttrVal( $shash->{NAME}, "verbose", 1 ) >= 5 ) ? $shash->{NAME} : undef;
for my $s ( keys %{ $hash->{subscriptions} } ) {
foreach my $s ( keys %{ $hash->{subscriptions} } ) {
my $re = $s;
$re =~ s,^#$,.*,g;
$re =~ s,/?#,\\b.*,g;
......@@ -551,7 +551,7 @@ sub MQTT2_SERVER_Write($$$) {
else {
Log3 $name, 1, "$name: ERROR: Ignoring function $function";
}
return;
return undef;
}
sub MQTT2_SERVER_calcRemainingLength($) {
......
# $Id: 00_Schellenberg.pm 22716 2020-09-02 19:37:55Z herrmannj $
###############################################################################
#
# This file is part of fhem.
#
# Fhem 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.
#
# Fhem is distributed in the hope that it will be useful,
# 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 fhem. If not, see <http://www.gnu.org/licenses/>.
#
#
###############################################################################
# Thanks to hypfer for doing the basic research
package main;
use 5.018;
use feature qw( lexical_subs );
use strict;
use warnings;
use utf8;
use DevIo;
no warnings qw( experimental::lexical_subs );
sub Schellenberg_Initialize {
my ($hash) = @_;
$hash->{'DefFn'} = 'Schellenberg_Define';
$hash->{'UndefFn'} = 'Schellenberg_Undef';
#$hash->{'DeleteFn'} = 'Schellenberg_Delete';
$hash->{'SetFn'} = 'Schellenberg_Set';
#$hash->{'ReadFn'} = "Schellenberg_Read";
$hash->{'ReadyFn'} = 'Schellenberg_Ready';
$hash->{'Clients'} = "Schellenberg.+";
$hash->{'MatchList'} =
{ '0:SchellenbergHandle' => '^ss[[:xdigit:]]{1}4[[:xdigit:]]{16}' };
$hash->{'AttrList'} = $readingFnAttributes;
return;
}
sub Schellenberg_Define {
my ( $hash, $def ) = @_;
my ( $name, $type, $device ) = split /\s/, $def, 3;
my $cvsid =
'$Id: 00_Schellenberg.pm 22716 2020-09-02 19:37:55Z herrmannj $';
$cvsid =~ s/^.*pm\s//;
$cvsid =~ s/Z\s\S+\s\$$/ UTC/;
$hash->{'SVN'} = $cvsid;
return "no interface given" unless ($device);
DevIo_CloseDev($hash) if ( DevIo_IsOpen($hash) );
$device .= '@38400' if ( $device !~ m/\@\d+$/ );
$hash->{'DeviceName'} = $device;
my $result = DevIo_OpenDev( $hash, 0, "Schellenberg_Init" );
return;
}
sub Schellenberg_Init {
my ($hash) = @_;
# my ($p, $id, $cmd, $counter) = unpack ('(H)(H3)', '14CB413E1A02D914A9');
# use Data::Dumper;
# print Dumper $p;
# print Dumper $id;
my $function;
# forward
sub expectVersion;
sub expectOK;
sub expectSome;
#my $test = 0;
my sub expectSome {
my ($msg) = @_;
my $found = Dispatch( $hash, $msg );
return;
}
my sub expectOK {
my ($msg) = @_;
#print "incoming OK -----> msg $msg\r";
$function = \&expectSome;
DevIo_SimpleWrite( $hash, "OK\r\n", 2 );
}
my sub expectVersion {
my ($msg) = @_;
#print "incoming VERSION -----> msg $msg\r";
$function = \&expectOK;
DevIo_SimpleWrite( $hash, "!G\r\n", 2 );
}
my sub receive {
my $data = DevIo_SimpleRead($hash);
#say "receive";
$hash->{'PARTIAL'} .= $data;
while ( $hash->{'PARTIAL'} =~ m/\r\n/ ) {
( my $msg, $hash->{'PARTIAL'} ) =
split( /\r\n/, $hash->{'PARTIAL'}, 2 );
$function->($msg);
}
}
$hash->{'directReadFn'} = \&receive;
$function = \&expectVersion;
DevIo_SimpleWrite( $hash, "!?\r\n", 2 );
}
sub Schellenberg_Undef {
my ($hash) = @_;
RemoveInternalTimer( $hash, \&SSchellenberg_ResetPairTimer );
DevIo_CloseDev($hash);
return undef;
}
sub Schellenberg_Set {
my ( $hash, $name, $cmd, @args ) = @_;
return "Unknown argument $cmd, choose one of pair" if ( $cmd eq '?' );
if ( $cmd eq 'send' and $args[0] ) {
DevIo_SimpleWrite( $hash, "$args[0]\r\n", 2 );
}
elsif ( $cmd eq 'pair' ) {
my $t = $args[0] || 60;
return 'missing time (seconds)' if ( $t !~ m/[0-9]+/ );
$hash->{'PAIRING'} = 1;
InternalTimer( Time::HiRes::time() + $t,
\&Schellenberg_ResetPairTimer, $hash );
}
return;
}
sub Schellenberg_ResetPairTimer {
my ($hash) = @_;
delete $hash->{'PAIRING'};
return;
}
sub Schellenberg_Ready {
my ($hash) = @_;
return DevIo_OpenDev( $hash, 1, "Schellenberg_Init" );
}
1;
=pod
=item device
=item summary Schellenberg USB RF-Dongle Receiver
=item summary_DE Schellenberg USB Funk-Stick Empfänger
=begin html
<a name="Schellenberg"></a>
<h3>Schellenberg</h3>
<ul>
Schellenberg USB RF Dongle.
</ul>
<ul>
<a name="Schellenbergdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; Schellenberg &lt;/dev/serial/by-id/usb-schellenberg_ENAS_000000000000-if00&gt;</code>
<br><br>
defines the device and set the port
</ul>
<br>
<a name="Schellenbergset"></a>
<b>Set</b>
<ul>
<li>pair
<ul>
<code>set &lt;name&gt; pair &lt;seconds&gt;</code>
<br><br>
enable pair mode for seconds
</ul>
</li>
</ul>
<br>
</ul>
=end html
=cut
##############################################
# $Id: 00_TCM.pm 19607 2019-06-13 08:06:53Z klaus.schauer $
# $Id: 00_TCM.pm 22616 2020-08-17 16:09:25Z klaus.schauer $
# This modules handles the communication with a TCM 120 or TCM 310 / TCM 400J /
# TCM 515 EnOcean transceiver chip. As the protocols are radically different,
......@@ -11,13 +11,8 @@
package main;
use strict;
use warnings;
use DevIo;
use Time::HiRes qw(gettimeofday usleep);
if ( $^O =~ /Win/ ) {
require Win32::SerialPort;
}
else {
require Device::SerialPort;
}
sub TCM_Read($);
sub TCM_ReadAnswer($$);
sub TCM_Ready($);
......@@ -29,7 +24,6 @@ sub TCM_CSUM($);
sub TCM_Initialize($) {
my ($hash) = @_;
require "$attr{global}{modpath}/FHEM/DevIo.pm";
# Provider
$hash->{ReadFn} = "TCM_Read";
......@@ -80,7 +74,7 @@ sub TCM_Define($$) {
if ( $dev eq "none" ) {
Log3 undef, 1, "TCM $name device is none, commands will be echoed only";
$attr{$name}{dummy} = 1;
return;
return undef;
}
my $ret = DevIo_OpenDev( $hash, 0, undef );
return $ret;
......@@ -93,7 +87,7 @@ sub TCM_InitSerialCom($) {
delete $hash->{helper}{init_done};
if ( $hash->{STATE} eq "disconnected" ) {
Log3 $name, 2, "TCM $name not initialized";
return;
return undef;
}
my $attrVal;
my $comType = AttrVal( $name, "comType", "TCM" );
......@@ -129,7 +123,7 @@ sub TCM_InitSerialCom($) {
else {
%setAttrInit = ( "sendInterval" => { ESP2 => 100, ESP3 => 0 } );
}
for ( keys %setAttrInit ) {
foreach ( keys %setAttrInit ) {
$attrVal = AttrVal( $name, $_, undef );
if ( !defined $attrVal && defined $setAttrInit{$_}{ $hash->{MODEL} } ) {
$attr{$name}{$_} = $setAttrInit{$_}{ $hash->{MODEL} };
......@@ -177,7 +171,7 @@ sub TCM_InitSerialCom($) {
repeater => "RepEnable: 00 RepLevel: 00",
smartAckMailboxMax => 0
);
for ( keys %setCmdRestore ) {
foreach ( keys %setCmdRestore ) {
$setCmdVal = ReadingsVal( $name, $_, AttrVal( $name, $_, undef ) );
if ( defined $setCmdVal ) {
if ( $_ eq "repeater" ) {
......@@ -214,7 +208,7 @@ sub TCM_InitSerialCom($) {
$hash->{helper}{init_done} = 1;
readingsSingleUpdate( $hash, "state", "initialized", 1 );
Log3 $name, 2, "TCM $name initialized";
return;
return undef;
}
sub TCM_Fingerprint($$) {
......@@ -278,8 +272,8 @@ sub TCM_Write($$$$) {
# Input is header and data (HEX), without CRC
my ( $hash, $shash, $header, $msg ) = @_;
return if ( !exists( $hash->{helper}{init_done} ) && $hash != $shash );
#return if (!exists($hash->{helper}{init_done}) && $hash != $shash);
# return if (!defined($header));
my $name = $hash->{NAME};
my $bstring;
......@@ -879,7 +873,7 @@ sub TCM_Parse310($$$) {
}
else {
my @ans;
for my $k ( sort keys %{$ptr} ) {
foreach my $k ( sort keys %{$ptr} ) {
next
if ( $k eq "cmd"
|| $k eq "oCmd"
......@@ -952,7 +946,7 @@ sub TCM_Ready($) {
# This is relevant for windows/USB only
my $po = $hash->{USBDev};
return if ( !$po );
return undef if ( !$po );
my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po->status;
return ( $InBytes > 0 );
}
......@@ -1113,15 +1107,15 @@ my %sets310 = (
"filterDel" => { packetType => 5, cmd => "0C", arg => "0[0-3][0-9A-F]{8}" },
"filterDelAll