remove all prototyps, change code PBP conform

This commit is contained in:
Marko Oldenburg 2020-04-24 15:56:10 +02:00
parent 4789870ad7
commit 765a923f46

View File

@ -197,16 +197,15 @@ my %CallBatteryAge = (
'48h' => 172800 '48h' => 172800
); );
sub Initialize($) { sub Initialize {
my $hash = shift;
my ($hash) = @_; $hash->{SetFn} = \&Set;
$hash->{GetFn} = \&Get;
$hash->{SetFn} = "FHEM::XiaomiBTLESens::Set"; $hash->{DefFn} = \&Define;
$hash->{GetFn} = "FHEM::XiaomiBTLESens::Get"; $hash->{NotifyFn} = \&Notify;
$hash->{DefFn} = "FHEM::XiaomiBTLESens::Define"; $hash->{UndefFn} = \&Undef;
$hash->{NotifyFn} = "FHEM::XiaomiBTLESens::Notify"; $hash->{AttrFn} = \&Attr;
$hash->{UndefFn} = "FHEM::XiaomiBTLESens::Undef";
$hash->{AttrFn} = "FHEM::XiaomiBTLESens::Attr";
$hash->{AttrList} = $hash->{AttrList} =
"interval " "interval "
. "disable:1 " . "disable:1 "
@ -226,29 +225,26 @@ sub Initialize($) {
. "model:flowerSens,thermoHygroSens,clearGrassSens " . "model:flowerSens,thermoHygroSens,clearGrassSens "
. "blockingCallLoglevel:2,3,4,5 " . "blockingCallLoglevel:2,3,4,5 "
. $readingFnAttributes; . $readingFnAttributes;
$hash->{parseParams} = 1;
return FHEM::Meta::InitMod( __FILE__, $hash ); return FHEM::Meta::InitMod( __FILE__, $hash );
} }
# declare prototype sub Define {
sub ExecGatttool_Run($); my $hash = shift;
my $a = shift;
sub Define($$) {
my ( $hash, $def ) = @_;
my @a = split( "[ \t][ \t]*", $def );
return $@ unless ( FHEM::Meta::SetInternals($hash) ); return $@ unless ( FHEM::Meta::SetInternals($hash) );
use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' ); use version 0.60; our $VERSION = FHEM::Meta::Get( $hash, 'version' );
return "too few parameters: define <name> XiaomiBTLESens <BTMAC>" return "too few parameters: define <name> XiaomiBTLESens <BTMAC>"
if ( @a != 3 ); if ( scalar( @{$a} ) != 3 );
return return
"Cannot define XiaomiBTLESens device. Perl modul ${missingModul}is missing." "Cannot define XiaomiBTLESens device. Perl modul ${missingModul}is missing."
if ($missingModul); if ($missingModul);
my $name = $a[0]; my $name = $a->[0];
my $mac = $a[2]; my $mac = $a->[2];
$hash->{BTMAC} = $mac; $hash->{BTMAC} = $mac;
$hash->{VERSION} = version->parse($VERSION)->normal; $hash->{VERSION} = version->parse($VERSION)->normal;
@ -262,15 +258,17 @@ sub Define($$) {
CommandAttr( undef, $name . ' room XiaomiBTLESens' ) CommandAttr( undef, $name . ' room XiaomiBTLESens' )
if ( AttrVal( $name, 'room', 'none' ) eq 'none' ); if ( AttrVal( $name, 'room', 'none' ) eq 'none' );
Log3($name, 3, "XiaomiBTLESens ($name) - defined with BTMAC $hash->{BTMAC}"); Log3( $name, 3,
"XiaomiBTLESens ($name) - defined with BTMAC $hash->{BTMAC}" );
$modules{XiaomiBTLESens}{defptr}{ $hash->{BTMAC} } = $hash; $modules{XiaomiBTLESens}{defptr}{ $hash->{BTMAC} } = $hash;
return undef;
return;
} }
sub Undef($$) { sub Undef {
my $hash = shift;
my ( $hash, $arg ) = @_; my $arg = shift;
my $mac = $hash->{BTMAC}; my $mac = $hash->{BTMAC};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -280,12 +278,12 @@ sub Undef($$) {
if ( defined( $hash->{helper}{RUNNING_PID} ) ); if ( defined( $hash->{helper}{RUNNING_PID} ) );
delete( $modules{XiaomiBTLESens}{defptr}{$mac} ); delete( $modules{XiaomiBTLESens}{defptr}{$mac} );
Log3($name, 3, "Sub XiaomiBTLESens_Undef ($name) - delete device $name"); Log3( $name, 3, "Sub XiaomiBTLESens_Undef ($name) - delete device $name" );
return undef;
return;
} }
sub Attr(@) { sub Attr {
my ( $cmd, $name, $attrName, $attrVal ) = @_; my ( $cmd, $name, $attrName, $attrVal ) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
@ -294,11 +292,11 @@ sub Attr(@) {
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
readingsSingleUpdate( $hash, "state", "disabled", 1 ); readingsSingleUpdate( $hash, "state", "disabled", 1 );
Log3($name, 3, "XiaomiBTLESens ($name) - disabled"); Log3( $name, 3, "XiaomiBTLESens ($name) - disabled" );
} }
elsif ( $cmd eq "del" ) { elsif ( $cmd eq "del" ) {
Log3($name, 3, "XiaomiBTLESens ($name) - enabled"); Log3( $name, 3, "XiaomiBTLESens ($name) - enabled" );
} }
} }
@ -307,12 +305,12 @@ sub Attr(@) {
return return
"check disabledForIntervals Syntax HH:MM-HH:MM or 'HH:MM-HH:MM HH:MM-HH:MM ...'" "check disabledForIntervals Syntax HH:MM-HH:MM or 'HH:MM-HH:MM HH:MM-HH:MM ...'"
unless ( $attrVal =~ /^((\d{2}:\d{2})-(\d{2}:\d{2})\s?)+$/ ); unless ( $attrVal =~ /^((\d{2}:\d{2})-(\d{2}:\d{2})\s?)+$/ );
Log3($name, 3, "XiaomiBTLESens ($name) - disabledForIntervals"); Log3( $name, 3, "XiaomiBTLESens ($name) - disabledForIntervals" );
stateRequest($hash); stateRequest($hash);
} }
elsif ( $cmd eq "del" ) { elsif ( $cmd eq "del" ) {
Log3($name, 3, "XiaomiBTLESens ($name) - enabled"); Log3( $name, 3, "XiaomiBTLESens ($name) - enabled" );
readingsSingleUpdate( $hash, "state", "active", 1 ); readingsSingleUpdate( $hash, "state", "active", 1 );
} }
} }
@ -322,44 +320,49 @@ sub Attr(@) {
if ( $cmd eq "set" ) { if ( $cmd eq "set" ) {
if ( $attrVal < 120 ) { if ( $attrVal < 120 ) {
Log3($name, 3, Log3( $name, 3,
"XiaomiBTLESens ($name) - interval too small, please use something >= 120 (sec), default is 300 (sec)"); "XiaomiBTLESens ($name) - interval too small, please use something >= 120 (sec), default is 300 (sec)"
);
return return
"interval too small, please use something >= 120 (sec), default is 300 (sec)"; "interval too small, please use something >= 120 (sec), default is 300 (sec)";
} }
else { else {
$hash->{INTERVAL} = $attrVal; $hash->{INTERVAL} = $attrVal;
Log3($name, 3, Log3( $name, 3,
"XiaomiBTLESens ($name) - set interval to $attrVal"); "XiaomiBTLESens ($name) - set interval to $attrVal" );
} }
} }
elsif ( $cmd eq "del" ) { elsif ( $cmd eq "del" ) {
$hash->{INTERVAL} = 300; $hash->{INTERVAL} = 300;
Log3($name, 3, "XiaomiBTLESens ($name) - set interval to default"); Log3( $name, 3,
"XiaomiBTLESens ($name) - set interval to default" );
} }
} }
elsif ( $attrName eq "blockingCallLoglevel" ) { elsif ( $attrName eq "blockingCallLoglevel" ) {
if ( $cmd eq "set" ) { if ( $cmd eq "set" ) {
$hash->{loglevel} = $attrVal; $hash->{loglevel} = $attrVal;
Log3($name, 3, Log3( $name, 3,
"XiaomiBTLESens ($name) - set blockingCallLoglevel to $attrVal"); "XiaomiBTLESens ($name) - set blockingCallLoglevel to $attrVal"
);
} }
elsif ( $cmd eq "del" ) { elsif ( $cmd eq "del" ) {
$hash->{loglevel} = 4; $hash->{loglevel} = 4;
Log3($name, 3, Log3( $name, 3,
"XiaomiBTLESens ($name) - set blockingCallLoglevel to default"); "XiaomiBTLESens ($name) - set blockingCallLoglevel to default"
);
} }
} }
return undef; return;
} }
sub Notify($$) { sub Notify {
my $hash = shift;
my $dev = shift;
my ( $hash, $dev ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
return stateRequestTimer($hash) if ( IsDisabled($name) ); return stateRequestTimer($hash) if ( IsDisabled($name) );
@ -419,9 +422,9 @@ sub Notify($$) {
return; return;
} }
sub stateRequest($) { sub stateRequest {
my $hash = shift;
my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
@ -481,11 +484,12 @@ sub stateRequest($) {
else { else {
readingsSingleUpdate( $hash, "state", "disabled", 1 ); readingsSingleUpdate( $hash, "state", "disabled", 1 );
} }
return;
} }
sub stateRequestTimer($) { sub stateRequestTimer {
my $hash = shift;
my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -495,30 +499,32 @@ sub stateRequestTimer($) {
InternalTimer( gettimeofday() + $hash->{INTERVAL} + int( rand(300) ), InternalTimer( gettimeofday() + $hash->{INTERVAL} + int( rand(300) ),
"XiaomiBTLESens_stateRequestTimer", $hash ); "XiaomiBTLESens_stateRequestTimer", $hash );
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - stateRequestTimer: Call Request Timer"); "XiaomiBTLESens ($name) - stateRequestTimer: Call Request Timer" );
return;
} }
sub Set($$@) { sub Set($$@) {
my $hash = shift;
my ( $hash, $name, @aa ) = @_; my $a = shift;
my ( $cmd, @args ) = @aa; my $name = shift @$a;
my $cmd = shift @$a // return qq{"set $name" needs at least one argument};
my $mod; my $mod;
my $handle; my $handle;
my $value = 'write'; my $value = 'write';
if ( $cmd eq 'devicename' ) { if ( $cmd eq 'devicename' ) {
return "usage: devicename <name>" if ( @args < 1 ); return "usage: devicename <name>" if ( scalar( @{$a} ) < 1 );
my $devicename = join( " ", @args );
$mod = 'write'; $mod = 'write';
$handle = $XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename}; $handle = $XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename};
$value = CreateDevicenameHEX( makeDeviceName($devicename) ); $value = CreateDevicenameHEX( makeDeviceName( $a->[0] ) );
} }
elsif ( $cmd eq 'resetBatteryTimestamp' ) { elsif ( $cmd eq 'resetBatteryTimestamp' ) {
return "usage: resetBatteryTimestamp" if ( @args != 0 ); return "usage: resetBatteryTimestamp" if ( scalar( @{$a} ) != 0 );
$hash->{helper}{updateTimeCallBattery} = 0; $hash->{helper}{updateTimeCallBattery} = 0;
return; return;
@ -538,32 +544,33 @@ sub Set($$@) {
CreateParamGatttool( $hash, $mod, $handle, $value ); CreateParamGatttool( $hash, $mod, $handle, $value );
return undef; return;
} }
sub Get($$@) { sub Get {
my $hash = shift;
my ( $hash, $name, @aa ) = @_; my $a = shift;
my ( $cmd, @args ) = @aa; my $name = shift @$a;
my $cmd = shift @$a // return qq{"set $name" needs at least one argument};
my $mod = 'read'; my $mod = 'read';
my $handle; my $handle;
if ( $cmd eq 'sensorData' ) { if ( $cmd eq 'sensorData' ) {
return "usage: sensorData" if ( @args != 0 ); return "usage: sensorData" if ( scalar( @{$a} ) != 0 );
stateRequest($hash); stateRequest($hash);
} }
elsif ( $cmd eq 'firmware' ) { elsif ( $cmd eq 'firmware' ) {
return "usage: firmware" if ( @args != 0 ); return "usage: firmware" if ( scalar( @{$a} ) != 0 );
$mod = 'read'; $mod = 'read';
$handle = $XiaomiModels{ AttrVal( $name, 'model', '' ) }{firmware}; $handle = $XiaomiModels{ AttrVal( $name, 'model', '' ) }{firmware};
} }
elsif ( $cmd eq 'devicename' ) { elsif ( $cmd eq 'devicename' ) {
return "usage: devicename" if ( @args != 0 ); return "usage: devicename" if ( scalar( @{$a} ) != 0 );
$mod = 'read'; $mod = 'read';
$handle = $XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename}; $handle = $XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename};
@ -582,17 +589,17 @@ sub Get($$@) {
CreateParamGatttool( $hash, $mod, $handle ) if ( $cmd ne 'sensorData' ); CreateParamGatttool( $hash, $mod, $handle ) if ( $cmd ne 'sensorData' );
return undef; return;
} }
sub CreateParamGatttool($@) { sub CreateParamGatttool {
my ( $hash, $mod, $handle, $value ) = @_; my ( $hash, $mod, $handle, $value ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $mac = $hash->{BTMAC}; my $mac = $hash->{BTMAC};
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - Run CreateParamGatttool with mod: $mod"); "XiaomiBTLESens ($name) - Run CreateParamGatttool with mod: $mod" );
if ( $mod eq 'read' ) { if ( $mod eq 'read' ) {
$hash->{helper}{RUNNING_PID} = BlockingCall( $hash->{helper}{RUNNING_PID} = BlockingCall(
@ -606,8 +613,9 @@ sub CreateParamGatttool($@) {
readingsSingleUpdate( $hash, "state", "read sensor data", 1 ); readingsSingleUpdate( $hash, "state", "read sensor data", 1 );
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - Read XiaomiBTLESens_ExecGatttool_Run $name|$mac|$mod|$handle"); "XiaomiBTLESens ($name) - Read XiaomiBTLESens_ExecGatttool_Run $name|$mac|$mod|$handle"
);
} }
elsif ( $mod eq 'write' ) { elsif ( $mod eq 'write' ) {
@ -627,18 +635,20 @@ sub CreateParamGatttool($@) {
readingsSingleUpdate( $hash, "state", "write sensor data", 1 ); readingsSingleUpdate( $hash, "state", "write sensor data", 1 );
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - Write XiaomiBTLESens_ExecGatttool_Run $name|$mac|$mod|$handle|$value"); "XiaomiBTLESens ($name) - Write XiaomiBTLESens_ExecGatttool_Run $name|$mac|$mod|$handle|$value"
);
} }
return;
} }
sub Gatttool_executeCommand($) { sub Gatttool_executeCommand {
my $command = join( ' ', @_ ); my $command = join( ' ', @_ );
return ( $_ = qx{$command 2>&1}, $? >> 8 ); return ( $_ = qx{$command 2>&1}, $? >> 8 );
} }
sub ExecGatttool_Run($) { sub ExecGatttool_Run {
my $string = shift; my $string = shift;
my ( $name, $mac, $gattCmd, $handle, $value, $listen ) = my ( $name, $mac, $gattCmd, $handle, $value, $listen ) =
@ -685,8 +695,9 @@ sub ExecGatttool_Run($) {
my $gatttoolCmdlineStaticEscaped = my $gatttoolCmdlineStaticEscaped =
BTLE_CmdlinePreventGrepFalsePositive("gatttool -i $hci -b $mac"); BTLE_CmdlinePreventGrepFalsePositive("gatttool -i $hci -b $mac");
my $psCommand = AttrVal( $name, 'psCommand', 'ps ax' ); my $psCommand = AttrVal( $name, 'psCommand', 'ps ax' );
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - ExecGatttool_Run: Execute Command $psCommand | grep -E $gatttoolCmdlineStaticEscaped"); "XiaomiBTLESens ($name) - ExecGatttool_Run: Execute Command $psCommand | grep -E $gatttoolCmdlineStaticEscaped"
);
# $grepGatttool = qx(ps ax| grep -E \'$gatttoolCmdlineStaticEscaped\') # $grepGatttool = qx(ps ax| grep -E \'$gatttoolCmdlineStaticEscaped\')
$grepGatttool = $grepGatttool =
@ -699,8 +710,9 @@ qx(ssh $sshHost '$psCommand | grep -E "$gatttoolCmdlineStaticEscaped"')
if ( $sshHost ne 'none' ); if ( $sshHost ne 'none' );
if ( not $grepGatttool =~ /^\s*$/ ) { if ( not $grepGatttool =~ /^\s*$/ ) {
Log3($name, 3, Log3( $name, 3,
"XiaomiBTLESens ($name) - ExecGatttool_Run: another gatttool process is running. waiting..."); "XiaomiBTLESens ($name) - ExecGatttool_Run: another gatttool process is running. waiting..."
);
sleep(1); sleep(1);
} }
else { else {
@ -713,30 +725,31 @@ qx(ssh $sshHost '$psCommand | grep -E "$gatttoolCmdlineStaticEscaped"')
my $returnCode = 1; my $returnCode = 1;
do { do {
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - ExecGatttool_Run: call gatttool with command: $cmd and loop $loop"); "XiaomiBTLESens ($name) - ExecGatttool_Run: call gatttool with command: $cmd and loop $loop"
);
($returnString, $returnCode) = Gatttool_executeCommand($cmd); ( $returnString, $returnCode ) = Gatttool_executeCommand($cmd);
@gtResult = split( ": ", $returnString ); @gtResult = split( ": ", $returnString );
# @gtResult = split( ": ", qx($cmd) ); # @gtResult = split( ": ", qx($cmd) );
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - ExecGatttool_Run: gatttool loop result " "XiaomiBTLESens ($name) - ExecGatttool_Run: gatttool loop result "
. join( ",", @gtResult )); . join( ",", @gtResult ) );
$returnCode = 2 $returnCode = 2
unless ( defined( $gtResult[0] ) ); unless ( defined( $gtResult[0] ) );
$loop++; $loop++;
} while ( $loop < 5 and ($returnCode != 0 and $returnCode != 124) ); } while ( $loop < 5 and ( $returnCode != 0 and $returnCode != 124 ) );
Log3($name, 3, Log3( $name, 3,
"XiaomiBTLESens ($name) - ExecGatttool_Run: errorcode: \"$returnCode\", ErrorString: \"$returnString\"") "XiaomiBTLESens ($name) - ExecGatttool_Run: errorcode: \"$returnCode\", ErrorString: \"$returnString\""
if ( $returnCode != 0 and $returnCode != 124 ); ) if ( $returnCode != 0 and $returnCode != 124 );
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ExecGatttool_Run: gatttool result " "XiaomiBTLESens ($name) - ExecGatttool_Run: gatttool result "
. join( ",", @gtResult )); . join( ",", @gtResult ) );
$handle = '0x35' $handle = '0x35'
if ( $sshHost ne 'none' if ( $sshHost ne 'none'
@ -778,11 +791,13 @@ qx(ssh $sshHost '$psCommand | grep -E "$gatttoolCmdlineStaticEscaped"')
); );
return "$name|$mac|error|$gattCmd|$handle|$json_notification"; return "$name|$mac|error|$gattCmd|$handle|$json_notification";
} }
return;
} }
sub ExecGatttool_Done($) { sub ExecGatttool_Done {
my $string = shift; my $string = shift;
my ( $name, $mac, $respstate, $gattCmd, $handle, $json_notification ) = my ( $name, $mac, $respstate, $gattCmd, $handle, $json_notification ) =
split( "\\|", $string ); split( "\\|", $string );
@ -790,18 +805,20 @@ sub ExecGatttool_Done($) {
delete( $hash->{helper}{RUNNING_PID} ); delete( $hash->{helper}{RUNNING_PID} );
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - ExecGatttool_Done: Helper is disabled. Stop processing") "XiaomiBTLESens ($name) - ExecGatttool_Done: Helper is disabled. Stop processing"
if ( $hash->{helper}{DISABLED} ); ) if ( $hash->{helper}{DISABLED} );
return if ( $hash->{helper}{DISABLED} ); return if ( $hash->{helper}{DISABLED} );
Log3($name, 5, Log3( $name, 5,
"XiaomiBTLESens ($name) - ExecGatttool_Done: gatttool return string: $string"); "XiaomiBTLESens ($name) - ExecGatttool_Done: gatttool return string: $string"
);
my $decode_json = eval { decode_json($json_notification) }; my $decode_json = eval { decode_json($json_notification) };
if ($@) { if ($@) {
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ExecGatttool_Done: JSON error while request: $@"); "XiaomiBTLESens ($name) - ExecGatttool_Done: JSON error while request: $@"
);
} }
if ( $respstate eq 'ok' if ( $respstate eq 'ok'
@ -820,11 +837,13 @@ sub ExecGatttool_Done($) {
else { else {
ProcessingErrors( $hash, $decode_json->{gtResult} ); ProcessingErrors( $hash, $decode_json->{gtResult} );
} }
return;
} }
sub ExecGatttool_Aborted($) { sub ExecGatttool_Aborted {
my $hash = shift;
my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
@ -835,32 +854,36 @@ sub ExecGatttool_Aborted($) {
'The BlockingCall Process terminated unexpectedly. Timedout'; 'The BlockingCall Process terminated unexpectedly. Timedout';
WriteReadings( $hash, \%readings ); WriteReadings( $hash, \%readings );
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ExecGatttool_Aborted: The BlockingCall Process terminated unexpectedly. Timedout"); "XiaomiBTLESens ($name) - ExecGatttool_Aborted: The BlockingCall Process terminated unexpectedly. Timedout"
);
return;
} }
sub ProcessingNotification($@) { sub ProcessingNotification {
my ( $hash, $gattCmd, $handle, $notification ) = @_; my ( $hash, $gattCmd, $handle, $notification ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $readings; my $readings;
Log3($name, 4, "XiaomiBTLESens ($name) - ProcessingNotification"); Log3( $name, 4, "XiaomiBTLESens ($name) - ProcessingNotification" );
if ( AttrVal( $name, 'model', 'none' ) eq 'flowerSens' ) { if ( AttrVal( $name, 'model', 'none' ) eq 'flowerSens' ) {
if ( $handle eq '0x38' ) { if ( $handle eq '0x38' ) {
### Flower Sens - Read Firmware and Battery Data ### Flower Sens - Read Firmware and Battery Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x38"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x38"
);
$readings = FlowerSensHandle0x38( $hash, $notification ); $readings = FlowerSensHandle0x38( $hash, $notification );
} }
elsif ( $handle eq '0x35' ) { elsif ( $handle eq '0x35' ) {
### Flower Sens - Read Sensor Data ### Flower Sens - Read Sensor Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x35"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x35"
);
$readings = FlowerSensHandle0x35( $hash, $notification ); $readings = FlowerSensHandle0x35( $hash, $notification );
} }
@ -869,29 +892,32 @@ sub ProcessingNotification($@) {
elsif ( AttrVal( $name, 'model', 'none' ) eq 'thermoHygroSens' ) { elsif ( AttrVal( $name, 'model', 'none' ) eq 'thermoHygroSens' ) {
if ( $handle eq '0x18' ) { if ( $handle eq '0x18' ) {
### Thermo/Hygro Sens - Read Battery Data ### Thermo/Hygro Sens - Read Battery Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x18"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x18"
);
$readings = ThermoHygroSensHandle0x18( $hash, $notification ); $readings = ThermoHygroSensHandle0x18( $hash, $notification );
} }
elsif ( $handle eq '0x10' ) { elsif ( $handle eq '0x10' ) {
### Thermo/Hygro Sens - Read Sensor Data ### Thermo/Hygro Sens - Read Sensor Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x10"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x10"
);
$readings = ThermoHygroSensHandle0x10( $hash, $notification ); $readings = ThermoHygroSensHandle0x10( $hash, $notification );
} }
elsif ( $handle eq '0x24' ) { elsif ( $handle eq '0x24' ) {
### Thermo/Hygro Sens - Read Firmware Data ### Thermo/Hygro Sens - Read Firmware Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x24"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x24"
);
$readings = ThermoHygroSensHandle0x24( $hash, $notification ); $readings = ThermoHygroSensHandle0x24( $hash, $notification );
} }
elsif ( $handle eq '0x3' ) { elsif ( $handle eq '0x3' ) {
### Thermo/Hygro Sens - Read and Write Devicename ### Thermo/Hygro Sens - Read and Write Devicename
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x3"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x3" );
return CreateParamGatttool( $hash, 'read', return CreateParamGatttool( $hash, 'read',
$XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename} ) $XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename} )
@ -902,29 +928,32 @@ sub ProcessingNotification($@) {
elsif ( AttrVal( $name, 'model', 'none' ) eq 'clearGrassSens' ) { elsif ( AttrVal( $name, 'model', 'none' ) eq 'clearGrassSens' ) {
if ( $handle eq '0x3b' ) { if ( $handle eq '0x3b' ) {
### Clear Grass Sens - Read Battery Data ### Clear Grass Sens - Read Battery Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x3b"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x3b"
);
$readings = ClearGrassSensHandle0x3b( $hash, $notification ); $readings = ClearGrassSensHandle0x3b( $hash, $notification );
} }
elsif ( $handle eq '0x1e' ) { elsif ( $handle eq '0x1e' ) {
### Clear Grass Sens - Read Sensor Data ### Clear Grass Sens - Read Sensor Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x1e"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x1e"
);
$readings = ClearGrassSensHandle0x1e( $hash, $notification ); $readings = ClearGrassSensHandle0x1e( $hash, $notification );
} }
elsif ( $handle eq '0x2a' ) { elsif ( $handle eq '0x2a' ) {
### Clear Grass Sens - Read Firmware Data ### Clear Grass Sens - Read Firmware Data
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x2a"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x2a"
);
$readings = ClearGrassSensHandle0x2a( $hash, $notification ); $readings = ClearGrassSensHandle0x2a( $hash, $notification );
} }
elsif ( $handle eq '0x3' ) { elsif ( $handle eq '0x3' ) {
### Clear Grass Sens - Read and Write Devicename ### Clear Grass Sens - Read and Write Devicename
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - ProcessingNotification: handle 0x3"); "XiaomiBTLESens ($name) - ProcessingNotification: handle 0x3" );
return CreateParamGatttool( $hash, 'read', return CreateParamGatttool( $hash, 'read',
$XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename} ) $XiaomiModels{ AttrVal( $name, 'model', '' ) }{devicename} )
@ -933,17 +962,18 @@ sub ProcessingNotification($@) {
} }
} }
WriteReadings( $hash, $readings ); return WriteReadings( $hash, $readings );
} }
sub FlowerSensHandle0x38($$) { sub FlowerSensHandle0x38 {
### FlowerSens - Read Firmware and Battery Data ### FlowerSens - Read Firmware and Battery Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - FlowerSens Handle0x38"); Log3( $name, 4, "XiaomiBTLESens ($name) - FlowerSens Handle0x38" );
my @dataBatFw = split( " ", $notification ); my @dataBatFw = split( " ", $notification );
@ -959,17 +989,19 @@ sub FlowerSensHandle0x38($$) {
$hash->{helper}{CallBattery} = 1; $hash->{helper}{CallBattery} = 1;
CallBattery_Timestamp($hash); CallBattery_Timestamp($hash);
return \%readings; return \%readings;
} }
sub FlowerSensHandle0x35($$) { sub FlowerSensHandle0x35 {
### Flower Sens - Read Sensor Data ### Flower Sens - Read Sensor Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - FlowerSens Handle0x35"); Log3( $name, 4, "XiaomiBTLESens ($name) - FlowerSens Handle0x35" );
my @dataSensor = split( " ", $notification ); my @dataSensor = split( " ", $notification );
@ -995,26 +1027,28 @@ sub FlowerSensHandle0x35($$) {
$readings{'moisture'} = hex( "0x" . $dataSensor[7] ); $readings{'moisture'} = hex( "0x" . $dataSensor[7] );
$readings{'fertility'} = hex( "0x" . $dataSensor[9] . $dataSensor[8] ); $readings{'fertility'} = hex( "0x" . $dataSensor[9] . $dataSensor[8] );
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - FlowerSens Handle0x35 - lux: " "XiaomiBTLESens ($name) - FlowerSens Handle0x35 - lux: "
. $readings{lux} . $readings{lux}
. ", moisture: " . ", moisture: "
. $readings{moisture} . $readings{moisture}
. ", fertility: " . ", fertility: "
. $readings{fertility}); . $readings{fertility} );
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub ThermoHygroSensHandle0x18($$) { sub ThermoHygroSensHandle0x18 {
### Thermo/Hygro Sens - Battery Data ### Thermo/Hygro Sens - Battery Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x18"); Log3( $name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x18" );
chomp($notification); chomp($notification);
$notification =~ s/\s+//g; $notification =~ s/\s+//g;
@ -1026,17 +1060,19 @@ sub ThermoHygroSensHandle0x18($$) {
$hash->{helper}{CallBattery} = 1; $hash->{helper}{CallBattery} = 1;
CallBattery_Timestamp($hash); CallBattery_Timestamp($hash);
return \%readings; return \%readings;
} }
sub ThermoHygroSensHandle0x10($$) { sub ThermoHygroSensHandle0x10 {
### Thermo/Hygro Sens - Read Sensor Data ### Thermo/Hygro Sens - Read Sensor Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x10"); Log3( $name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x10" );
return stateRequest($hash) return stateRequest($hash)
unless ( $notification =~ /^([0-9a-f]{2}(\s?))*$/ ); unless ( $notification =~ /^([0-9a-f]{2}(\s?))*$/ );
@ -1062,51 +1098,57 @@ sub ThermoHygroSensHandle0x10($$) {
); );
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub ThermoHygroSensHandle0x24($$) { sub ThermoHygroSensHandle0x24 {
### Thermo/Hygro Sens - Read Firmware Data ### Thermo/Hygro Sens - Read Firmware Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x24"); Log3( $name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x24" );
$notification =~ s/\s+//g; $notification =~ s/\s+//g;
$readings{'firmware'} = pack( 'H*', $notification ); $readings{'firmware'} = pack( 'H*', $notification );
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub ThermoHygroSensHandle0x3($$) { sub ThermoHygroSensHandle0x3 {
### Thermo/Hygro Sens - Read and Write Devicename ### Thermo/Hygro Sens - Read and Write Devicename
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x3"); Log3( $name, 4, "XiaomiBTLESens ($name) - Thermo/Hygro Sens Handle0x3" );
$notification =~ s/\s+//g; $notification =~ s/\s+//g;
$readings{'devicename'} = pack( 'H*', $notification ); $readings{'devicename'} = pack( 'H*', $notification );
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub ClearGrassSensHandle0x3b($$) { sub ClearGrassSensHandle0x3b {
### Clear Grass Sens - Battery Data ### Clear Grass Sens - Battery Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x3b"); Log3( $name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x3b" );
chomp($notification); chomp($notification);
$notification =~ s/\s+//g; $notification =~ s/\s+//g;
@ -1118,17 +1160,19 @@ sub ClearGrassSensHandle0x3b($$) {
$hash->{helper}{CallBattery} = 1; $hash->{helper}{CallBattery} = 1;
CallBattery_Timestamp($hash); CallBattery_Timestamp($hash);
return \%readings; return \%readings;
} }
sub ClearGrassSensHandle0x1e($$) { sub ClearGrassSensHandle0x1e {
### Clear Grass Sens - Read Sensor Data ### Clear Grass Sens - Read Sensor Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x1e"); Log3( $name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x1e" );
return stateRequest($hash) return stateRequest($hash)
unless ( $notification =~ /^([0-9a-f]{2}(\s?))*$/ ); unless ( $notification =~ /^([0-9a-f]{2}(\s?))*$/ );
@ -1143,46 +1187,51 @@ sub ClearGrassSensHandle0x1e($$) {
10; 10;
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub ClearGrassSensHandle0x2a($$) { sub ClearGrassSensHandle0x2a {
### Clear Grass Sens - Read Firmware Data ### Clear Grass Sens - Read Firmware Data
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x2a"); Log3( $name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x2a" );
$notification =~ s/\s+//g; $notification =~ s/\s+//g;
$readings{'firmware'} = pack( 'H*', $notification ); $readings{'firmware'} = pack( 'H*', $notification );
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub ClearGrassSensHandle0x3($$) { sub ClearGrassSensHandle0x3 {
### Clear Grass Sens - Read and Write Devicename ### Clear Grass Sens - Read and Write Devicename
my ( $hash, $notification ) = @_; my $hash = shift;
my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x3"); Log3( $name, 4, "XiaomiBTLESens ($name) - Clear Grass Sens Handle0x3" );
$notification =~ s/\s+//g; $notification =~ s/\s+//g;
$readings{'devicename'} = pack( 'H*', $notification ); $readings{'devicename'} = pack( 'H*', $notification );
$hash->{helper}{CallBattery} = 0; $hash->{helper}{CallBattery} = 0;
return \%readings; return \%readings;
} }
sub WriteReadings($$) { sub WriteReadings {
my $hash = shift;
my ( $hash, $readings ) = @_; my $readings = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -1291,29 +1340,30 @@ sub WriteReadings($$) {
) if ( AttrVal( $name, 'maxTemp', 'none' ) ne 'none' ); ) if ( AttrVal( $name, 'maxTemp', 'none' ) ne 'none' );
} }
Log3($name, 4, Log3( $name, 4,
"XiaomiBTLESens ($name) - WriteReadings: Readings were written"); "XiaomiBTLESens ($name) - WriteReadings: Readings were written" );
$hash->{helper}{CallSensDataCounter} = 0; $hash->{helper}{CallSensDataCounter} = 0;
stateRequest($hash) if ( $hash->{helper}{CallBattery} == 1 ); stateRequest($hash) if ( $hash->{helper}{CallBattery} == 1 );
return;
} }
sub ProcessingErrors($$) { sub ProcessingErrors {
my $hash = shift;
my ( $hash, $notification ) = @_; my $notification = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my %readings; my %readings;
Log3($name, 4, "XiaomiBTLESens ($name) - ProcessingErrors"); Log3( $name, 4, "XiaomiBTLESens ($name) - ProcessingErrors" );
$readings{'lastGattError'} = $notification; $readings{'lastGattError'} = $notification;
WriteReadings( $hash, \%readings ); return WriteReadings( $hash, \%readings );
} }
#### my little Helper #### my little Helper
sub encodeJSON($) { sub encodeJSON {
my $gtResult = shift; my $gtResult = shift;
chomp($gtResult); chomp($gtResult);
@ -1324,8 +1374,7 @@ sub encodeJSON($) {
} }
## Routinen damit Firmware und Batterie nur alle X male statt immer aufgerufen wird ## Routinen damit Firmware und Batterie nur alle X male statt immer aufgerufen wird
sub CallBattery_Timestamp($) { sub CallBattery_Timestamp {
my $hash = shift; my $hash = shift;
# get timestamp # get timestamp
@ -1334,8 +1383,7 @@ sub CallBattery_Timestamp($) {
$hash->{helper}{updateTimestampCallBattery} = FmtDateTime( gettimeofday() ); $hash->{helper}{updateTimestampCallBattery} = FmtDateTime( gettimeofday() );
} }
sub CallBattery_UpdateTimeAge($) { sub CallBattery_UpdateTimeAge {
my $hash = shift; my $hash = shift;
$hash->{helper}{updateTimeCallBattery} = 0 $hash->{helper}{updateTimeCallBattery} = 0
@ -1345,15 +1393,14 @@ sub CallBattery_UpdateTimeAge($) {
return $UpdateTimeAge; return $UpdateTimeAge;
} }
sub CallBattery_IsUpdateTimeAgeToOld($$) { sub CallBattery_IsUpdateTimeAgeToOld {
my $hash = shift;
my ( $hash, $maxAge ) = @_; my $maxAge = shift;
return ( CallBattery_UpdateTimeAge($hash) > $maxAge ? 1 : 0 ); return ( CallBattery_UpdateTimeAge($hash) > $maxAge ? 1 : 0 );
} }
sub CreateDevicenameHEX($) { sub CreateDevicenameHEX {
my $devicename = shift; my $devicename = shift;
my $devicenameHex = unpack( "H*", $devicename ); my $devicenameHex = unpack( "H*", $devicename );
@ -1361,15 +1408,15 @@ sub CreateDevicenameHEX($) {
return $devicenameHex; return $devicenameHex;
} }
sub BTLE_CmdlinePreventGrepFalsePositive($) { sub BTLE_CmdlinePreventGrepFalsePositive {
# https://stackoverflow.com/questions/9375711/more-elegant-ps-aux-grep-v-grep # https://stackoverflow.com/questions/9375711/more-elegant-ps-aux-grep-v-grep
# Given abysmal (since external-command-based) performance in the first place, we'd better # Given abysmal (since external-command-based) performance in the first place, we'd better
# avoid an *additional* grep process plus pipe... # avoid an *additional* grep process plus pipe...
my $cmdline = shift; my $cmdline = shift;
$cmdline =~ s/(.)(.*)/[$1]$2/; $cmdline =~ s/(.)(.*)/[$1]$2/;
return $cmdline; return $cmdline;
} }
@ -1562,7 +1609,7 @@ sub BTLE_CmdlinePreventGrepFalsePositive($) {
], ],
"release_status": "stable", "release_status": "stable",
"license": "GPL_2", "license": "GPL_2",
"version": "v2.8.2", "version": "v2.9.1",
"author": [ "author": [
"Marko Oldenburg <leongaultier@gmail.com>" "Marko Oldenburg <leongaultier@gmail.com>"
], ],