2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-09 14:47:00 +00:00

FULLY: Version 2.2

git-svn-id: https://svn.fhem.de/fhem/trunk@24422 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
zap 2021-05-12 07:34:41 +00:00
parent 8216757dd5
commit dbf6d914a7
2 changed files with 85 additions and 43 deletions

View File

@ -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: 89_FULLY: Implemented some new commands
- bugfix: 98_serviced: interval not starting after FHEM start
- feature: 98_serviced: add attr disabledForIntervals
- change: 98_serviced: adapt new help format for commandref

View File

@ -1,13 +1,16 @@
##############################################################################
#
# 89_FULLY.pm 2.1
# 89_FULLY.pm 2.2
#
# $Id$
#
# Control Fully browser on Android tablets from FHEM.
# Requires Fully App Plus license!
#
# (c) 2020 by zap (zap01 <at> t-online <dot> de)
# This program free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License V2.
#
# (c) 2021 by zap (zap01 <at> t-online <dot> de)
#
##############################################################################
@ -28,6 +31,7 @@ sub FULLY_Set ($@);
sub FULLY_Get ($@);
sub FULLY_Attr ($@);
sub FULLY_Detail ($@);
sub FULLY_Notify ($$);
sub FULLY_UpdateDeviceInfo ($);
sub FULLY_Execute ($$$$);
sub FULLY_ExecuteNB ($$$$);
@ -40,7 +44,7 @@ sub FULLY_Decrypt ($);
sub FULLY_Ping ($$);
sub FULLY_SetPolling ($$;$);
my $FULLY_VERSION = '2.1';
my $FULLY_VERSION = '2.2';
# Timeout for Fully requests
my $FULLY_TIMEOUT = 5;
@ -56,20 +60,7 @@ my $FULLY_REQUIRED_VERSION = 1.42;
my $FULLY_DEFAULT_PROT = 'http';
my $FULLY_DEFAULT_PORT = '2323';
# Code for Fully Javascript injection. Not implemented because of problems with Tablet UI.
my $FULLY_FHEM_COMMAND = qq(
function SendRequest(FHEM_Address, Devicename, Command) {
var Port = "8085"
var url = "http://" + FHEM_Address + ":" + Port + "/fhem?XHR=1&cmd." + Devicename + "=" + Command;
var req = new XMLHttpRequest();
req.open("GET", url);
req.send(null);
req = null;
}
);
######################################################################
# Initialize module
@ -79,12 +70,13 @@ sub FULLY_Initialize ($)
{
my ($hash) = @_;
$hash->{DefFn} = "FULLY_Define";
$hash->{UndefFn} = "FULLY_Undef";
$hash->{SetFn} = "FULLY_Set";
$hash->{GetFn} = "FULLY_Get";
$hash->{AttrFn} = "FULLY_Attr";
$hash->{ShutdownFn} = "FULLY_Shutdown";
$hash->{DefFn} = "FULLY_Define";
$hash->{UndefFn} = "FULLY_Undef";
$hash->{SetFn} = "FULLY_Set";
$hash->{GetFn} = "FULLY_Get";
$hash->{AttrFn} = "FULLY_Attr";
$hash->{NotifyFn} = "FULLY_Notify";
$hash->{ShutdownFn} = "FULLY_Shutdown";
$hash->{FW_detailFn} = "FULLY_Detail";
$hash->{parseParams} = 1;
@ -124,9 +116,10 @@ sub FULLY_Define ($$)
$hash->{port} = $FULLY_DEFAULT_PORT;
}
$hash->{version} = $FULLY_VERSION;
$hash->{onForTimer} = 'off';
$hash->{nextUpdate} = 'off';
$hash->{version} = $FULLY_VERSION;
$hash->{NOTIFYDEV} = 'global,TYPE=FULLY';
$hash->{onForTimer} = 'off';
$hash->{nextUpdate} = 'off';
$hash->{fully}{schedule} = 0;
if (@$a == 4) {
@ -275,6 +268,24 @@ sub FULLY_Shutdown ($)
return undef;
}
######################################################################
# FHEM notifications
######################################################################
sub FULLY_Notify ($$)
{
my ($hash, $devhash) = @_;
return if (AttrVal ($hash->{NAME}, 'disable', 0) == 1);
my $events = deviceEvents ($devhash, 1);
return if (!$events);
if ($devhash->{NAME} eq 'global' && grep (/INITIALIZED/, @$events)) {
FULLY_SetPolling ($hash, 1);
}
}
######################################################################
# Enhance device detail view
######################################################################
@ -307,7 +318,8 @@ sub FULLY_Set ($@)
my ($hash, $a, $h) = @_;
my $name = shift @$a;
my $opt = shift @$a;
my $options = "brightness:slider,0,1,255 photo:noArg clearCache:noArg exit:noArg foreground:noArg lock:noArg ".
my $options = "brightness:slider,0,1,255 photo:noArg clearCache:noArg clearWebstorage:noArg ".
"clearCookies:noArg exit:noArg foreground:noArg lock:noArg startApp ".
"motionDetection:on,off off:noArg on:noArg on-for-timer playSound playVideo restart:noArg ".
"screenOffTimer screenSaver:start,stop screenSaverTimer screenSaverURL speak startURL ".
"stopSound:noArg stopVideo:noArg lockKiosk:noArg unlockKiosk:noArg unlock:noArg url ".
@ -315,16 +327,21 @@ sub FULLY_Set ($@)
# Fully commands without argument
my %cmds = (
"clearCache" => "clearCache",
"photo" => "getCamshot",
"exit" => "exitApp",
"restart" => "restartApp",
"on" => "screenOn", "off" => "screenOff",
"lock" => "enabledLockedMode", "unlock" => "disableLockedMode",
"lockKiosk" => "lockKiosk", "unlockKiosk" => "unlockKiosk",
"stopSound" => "stopSound",
"stopVideo" => "stopVideo",
"foreground" => "toForeground"
"clearCache" => "clearCache",
"clearWebstorage" => "clearWebstorage",
"clearCookies" => "clearCookies",
"photo" => "getCamshot",
"exit" => "exitApp",
"restart" => "restartApp",
"on" => "screenOn",
"off" => "screenOff",
"lock" => "enabledLockedMode",
"unlock" => "disableLockedMode",
"lockKiosk" => "lockKiosk",
"unlockKiosk" => "unlockKiosk",
"stopSound" => "stopSound",
"stopVideo" => "stopVideo",
"foreground" => "toForeground"
);
my @c = ();
@ -411,6 +428,11 @@ sub FULLY_Set ($@)
push (@c, "setStringSetting");
push (@p, { "key" => "startURL", "value" => "$value" });
}
elsif ($opt eq 'startApp') {
my $app = shift @$a // return "Usage set $name $opt {APK-Name}";
push (@c, "startApplication");
push (@p, { "package" => "$app" } );
}
elsif ($opt eq 'brightness') {
my $value = shift @$a // return "Usage: set $name brightness 0-255";
$value = 255 if ($value > 255);
@ -502,7 +524,7 @@ sub FULLY_Get ($@)
my ($hash, $a, $h) = @_;
my $name = shift @$a;
my $opt = shift @$a;
my $options = "info:noArg stats:noArg update:noArg";
my $options = "info:noArg update:noArg";
return "Device disabled" if (AttrVal ($name, 'disable', 0) == 1);
return "No password defined for Fully access" if (!exists($hash->{fully}{password}));
@ -514,9 +536,6 @@ sub FULLY_Get ($@)
if (exists($result->{'status'}));
return join ("\n", map { "$_ = $result->{$_}" } sort keys %$result);
}
elsif ($opt eq 'stats') {
return FULLY_Log ($hash, 2, 'Command stats not implemented');
}
elsif ($opt eq 'update') {
FULLY_GetDeviceInfo ($name);
}
@ -582,7 +601,10 @@ sub FULLY_Execute ($$$$)
$i++;
}
return (defined($response) && $response ne '') ? decode_json ($response) : undef;
my $result = eval { decode_json ($response) };
FULLY_Log ($hash, 2, "Error in JSON data") if (!defined($result));
return $result;
}
######################################################################
@ -742,6 +764,9 @@ sub FULLY_ExecuteCB ($$$)
HttpUtils_NonblockingGet ($reqpar);
}
else {
if ($err =~ /^empty answer/) {
$err .= ' (probable reason: timeout)';
}
FULLY_UpdateReadings ($hash, {
"status" => "Error",
"statustext" => "$err",
@ -843,8 +868,10 @@ sub FULLY_UpdateReadings ($$)
}
}
my $screenOn = $result->{isScreenOn} // $result->{screenOn};
readingsBulkUpdate ($hash, 'state', defined($screenOn) ? ($screenOn eq '0' ? 'off' : 'on') : 'unknown');
my $screenOn = $result->{isScreenOn} // $result->{screenOn};
if (defined($screenOn)) {
readingsBulkUpdate ($hash, 'state', $screenOn eq '0' ? 'off' : 'on');
}
if (exists($result->{appVersionName}) && $result->{appVersionName} =~ /^([0-9]\.[0-9]+).*/) {
if ($1 < $FULLY_REQUIRED_VERSION && !exists($hash->{fully}{versionWarn})) {
FULLY_Log ($hash, 1, "Version of fully browser is $1. Version $FULLY_REQUIRED_VERSION is required.");
@ -982,6 +1009,12 @@ sub FULLY_Ping ($$)
<li><b>set &lt;name&gt; clearCache</b><br/>
Clear browser cache.
</li><br/>
<li><b>set &lt;name&gt; clearCookies</b><br/>
Clear cookies.
</li><br/>
<li><b>set &lt;name&gt; clearWebstorage</b><br/>
Clear web storage.
</li><br/>
<li><b>set &lt;name&gt; exit</b><br/>
Terminate Fully.
</li><br/>
@ -1085,32 +1118,40 @@ sub FULLY_Ping ($$)
<b>Attributes</b><br/>
<br/>
<ul>
<a name="disable"></a>
<li><b>disable &lt;0 | 1&gt;</b><br/>
Disable device and automatic polling.
</li><br/>
<a name="expert"></a>
<li><b>expert &lt;0 | 1&gt;</b><br/>
Activate expert mode.
</li><br/>
<a name="pingBeforeCmd"></a>
<li><b>pingBeforeCmd &lt;Count&gt;</b><br/>
Send <i>Count</i> ping request to tablet before executing commands. Valid values
for <i>Count</i> are 0,1,2. Default is 0 (do not send ping request).
</li><br/>
<a name="pollInterval"></a>
<li><b>pollInterval &lt;seconds&gt;</b><br/>
Set polling interval for FULLY device information.
If <i>seconds</i> is 0 polling is turned off. Valid values are from 10 to
86400 seconds.
</li><br/>
<a name="repeatCommand"></a>
<li><b>repeatCommand &lt;Count&gt;</b><br/>
Repeat fully command on failure. Valid values for <i>Count</i> are 0,1,2. Default
is 0 (do not repeat commands).
</li><br/>
<a name="requestTimeout"></a>
<li><b>requestTimeout &lt;seconds&gt;</b><br/>
Set timeout for http requests. Default is 5 seconds. Increase this value if commands
are failing with a timeout error.
</li><br/>
<a name="updateAfterCommand"></a>
<li><b>updateAfterCommand &lt;0 | 1&gt;</b><br/>
When set to 1 update readings after a set command. Default is 0.
</li><br/>
<a name="waitAfterPing"></a>
<li><b>waitAfterPing &lt;Seconds&gt;</b><br/>
Wait specified amount of time after sending ping request to tablet device. Valid
values for <i>Seconds</i> are 0,1,2. Default is 0 (do not wait). Only used if