diff --git a/fhem/CHANGED b/fhem/CHANGED index 4afa148a0..f799ef809 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 74_XiaomiBTLESens: add new set command resetBatteryTimestamp - bugfix: 93_DbRep: some perl warnings fixed - fhem.pl: restoreDir restructured (Forum #85801) - added: 88_xs1Bridge: added blacklist function diff --git a/fhem/FHEM/74_XiaomiBTLESens.pm b/fhem/FHEM/74_XiaomiBTLESens.pm index c4a34afd1..6d5e37839 100644 --- a/fhem/FHEM/74_XiaomiBTLESens.pm +++ b/fhem/FHEM/74_XiaomiBTLESens.pm @@ -39,15 +39,18 @@ package main; +my $missingModul = ""; + use strict; use warnings; use POSIX; -use JSON; -use Blocking; +eval "use JSON;1" or $missingModul .= "JSON "; +eval "use Blocking;1" or $missingModul .= "Blocking "; +#use Data::Dumper; only for Debugging -my $version = "2.0.9"; +my $version = "2.0.10"; @@ -86,6 +89,7 @@ sub XiaomiBTLESens_ProcessingNotification($@); sub XiaomiBTLESens_WriteReadings($$); sub XiaomiBTLESens_ProcessingErrors($$); sub XiaomiBTLESens_encodeJSON($); +sub CometBlueBTLE_CmdlinePreventGrepFalsePositive($); sub XiaomiBTLESens_CallBattery_IsUpdateTimeAgeToOld($$); sub XiaomiBTLESens_CallBattery_Timestamp($); @@ -147,6 +151,7 @@ sub XiaomiBTLESens_Define($$) { my @a = split( "[ \t][ \t]*", $def ); return "too few parameters: define XiaomiBTLESens " if( @a != 3 ); + return "Cannot define XiaomiBTLESens device. Perl modul ${missingModul}is missing." if ( $missingModul ); my $name = $a[0]; @@ -162,7 +167,8 @@ sub XiaomiBTLESens_Define($$) { readingsSingleUpdate($hash,"state","initialized", 0); - $attr{$name}{room} = "XiaomiBTLESens" if( AttrVal($name,'room','none') eq 'none' ); + #$attr{$name}{room} = "XiaomiBTLESens" if( AttrVal($name,'room','none') eq 'none' ); + CommandAttr(undef,$name . ' room XiaomiBTLESens') if( AttrVal($name,'room','none') eq 'none' ); Log3 $name, 3, "XiaomiBTLESens ($name) - defined with BTMAC $hash->{BTMAC}"; @@ -265,7 +271,7 @@ sub XiaomiBTLESens_Notify($$) { return if (!$events); - XiaomiBTLESens_stateRequestTimer($hash) if( (grep /^DEFINED.$name$/,@{$events} + XiaomiBTLESens_stateRequestTimer($hash) if( (((grep /^DEFINED.$name$/,@{$events} or grep /^INITIALIZED$/,@{$events} or grep /^MODIFIED.$name$/,@{$events} or grep /^DELETEATTR.$name.disable$/,@{$events} @@ -273,8 +279,9 @@ sub XiaomiBTLESens_Notify($$) { or grep /^DELETEATTR.$name.interval$/,@{$events} or grep /^DELETEATTR.$name.model$/,@{$events} or grep /^ATTR.$name.model.+/,@{$events} - or grep /^ATTR.$name.interval.[0-9]+/,@{$events} ) and $init_done and $devname eq 'global' ); - + or grep /resetBatteryTimestamp$/,@{$events} + or grep /^ATTR.$name.interval.[0-9]+/,@{$events}) and $devname eq 'global') + or grep /^resetBatteryTimestamp$/,@{$events}) and $init_done ); XiaomiBTLESens_CreateParamGatttool($hash,'read',$XiaomiModels{AttrVal($name,'model','')}{devicename}) if( AttrVal($name,'model','thermoHygroSens') eq 'thermoHygroSens' and $devname eq $name @@ -349,10 +356,16 @@ sub XiaomiBTLESens_Set($$@) { my $devicename = join( " ", @args ); $mod = 'write'; $handle = $XiaomiModels{AttrVal($name,'model','')}{devicename}; $value = XiaomiBTLESens_CreateDevicenameHEX(makeDeviceName($devicename)); + + } elsif( $cmd eq 'resetBatteryTimestamp' ) { + return "usage: resetBatteryTimestamp" if( @args != 0 ); + + $hash->{helper}{updateTimeCallBattery} = 0; + return; } else { - my $list = ""; - $list .= "devicename" if( AttrVal($name,'model','thermoHygroSens') eq 'thermoHygroSens' ); + my $list = "resetBatteryTimestamp:noArg"; + $list .= " devicename" if( AttrVal($name,'model','thermoHygroSens') eq 'thermoHygroSens' ); return "Unknown argument $cmd, choose one of $list"; } @@ -462,8 +475,11 @@ sub XiaomiBTLESens_ExecGatttool_Run($) { while($wait) { my $grepGatttool; - $grepGatttool = qx(ps ax| grep -E \'gatttool -i $hci -b $mac\' | grep -v grep) if($sshHost eq 'none'); - $grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "gatttool -i $hci -b $mac" | grep -v grep') if($sshHost ne 'none'); + my $gatttoolCmdlineStaticEscaped = CometBlueBTLE_CmdlinePreventGrepFalsePositive("gatttool -i $hci -b $mac"); + #$grepGatttool = qx(ps ax| grep -E \'gatttool -i $hci -b $mac\' | grep -v grep) if($sshHost eq 'none'); + #$grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "gatttool -i $hci -b $mac" | grep -v grep') if($sshHost ne 'none'); + $grepGatttool = qx(ps ax| grep -E \'$gatttoolCmdlineStaticEscaped\') if($sshHost eq 'none'); + $grepGatttool = qx(ssh $sshHost 'ps ax| grep -E "$gatttoolCmdlineStaticEscaped"') if($sshHost ne 'none'); if(not $grepGatttool =~ /^\s*$/) { Log3 $name, 3, "XiaomiBTLESens ($name) - ExecGatttool_Run: another gatttool process is running. waiting..."; @@ -639,7 +655,7 @@ sub XiaomiBTLESens_FlowerSensHandle0x38($$) { my @dataBatFw = split(" ",$notification); $readings{'batteryLevel'} = hex("0x".$dataBatFw[0]); - $readings{'battery'} = (hex("0x".$dataBatFw[0]) > 20?"ok":"low"); + $readings{'battery'} = (hex("0x".$dataBatFw[0]) > 19 ? "ok" : "low"); $readings{'firmware'} = ($dataBatFw[2]-30).".".($dataBatFw[4]-30).".".($dataBatFw[6]-30); $hash->{helper}{CallBattery} = 1; @@ -690,7 +706,7 @@ sub XiaomiBTLESens_ThermoHygroSensHandle0x18($$) { chomp($notification); $readings{'batteryLevel'} = hex("0x".$notification); - $readings{'battery'} = (hex("0x".$notification) > 20?"ok":"low"); + $readings{'battery'} = (hex("0x".$notification) > 15 ? "ok" : "low"); $hash->{helper}{CallBattery} = 1; XiaomiBTLESens_CallBattery_Timestamp($hash); @@ -876,6 +892,22 @@ sub XiaomiBTLESens_CreateDevicenameHEX($) { return $devicenameHex; } +sub CometBlueBTLE_CmdlinePreventGrepFalsePositive($) { +# 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 +# avoid an *additional* grep process plus pipe... + + my $cmdline = shift; + + + $cmdline =~ s/(.)(.*)/[$1]$2/; + return $cmdline; +} + + + + + @@ -934,6 +966,7 @@ sub XiaomiBTLESens_CreateDevicenameHEX($) { Set

@@ -1019,6 +1052,7 @@ sub XiaomiBTLESens_CreateDevicenameHEX($) { Get