diff --git a/fhem/CHANGED b/fhem/CHANGED index ad2702507..db85d0036 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. + - bugfix: 89_AndroidDB: Connection handling improved - feature: 73_AutoShuttersControl: add abort rain unprotection waiting time - bugfix: lib/FHEM/Core/Authentication/Passwords.pm change commandref diff --git a/fhem/FHEM/89_AndroidDB.pm b/fhem/FHEM/89_AndroidDB.pm index 21bc44f2a..ea0ad9b8b 100644 --- a/fhem/FHEM/89_AndroidDB.pm +++ b/fhem/FHEM/89_AndroidDB.pm @@ -4,7 +4,7 @@ # # 89_AndroidDB # -# Version 0.2 +# Version 0.3 # # FHEM Integration for Android Devices # @@ -195,6 +195,11 @@ sub Attr ($@) $PRESET{_custom_}{$macroName} = $macroKeycodes; } } + elsif ($attrName eq 'preset' && $attrVal =~ /^\@(.+)$/) { + if (!LoadPreset ($hash, $1)) { + Log3 $hash, 2, "Can't load preset from file $1"; + } + } } elsif ($cmd eq 'del') { delete $PRESET{_custom_} if (exists($PRESET{_custom_})); @@ -203,6 +208,49 @@ sub Attr ($@) return undef; } +############################################################################## +# Load macro definitions from file +# File format: +# - Lines starting with a # are treated as comments +# - Lines containing a single word are setting the preset name for the +# following lines +# - Lines in format Name:KeyList are defining a macro. KeyList is a comma +# separated list of keycodes. +############################################################################## + +sub LoadPreset ($$) +{ + my ($hash, $fileName) = @_; + + my @lines; + if (open (PRESETFILE, "<$fileName")) { + @lines = ; + close (PRESETFILE); + } + else { + return 0; + } + + chomp @lines; + my $presetName = ''; + + foreach my $l (@lines) { + next if ($l =~ /^#/); # Comments are allowed + my ($macroName, $keyList) = split (':', $l); + if (!defined($keyList)) { + $presetName = $macroName; + next; + } + elsif (defined($keyList) && $presetName eq '') { + Log3 $hash, 2, "Preset name must be specified before first macro definition in file $fileName"; + return 0; + } + $PRESET{$presetName}{$macroName} = $keyList; + } + + return 1; +} + 1; =pod @@ -258,10 +306,21 @@ sub Attr ($@) Several macro definitions can be specified by seperating them using a blank character.
-
  • preset <Preset>
    - Select a preset of keycode macros. If the same macro name is defined in the selected +
  • preset {<PresetName>|@<PresetFileName>}
    + Select a preset of keycode macros or load a set of macros from a preset defintion + file. If the same macro name is defined in the selected preset and in attribute 'macros', the definition in the 'macros' attribute overwrites - the definition in the preset. + the definition in the preset.
    + A preset defintion file is using the following format:
    +
    +		# Comment
    +		PresetName1
    +		MacroName1:KeyCode[,...]
    +		MacroName2:KeyCode[,...]
    +		...
    +		PresetName2
    +		...
    +		

  • diff --git a/fhem/FHEM/89_AndroidDBHost.pm b/fhem/FHEM/89_AndroidDBHost.pm index 4d146a8a7..f3474d7a5 100644 --- a/fhem/FHEM/89_AndroidDBHost.pm +++ b/fhem/FHEM/89_AndroidDBHost.pm @@ -4,7 +4,7 @@ # # 89_AndroidDBHost # -# Version 0.2 +# Version 0.3 # # FHEM Integration for Android Debug Bridge # @@ -45,6 +45,7 @@ package AndroidDBHost; use strict; use warnings; +use Data::Dumper; use IPC::Open3; use SetExtensions; @@ -59,6 +60,7 @@ BEGIN { readingsBulkUpdateIfChanged readingsBeginUpdate readingsEndUpdate + devspec2array Log3 AttrVal ReadingsVal @@ -67,6 +69,7 @@ BEGIN { init_done deviceEvents gettimeofday + defs )) }; @@ -172,10 +175,35 @@ sub CheckADBServer ($) } readingsSingleUpdate ($hash, 'state', $newState, 1); + + # Update status of client devices + UpdateClientStates ($hash) if ($newState eq 'running'); return $newState eq 'running' ? 1 : 0; } +############################################################################## +# Update connection states of client devices +############################################################################## + +sub UpdateClientStates ($) +{ + my $hash = shift; + + my $device = GetDeviceList ($hash) // return 0; + + foreach my $d (keys %defs) { + my $clHash = $defs{$d}; + if ($clHash->{TYPE} eq 'AndroidDB') { + my $clState = $device->{$clHash->{ADBDevice}} // 'disconnected'; + $clState =~ s/device/connected/; + readingsSingleUpdate ($clHash, 'state', $clState, 1); + } + } + + return 1; +} + ############################################################################## # Check if ADB server is running by connecting to port ############################################################################## @@ -199,7 +227,7 @@ sub Set ($@) my $opt = shift @$a // return 'No set command specified'; # Preprare list of available commands - my $options = 'command start:noArg stop:noArg'; + my $options = 'command disconnectAll:noArg start:noArg stop:noArg'; $opt = lc($opt); @@ -225,6 +253,11 @@ sub Set ($@) my ($rc, $result, $error) = Execute ($hash, $command, '.*', @$a); return $result.$error; } + elsif ($opt eq 'disconnect') { + my ($rc, $result, $error) = Execute ($Hash, 'disconnect', 'disconnected'); + UpdateClientStates ($hash); + return "Disconnecting all devices failed $result $error" if ($rc == 0); + } else { return "Unknown argument $opt, choose one of $options"; } @@ -242,7 +275,7 @@ sub Get ($@) my $opt = shift @$a // return 'No get command specified'; # Prepare list of available commands - my $options = 'status:noArg'; + my $options = 'devices:noArg status:noArg'; $opt = lc($opt); @@ -251,6 +284,22 @@ sub Get ($@) readingsSingleUpdate ($hash, 'state', $status, 1); return "ADB server $status"; } + elsif ($opt eq 'devices') { + my $device = GetDeviceList ($hash) // return 'Cannot read device list'; + my @clDevices = devspec2array ('TYPE=AndroidDB'); + my $list = 'List of devices:

    '; + foreach my $d (keys %$device) { + my @f = (); + foreach my $cd (@clDevices) { + if (exists($defs{$cd}) && $defs{$cd}{ADBDevice} eq $d) { + push @f, $cd; + } + } + $list .= sprintf ('%22s %20s %s
    ', $d, join(',', @f), $device->{$d}); + } + $list .= ''; + return $list; + } else { return "Unknown argument $opt, choose one of $options"; } @@ -316,7 +365,7 @@ sub Execute ($@) # -1 = Error # 0 = No active connections # 1 = Current device connected -# 2 = Multiple devices connected (need to disconnect) +# 2 = Other / multiple device(s) connected (need to disconnect) ############################################################################## sub IsConnected ($) @@ -326,14 +375,13 @@ sub IsConnected ($) my $ioHash = $clHash->{IODev} // return -1; # Get active connections - my ($rc, $result, $error) = Execute ($ioHash, 'devices', 'list'); - return -1 if ($rc == 0); + my $device = GetDeviceList ($ioHash) // return -1; + my $devCount = keys %$device; - my @devices = $result =~ /([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+)/g; - if (scalar(@devices) == 1 && $devices[0] eq $clHash->{ADBDevice}) { - return 1; + if ($devCount == 1) { + return exists($device->{$clHash->{ADBDevice}}) ? 1 : 2; } - elsif (scalar(@devices) > 1) { + elsif ($devCount > 1) { return 2; } @@ -395,6 +443,27 @@ sub Disconnect ($) return $rc; } +############################################################################## +# Get list of devices +############################################################################## + +sub GetDeviceList ($) +{ + my $hash = shift; + + my ($rc, $result, $error) = Execute ($hash, 'devices'); + return undef if ($rc == 0); + + my %devState = (); + my @devices = $result =~ /([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+\s+[a-zA-Z0-9]+)/g; + foreach my $d (@devices) { + my ($address, $state) = split /\s+/, $d; + $devState{$address} = $state // 'disconnected'; + } + + return \%devState; +} + ############################################################################## # Execute commmand and return status code and command output # @@ -455,15 +524,18 @@ sub TCPConnect ($$$) Dependencies: Perl module IPC::Open3, Android Platform Tools

    Android DB Platform Tools installation:
    - Debian/Raspbian: apt-get install android-sdk-platform-tools
    - Windows/MacOSX/Linux x86: Android Developer Portal -

    + +
    Define