mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-07 19:04:20 +00:00
All my modules: refactoring code
git-svn-id: https://svn.fhem.de/fhem/trunk@14012 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
591a2717a1
commit
d2a6bcd07b
@ -1,30 +1,7 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# 59_Wunderground.pm
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# http://api.wunderground.com/weather/api
|
||||
|
||||
#
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
@ -36,9 +13,7 @@ use Encode qw(encode_utf8 decode_utf8);
|
||||
use Unit;
|
||||
use Data::Dumper;
|
||||
|
||||
sub Wunderground_Hash2Readings($$;$);
|
||||
|
||||
###################################
|
||||
# initialize ##################################################################
|
||||
sub Wunderground_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
@ -47,15 +22,15 @@ sub Wunderground_Initialize($) {
|
||||
my $webhookFWinstance =
|
||||
join( ",", devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') );
|
||||
|
||||
$hash->{SetFn} = "Wunderground_Set";
|
||||
$hash->{DefFn} = "Wunderground_Define";
|
||||
$hash->{AttrFn} = "Wunderground_Attr";
|
||||
$hash->{UndefFn} = "Wunderground_Undefine";
|
||||
$hash->{SetFn} = "Wunderground_Set";
|
||||
$hash->{AttrFn} = "Wunderground_Attr";
|
||||
$hash->{DbLog_splitFn} = "Unit_DbLog_split";
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} =
|
||||
"disable:0,1 timeout:1,2,3,4,5 pollInterval:300,450,600,750,900 wu_lang:en,de,at,ch,nl,fr,pl wu_pws:1,0 wu_bestfct:1,0 stateReadings stateReadingsFormat:0,1 "
|
||||
"disable:0,1 disabledForIntervals do_not_notify:1,0 timeout:1,2,3,4,5 pollInterval:300,450,600,750,900 wu_lang:en,de,at,ch,nl,fr,pl wu_pws:1,0 wu_bestfct:1,0 stateReadings stateReadingsFormat:0,1 "
|
||||
. "wu_features:multiple-strict,alerts,almanac,astronomy,conditions,currenthurricane,forecast,forecast10day,hourly,hourly10day "
|
||||
. $readingFnAttributes;
|
||||
|
||||
@ -228,11 +203,116 @@ sub Wunderground_Initialize($) {
|
||||
'wind_speed' => { rtype => 'kmph', formula_symbol => 'Ws' },
|
||||
'wind_speed_mph' => { rtype => 'mph', formula_symbol => 'Ws' }
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#####################################
|
||||
# regular Fn ##################################################################
|
||||
sub Wunderground_Define($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $infix = "Wunderground";
|
||||
|
||||
Log3 $name, 5, "Wunderground $name: called function Wunderground_Define()";
|
||||
|
||||
eval {
|
||||
require JSON;
|
||||
import JSON qw( decode_json );
|
||||
};
|
||||
return "Please install Perl JSON to use module Wunderground"
|
||||
if ($@);
|
||||
|
||||
if ( int(@$a) < 2 ) {
|
||||
my $msg = "Wrong syntax: define <name> Wunderground <api-key> <pws-id>";
|
||||
Log3 $name, 4, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
$hash->{TYPE} = "Wunderground";
|
||||
|
||||
$hash->{API_KEY} = @$a[2];
|
||||
$hash->{QUERY} = @$a[3];
|
||||
|
||||
$hash->{QUERY} = "pws:" . $hash->{QUERY}
|
||||
if ( $hash->{QUERY} =~ /^[A-Z]{3,}\d{1,}$/ );
|
||||
|
||||
if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
|
||||
fhem 'attr ' . $name . ' stateReadings temp_c humidity';
|
||||
fhem 'attr ' . $name . ' stateReadingsFormat 1';
|
||||
fhem 'attr ' . $name . ' wu_features astronomy,conditions,forecast';
|
||||
}
|
||||
|
||||
# start the status update timer
|
||||
Wunderground_GetStatus( $hash, 2 );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub Wunderground_Undefine($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
if ( defined( $hash->{fhem}{infix} ) ) {
|
||||
Wunderground_removeExtension( $hash->{fhem}{infix} );
|
||||
}
|
||||
|
||||
Log3 $name, 5,
|
||||
"Wunderground $name: called function Wunderground_Undefine()";
|
||||
|
||||
# Stop the internal GetStatus-Loop and exit
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
# release reverse pointer
|
||||
delete $modules{Wunderground}{defptr}{$name};
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub Wunderground_Set($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 5, "Wunderground $name: called function Wunderground_Set()";
|
||||
|
||||
return "Argument is missing" if ( int(@$a) < 1 );
|
||||
|
||||
my $usage = "Unknown argument " . @$a[1] . ", choose one of update:noArg";
|
||||
|
||||
my $cmd = '';
|
||||
my $result;
|
||||
|
||||
# update
|
||||
if ( lc( @$a[1] ) eq "update" ) {
|
||||
Log3 $name, 3, "Wunderground set $name " . @$a[1];
|
||||
Wunderground_GetStatus($hash);
|
||||
}
|
||||
|
||||
# return usage hint
|
||||
else {
|
||||
return $usage;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub Wunderground_Attr(@) {
|
||||
my ( $cmd, $name, $attrName, $attrVal ) = @_;
|
||||
my $hash = $defs{$name};
|
||||
|
||||
Log3 $name, 5, "Wunderground $name: called function Wunderground_Attr()";
|
||||
|
||||
return
|
||||
"Invalid value for attribute $attrName: minimum value is 1 second, maximum 5 seconds"
|
||||
if ( $attrVal
|
||||
&& $attrName eq "timeout"
|
||||
&& ( $attrVal < 1 || $attrVal > 5 ) );
|
||||
|
||||
return
|
||||
"Invalid value for attribute $attrName: minimum value is 300 seconds"
|
||||
if ( $attrVal && $attrName eq "pollInterval" && $attrVal < 300 );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
# module Fn ####################################################################
|
||||
sub Wunderground_GetStatus($;$) {
|
||||
my ( $hash, $delay ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -286,102 +366,6 @@ sub Wunderground_GetStatus($;$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub Wunderground_Set($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 5, "Wunderground $name: called function Wunderground_Set()";
|
||||
|
||||
return "Argument is missing" if ( int(@$a) < 1 );
|
||||
|
||||
my $usage = "Unknown argument " . @$a[1] . ", choose one of update:noArg";
|
||||
|
||||
my $cmd = '';
|
||||
my $result;
|
||||
|
||||
# update
|
||||
if ( lc( @$a[1] ) eq "update" ) {
|
||||
Log3 $name, 3, "Wunderground set $name " . @$a[1];
|
||||
Wunderground_GetStatus($hash);
|
||||
}
|
||||
|
||||
# return usage hint
|
||||
else {
|
||||
return $usage;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub Wunderground_Define($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $infix = "Wunderground";
|
||||
|
||||
Log3 $name, 5, "Wunderground $name: called function Wunderground_Define()";
|
||||
|
||||
eval {
|
||||
require JSON;
|
||||
import JSON qw( decode_json );
|
||||
};
|
||||
return "Please install Perl JSON to use module Wunderground"
|
||||
if ($@);
|
||||
|
||||
if ( int(@$a) < 2 ) {
|
||||
my $msg = "Wrong syntax: define <name> Wunderground <api-key> <pws-id>";
|
||||
Log3 $name, 4, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
$hash->{TYPE} = "Wunderground";
|
||||
|
||||
$hash->{API_KEY} = @$a[2];
|
||||
$hash->{QUERY} = @$a[3];
|
||||
|
||||
$hash->{QUERY} = "pws:" . $hash->{QUERY}
|
||||
if ( $hash->{QUERY} =~ /^[A-Z]{3,}\d{1,}$/ );
|
||||
|
||||
if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
|
||||
fhem 'attr ' . $name . ' stateReadings temp_c humidity';
|
||||
fhem 'attr ' . $name . ' stateReadingsFormat 1';
|
||||
fhem 'attr ' . $name . ' wu_features astronomy,conditions,forecast';
|
||||
}
|
||||
|
||||
# start the status update timer
|
||||
Wunderground_GetStatus( $hash, 2 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub Wunderground_Attr(@) {
|
||||
my ( $cmd, $name, $attrName, $attrVal ) = @_;
|
||||
my $hash = $defs{$name};
|
||||
|
||||
Log3 $name, 5, "Wunderground $name: called function Wunderground_Attr()";
|
||||
|
||||
return
|
||||
"Invalid value for attribute $attrName: minimum value is 1 second, maximum 5 seconds"
|
||||
if ( $attrVal
|
||||
&& $attrName eq "timeout"
|
||||
&& ( $attrVal < 1 || $attrVal > 5 ) );
|
||||
|
||||
return
|
||||
"Invalid value for attribute $attrName: minimum value is 300 seconds"
|
||||
if ( $attrVal && $attrName eq "pollInterval" && $attrVal < 300 );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
############################################################################################################
|
||||
#
|
||||
# Begin of helper functions
|
||||
#
|
||||
############################################################################################################
|
||||
|
||||
###################################
|
||||
sub Wunderground_SendCommand($$) {
|
||||
my ( $hash, $features ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -420,7 +404,6 @@ sub Wunderground_SendCommand($$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub Wunderground_ReceiveCommand($$$) {
|
||||
my ( $param, $err, $data ) = @_;
|
||||
my $hash = $param->{hash};
|
||||
@ -495,7 +478,8 @@ sub Wunderground_ReceiveCommand($$$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub Wunderground_Hash2Readings($$;$);
|
||||
|
||||
sub Wunderground_Hash2Readings($$;$) {
|
||||
my ( $hash, $h, $r ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -991,27 +975,6 @@ sub Wunderground_Hash2Readings($$;$) {
|
||||
return "ok" if ( !$loop );
|
||||
}
|
||||
|
||||
###################################
|
||||
sub Wunderground_Undefine($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
if ( defined( $hash->{fhem}{infix} ) ) {
|
||||
Wunderground_removeExtension( $hash->{fhem}{infix} );
|
||||
}
|
||||
|
||||
Log3 $name, 5,
|
||||
"Wunderground $name: called function Wunderground_Undefine()";
|
||||
|
||||
# Stop the internal GetStatus-Loop and exit
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
# release reverse pointer
|
||||
delete $modules{Wunderground}{defptr}{$name};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,68 +1,29 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# 70_PHTV.pm
|
||||
# An FHEM Perl module for controlling Philips Televisons
|
||||
# via network connection.
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
package main;
|
||||
|
||||
use 5.012;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
use Time::HiRes qw(gettimeofday);
|
||||
use HttpUtils;
|
||||
use Color;
|
||||
use SetExtensions;
|
||||
use Encode;
|
||||
|
||||
sub PHTV_Set($@);
|
||||
sub PHTV_Get($@);
|
||||
sub PHTV_GetStatus($;$);
|
||||
sub PHTV_Define($$);
|
||||
sub PHTV_Notify($$);
|
||||
sub PHTV_Undefine($$);
|
||||
|
||||
#########################
|
||||
# Forward declaration for remotecontrol module
|
||||
#sub PHTV_RClayout_TV();
|
||||
#sub PHTV_RCmakenotify($$);
|
||||
|
||||
###################################
|
||||
# initialize ##################################################################
|
||||
sub PHTV_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
Log3 $hash, 5, "PHTV_Initialize: Entering";
|
||||
|
||||
$hash->{GetFn} = "PHTV_Get";
|
||||
$hash->{SetFn} = "PHTV_Set";
|
||||
$hash->{NotifyFn} = "PHTV_Notify";
|
||||
$hash->{DefFn} = "PHTV_Define";
|
||||
$hash->{UndefFn} = "PHTV_Undefine";
|
||||
$hash->{SetFn} = "PHTV_Set";
|
||||
$hash->{GetFn} = "PHTV_Get";
|
||||
$hash->{NotifyFn} = "PHTV_Notify";
|
||||
|
||||
$hash->{AttrList} =
|
||||
"disable:0,1 timeout sequentialQuery:0,1 drippyFactor:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 inputs ambiHueLeft ambiHueRight ambiHueTop ambiHueBottom ambiHueLatency:150,200,250,300,350,400,450,500,550,600,650,700,750,800,850,900,950,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000 jsversion:1,5,6 macaddr:textField model wakeupCmd:textField channelsMax:slider,30,1,200 httpLoglevel:1,2,3,4,5 sslVersion device_id auth_key "
|
||||
"disable:0,1 disabledForIntervals do_not_notify:1,0 timeout sequentialQuery:0,1 drippyFactor:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 inputs ambiHueLeft ambiHueRight ambiHueTop ambiHueBottom ambiHueLatency:150,200,250,300,350,400,450,500,550,600,650,700,750,800,850,900,950,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000 jsversion:1,5,6 macaddr:textField model wakeupCmd:textField channelsMax:slider,30,1,200 httpLoglevel:1,2,3,4,5 sslVersion device_id auth_key "
|
||||
. $readingFnAttributes;
|
||||
|
||||
$data{RC_layout}{PHTV_SVG} = "PHTV_RClayout_SVG";
|
||||
@ -88,170 +49,73 @@ sub PHTV_Initialize($) {
|
||||
};
|
||||
|
||||
FHEM_colorpickerInit();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub PHTV_GetStatus($;$) {
|
||||
my ( $hash, $update ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $interval = $hash->{INTERVAL};
|
||||
my $presence = ReadingsVal( $name, "presence", "absent" );
|
||||
my $sequential = AttrVal( $name, "sequentialQuery", 0 );
|
||||
my $querySent = 0;
|
||||
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_GetStatus()";
|
||||
|
||||
$interval = $interval * 1.6
|
||||
if ( ReadingsVal( $name, "ambiHue", "off" ) eq "on" );
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer( gettimeofday() + $interval, "PHTV_GetStatus", $hash, 0 );
|
||||
|
||||
return
|
||||
if ( IsDisabled($name) );
|
||||
|
||||
# try to fetch only some information to check device availability
|
||||
if ( !$update ) {
|
||||
PHTV_SendCommand( $hash, "audio/volume" ) if ( $presence eq "present" );
|
||||
PHTV_SendCommand( $hash, "system" ) if ( $presence eq "absent" );
|
||||
|
||||
# in case we should query the device gently, mark we already sent a query
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter} = 1 if $sequential;
|
||||
}
|
||||
|
||||
# fetch other info if device is on
|
||||
if ( !$querySent
|
||||
&& ( ReadingsVal( $name, "state", "off" ) eq "on" || $update ) )
|
||||
{
|
||||
|
||||
# Read device info every 15 minutes only
|
||||
if (
|
||||
!$querySent
|
||||
&& (
|
||||
!defined( $hash->{helper}{lastFullUpdate} )
|
||||
|| ( !$update
|
||||
&& $hash->{helper}{lastFullUpdate} + 900 le time() )
|
||||
)
|
||||
)
|
||||
{
|
||||
PHTV_SendCommand( $hash, "system" );
|
||||
PHTV_SendCommand( $hash, "ambilight/topology" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
|
||||
# Update state
|
||||
$hash->{helper}{lastFullUpdate} = time();
|
||||
}
|
||||
|
||||
# read audio volume
|
||||
if ( !$querySent && $update ) {
|
||||
PHTV_SendCommand( $hash, "audio/volume" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# read ambilight details
|
||||
if ( !$querySent ) {
|
||||
|
||||
# read ambilight mode
|
||||
PHTV_SendCommand( $hash, "ambilight/mode" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
|
||||
# read ambilight RGB value
|
||||
PHTV_SendCommand( $hash, "ambilight/cached" )
|
||||
if ( ReadingsVal( $name, "ambiMode", "internal" ) ne "internal" );
|
||||
}
|
||||
|
||||
# read all sources if not existing
|
||||
if (
|
||||
!$querySent
|
||||
&& ( !defined( $hash->{helper}{device}{sourceName} )
|
||||
|| !defined( $hash->{helper}{device}{sourceID} ) )
|
||||
)
|
||||
{
|
||||
PHTV_SendCommand( $hash, "sources" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# otherwise read current source
|
||||
elsif ( !$querySent ) {
|
||||
PHTV_SendCommand( $hash, "sources/current" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# read all channels if not existing
|
||||
if (
|
||||
!$querySent
|
||||
&& ( !defined( $hash->{helper}{device}{channelName} )
|
||||
|| !defined( $hash->{helper}{device}{channelID} ) )
|
||||
)
|
||||
{
|
||||
PHTV_SendCommand( $hash, "channels" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# otherwise read current channel
|
||||
elsif ( !$querySent ) {
|
||||
PHTV_SendCommand( $hash, "channels/current" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Input alias handling
|
||||
#
|
||||
if ( AttrVal( $name, "inputs", "" ) ne "" ) {
|
||||
my @inputs = split( ':', AttrVal( $name, "inputs", ":" ) );
|
||||
|
||||
if (@inputs) {
|
||||
foreach (@inputs) {
|
||||
if (m/[^,\s]+(,[^,\s]+)+/) {
|
||||
my @input_names = split( ',', $_ );
|
||||
$input_names[1] =~ s/\s/_/g;
|
||||
$hash->{helper}{device}{inputAliases}{ $input_names[0] } =
|
||||
$input_names[1];
|
||||
$hash->{helper}{device}{inputNames}{ $input_names[1] } =
|
||||
$input_names[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_Get($@) {
|
||||
my ( $hash, @a ) = @_;
|
||||
# regular Fn ##################################################################
|
||||
sub PHTV_Define($$) {
|
||||
my ( $hash, $def ) = @_;
|
||||
my @a = split( "[ \t][ \t]*", $def );
|
||||
my $name = $hash->{NAME};
|
||||
my $state = ReadingsVal( $name, "state", "Initialized" );
|
||||
my $what;
|
||||
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_Get()";
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_Define()";
|
||||
|
||||
return "argument is missing" if ( int(@a) < 2 );
|
||||
return if ( $state =~ /^(pairing.*|initialized)$/i );
|
||||
eval {
|
||||
require JSON;
|
||||
import JSON qw( decode_json encode_json );
|
||||
};
|
||||
return "Please install Perl JSON to use module PHTV"
|
||||
if ($@);
|
||||
|
||||
$what = $a[1];
|
||||
|
||||
if ( $what =~ /^(power|input|volume|mute|rgb)$/ ) {
|
||||
return ReadingsVal( $name, $what, "no such reading: $what" );
|
||||
if ( int(@a) < 3 ) {
|
||||
my $msg =
|
||||
"Wrong syntax: define <name> PHTV <ip-or-hostname> [<poll-interval>]";
|
||||
Log3 $name, 4, $msg;
|
||||
return $msg;
|
||||
}
|
||||
else {
|
||||
return
|
||||
"Unknown argument $what, choose one of power:noArg input:noArg volume:noArg mute:noArg rgb:noArg ";
|
||||
|
||||
$hash->{TYPE} = "PHTV";
|
||||
|
||||
my $address = $a[2];
|
||||
$hash->{helper}{ADDRESS} = $address;
|
||||
|
||||
# use interval of 45sec if not defined
|
||||
my $interval = $a[3] || 45;
|
||||
$hash->{INTERVAL} = $interval;
|
||||
|
||||
readingsSingleUpdate( $hash, "ambiHue", "off", 0 )
|
||||
if ( ReadingsVal( $name, "ambiHue", "" ) ne "off" );
|
||||
|
||||
$hash->{model} = ReadingsVal( $name, "model", undef )
|
||||
if ( ReadingsVal( $name, "model", undef ) );
|
||||
|
||||
$hash->{swversion} = ReadingsVal( $name, "softwareversion", undef )
|
||||
if ( ReadingsVal( $name, "softwareversion", undef ) );
|
||||
|
||||
# set default settings on first define
|
||||
if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
|
||||
fhem 'attr ' . $name . ' webCmd volume:input:rgb';
|
||||
fhem 'attr ' . $name
|
||||
. ' devStateIcon on:rc_GREEN:off off:rc_YELLOW:on absent:rc_STOP:on';
|
||||
fhem 'attr ' . $name . ' icon it_television';
|
||||
|
||||
PHTV_GetStatus($hash);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub PHTV_Undefine($$) {
|
||||
my ( $hash, $arg ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_Undefine()";
|
||||
|
||||
# Stop the internal GetStatus-Loop and exit
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_Set($@) {
|
||||
my ( $hash, @a ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -1396,57 +1260,26 @@ sub PHTV_Set($@) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_Define($$) {
|
||||
my ( $hash, $def ) = @_;
|
||||
my @a = split( "[ \t][ \t]*", $def );
|
||||
sub PHTV_Get($@) {
|
||||
my ( $hash, @a ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $state = ReadingsVal( $name, "state", "Initialized" );
|
||||
my $what;
|
||||
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_Define()";
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_Get()";
|
||||
|
||||
eval {
|
||||
require JSON;
|
||||
import JSON qw( decode_json encode_json );
|
||||
};
|
||||
return "Please install Perl JSON to use module PHTV"
|
||||
if ($@);
|
||||
return "argument is missing" if ( int(@a) < 2 );
|
||||
return if ( $state =~ /^(pairing.*|initialized)$/i );
|
||||
|
||||
if ( int(@a) < 3 ) {
|
||||
my $msg =
|
||||
"Wrong syntax: define <name> PHTV <ip-or-hostname> [<poll-interval>]";
|
||||
Log3 $name, 4, $msg;
|
||||
return $msg;
|
||||
$what = $a[1];
|
||||
|
||||
if ( $what =~ /^(power|input|volume|mute|rgb)$/ ) {
|
||||
return ReadingsVal( $name, $what, "no such reading: $what" );
|
||||
}
|
||||
|
||||
$hash->{TYPE} = "PHTV";
|
||||
|
||||
my $address = $a[2];
|
||||
$hash->{helper}{ADDRESS} = $address;
|
||||
|
||||
# use interval of 45sec if not defined
|
||||
my $interval = $a[3] || 45;
|
||||
$hash->{INTERVAL} = $interval;
|
||||
|
||||
readingsSingleUpdate( $hash, "ambiHue", "off", 0 )
|
||||
if ( ReadingsVal( $name, "ambiHue", "" ) ne "off" );
|
||||
|
||||
$hash->{model} = ReadingsVal( $name, "model", undef )
|
||||
if ( ReadingsVal( $name, "model", undef ) );
|
||||
|
||||
$hash->{swversion} = ReadingsVal( $name, "softwareversion", undef )
|
||||
if ( ReadingsVal( $name, "softwareversion", undef ) );
|
||||
|
||||
# set default settings on first define
|
||||
if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
|
||||
fhem 'attr ' . $name . ' webCmd volume:input:rgb';
|
||||
fhem 'attr ' . $name
|
||||
. ' devStateIcon on:rc_GREEN:off off:rc_YELLOW:on absent:rc_STOP:on';
|
||||
fhem 'attr ' . $name . ' icon it_television';
|
||||
|
||||
PHTV_GetStatus($hash);
|
||||
else {
|
||||
return
|
||||
"Unknown argument $what, choose one of power:noArg input:noArg volume:noArg mute:noArg rgb:noArg ";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub PHTV_Notify($$) {
|
||||
@ -1488,13 +1321,142 @@ sub PHTV_Notify($$) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
############################################################################################################
|
||||
#
|
||||
# Begin of helper functions
|
||||
#
|
||||
############################################################################################################
|
||||
# module Fn ####################################################################
|
||||
sub PHTV_GetStatus($;$) {
|
||||
my ( $hash, $update ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $interval = $hash->{INTERVAL};
|
||||
my $presence = ReadingsVal( $name, "presence", "absent" );
|
||||
my $sequential = AttrVal( $name, "sequentialQuery", 0 );
|
||||
my $querySent = 0;
|
||||
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_GetStatus()";
|
||||
|
||||
$interval = $interval * 1.6
|
||||
if ( ReadingsVal( $name, "ambiHue", "off" ) eq "on" );
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer( gettimeofday() + $interval, "PHTV_GetStatus", $hash, 0 );
|
||||
|
||||
return
|
||||
if ( IsDisabled($name) );
|
||||
|
||||
# try to fetch only some information to check device availability
|
||||
if ( !$update ) {
|
||||
PHTV_SendCommand( $hash, "audio/volume" ) if ( $presence eq "present" );
|
||||
PHTV_SendCommand( $hash, "system" ) if ( $presence eq "absent" );
|
||||
|
||||
# in case we should query the device gently, mark we already sent a query
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter} = 1 if $sequential;
|
||||
}
|
||||
|
||||
# fetch other info if device is on
|
||||
if ( !$querySent
|
||||
&& ( ReadingsVal( $name, "state", "off" ) eq "on" || $update ) )
|
||||
{
|
||||
|
||||
# Read device info every 15 minutes only
|
||||
if (
|
||||
!$querySent
|
||||
&& (
|
||||
!defined( $hash->{helper}{lastFullUpdate} )
|
||||
|| ( !$update
|
||||
&& $hash->{helper}{lastFullUpdate} + 900 le time() )
|
||||
)
|
||||
)
|
||||
{
|
||||
PHTV_SendCommand( $hash, "system" );
|
||||
PHTV_SendCommand( $hash, "ambilight/topology" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
|
||||
# Update state
|
||||
$hash->{helper}{lastFullUpdate} = time();
|
||||
}
|
||||
|
||||
# read audio volume
|
||||
if ( !$querySent && $update ) {
|
||||
PHTV_SendCommand( $hash, "audio/volume" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# read ambilight details
|
||||
if ( !$querySent ) {
|
||||
|
||||
# read ambilight mode
|
||||
PHTV_SendCommand( $hash, "ambilight/mode" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
|
||||
# read ambilight RGB value
|
||||
PHTV_SendCommand( $hash, "ambilight/cached" )
|
||||
if ( ReadingsVal( $name, "ambiMode", "internal" ) ne "internal" );
|
||||
}
|
||||
|
||||
# read all sources if not existing
|
||||
if (
|
||||
!$querySent
|
||||
&& ( !defined( $hash->{helper}{device}{sourceName} )
|
||||
|| !defined( $hash->{helper}{device}{sourceID} ) )
|
||||
)
|
||||
{
|
||||
PHTV_SendCommand( $hash, "sources" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# otherwise read current source
|
||||
elsif ( !$querySent ) {
|
||||
PHTV_SendCommand( $hash, "sources/current" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# read all channels if not existing
|
||||
if (
|
||||
!$querySent
|
||||
&& ( !defined( $hash->{helper}{device}{channelName} )
|
||||
|| !defined( $hash->{helper}{device}{channelID} ) )
|
||||
)
|
||||
{
|
||||
PHTV_SendCommand( $hash, "channels" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
# otherwise read current channel
|
||||
elsif ( !$querySent ) {
|
||||
PHTV_SendCommand( $hash, "channels/current" );
|
||||
$querySent = 1 if $sequential;
|
||||
$hash->{helper}{sequentialQueryCounter}++ if $sequential;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Input alias handling
|
||||
#
|
||||
if ( AttrVal( $name, "inputs", "" ) ne "" ) {
|
||||
my @inputs = split( ':', AttrVal( $name, "inputs", ":" ) );
|
||||
|
||||
if (@inputs) {
|
||||
foreach (@inputs) {
|
||||
if (m/[^,\s]+(,[^,\s]+)+/) {
|
||||
my @input_names = split( ',', $_ );
|
||||
$input_names[1] =~ s/\s/_/g;
|
||||
$hash->{helper}{device}{inputAliases}{ $input_names[0] } =
|
||||
$input_names[1];
|
||||
$hash->{helper}{device}{inputNames}{ $input_names[1] } =
|
||||
$input_names[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_SendCommandDelayed($) {
|
||||
my ($par) = @_;
|
||||
|
||||
@ -1507,7 +1469,6 @@ sub PHTV_SendCommandDelayed($) {
|
||||
$par->{type} );
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_SendCommand($$;$$$) {
|
||||
my ( $hash, $service, $cmd, $type, $delay ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -1613,7 +1574,7 @@ sub PHTV_SendCommand($$;$$$) {
|
||||
'Accept-Charset' => 'UTF-8',
|
||||
},
|
||||
sslargs => {
|
||||
SSL_verify_mode => 0,
|
||||
SSL_verify_mode => 'SSL_VERIFY_NONE',
|
||||
},
|
||||
}
|
||||
);
|
||||
@ -1621,7 +1582,6 @@ sub PHTV_SendCommand($$;$$$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_ReceiveCommand($$$) {
|
||||
my ( $param, $err, $data ) = @_;
|
||||
my $hash = $param->{hash};
|
||||
@ -3079,20 +3039,6 @@ m/^\s*(([{\[][\s\S]+[}\]])|(<html>\s*<head>\s*<title>\s*Ok\s*<\/title>\s*<\/head
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_Undefine($$) {
|
||||
my ( $hash, $arg ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3 $name, 5, "PHTV $name: called function PHTV_Undefine()";
|
||||
|
||||
# Stop the internal GetStatus-Loop and exit
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_GetStateAV($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -3114,7 +3060,6 @@ sub PHTV_GetStateAV($) {
|
||||
}
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_wake ($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -3153,8 +3098,6 @@ sub PHTV_wake ($) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#####################################
|
||||
# Callback from 95_remotecontrol for command makenotify.
|
||||
sub PHTV_RCmakenotify($$) {
|
||||
my ( $nam, $ndev ) = @_;
|
||||
my $nname = "notify_$nam";
|
||||
@ -3164,10 +3107,6 @@ sub PHTV_RCmakenotify($$) {
|
||||
return "Notify created by PHTV: $nname";
|
||||
}
|
||||
|
||||
#####################################
|
||||
# RC layouts
|
||||
|
||||
# Philips TV with SVG
|
||||
sub PHTV_RClayout_SVG() {
|
||||
my @row;
|
||||
|
||||
@ -3202,7 +3141,6 @@ sub PHTV_RClayout_SVG() {
|
||||
return @row;
|
||||
}
|
||||
|
||||
# Philips TV with PNG
|
||||
sub PHTV_RClayout() {
|
||||
my @row;
|
||||
|
||||
@ -3233,7 +3171,6 @@ sub PHTV_RClayout() {
|
||||
return @row;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_GetRemotecontrolCommand($) {
|
||||
my ($command) = @_;
|
||||
my $commands = {
|
||||
@ -3305,26 +3242,22 @@ sub PHTV_GetRemotecontrolCommand($) {
|
||||
}
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_isinteger {
|
||||
defined $_[0] && $_[0] =~ /^[+-]?\d+$/;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_bri2pct($) {
|
||||
my ($bri) = @_;
|
||||
return 0 if ( $bri <= 0 );
|
||||
return int( $bri / 255 * 100 + 0.5 );
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_pct2bri($) {
|
||||
my ($pct) = @_;
|
||||
return 0 if ( $pct <= 0 );
|
||||
return int( $pct / 100 * 255 + 0.5 );
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_hex2rgb($) {
|
||||
my ($hex) = @_;
|
||||
if ( uc($hex) =~ /^(..)(..)(..)$/ ) {
|
||||
@ -3339,7 +3272,6 @@ sub PHTV_hex2rgb($) {
|
||||
}
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_rgb2hex($$$) {
|
||||
my ( $r, $g, $b ) = @_;
|
||||
my $return = sprintf( "%2.2X%2.2X%2.2X", $r, $g, $b );
|
||||
@ -3347,7 +3279,6 @@ sub PHTV_rgb2hex($$$) {
|
||||
return uc($return);
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_hex2hsb($;$) {
|
||||
my ( $hex, $type ) = @_;
|
||||
$type = lc($type) if ( defined( ($type) && $type ne "" ) );
|
||||
@ -3364,14 +3295,12 @@ sub PHTV_hex2hsb($;$) {
|
||||
}
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_hsb2hex($$$) {
|
||||
my ( $h, $s, $b ) = @_;
|
||||
my $rgb = PHTV_hsb2rgb( $h, $s, $b );
|
||||
return PHTV_rgb2hex( $rgb->{r}, $rgb->{g}, $rgb->{b} );
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_rgb2hsb ($$$) {
|
||||
my ( $r, $g, $b ) = @_;
|
||||
|
||||
@ -3393,7 +3322,6 @@ sub PHTV_rgb2hsb ($$$) {
|
||||
};
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_hsb2rgb ($$$) {
|
||||
my ( $h, $s, $bri ) = @_;
|
||||
|
||||
@ -3415,7 +3343,6 @@ sub PHTV_hsb2rgb ($$$) {
|
||||
};
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_rgb2hsv($$$) {
|
||||
my ( $r, $g, $b ) = @_;
|
||||
my ( $M, $m, $c, $h, $s, $v );
|
||||
@ -3457,7 +3384,6 @@ sub PHTV_rgb2hsv($$$) {
|
||||
};
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_hsv2rgb($$$) {
|
||||
my ( $h, $s, $v ) = @_;
|
||||
my $r = 0.0;
|
||||
@ -3518,7 +3444,6 @@ sub PHTV_hsv2rgb($$$) {
|
||||
};
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_max {
|
||||
my ( $max, @vars ) = @_;
|
||||
for (@vars) {
|
||||
@ -3528,7 +3453,6 @@ sub PHTV_max {
|
||||
return $max;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_min {
|
||||
my ( $min, @vars ) = @_;
|
||||
for (@vars) {
|
||||
@ -3537,7 +3461,6 @@ sub PHTV_min {
|
||||
return $min;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_createDeviceId() {
|
||||
my $deviceid;
|
||||
my @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9 );
|
||||
@ -3545,7 +3468,6 @@ sub PHTV_createDeviceId() {
|
||||
return $deviceid;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub PHTV_createAuthSignature($$$) {
|
||||
my ( $timestamp, $pin, $secretkey ) = @_;
|
||||
my $base64 = 0;
|
||||
|
@ -1,24 +1,22 @@
|
||||
# $Id$
|
||||
###############################################################################
|
||||
#
|
||||
# Also see API documentation:
|
||||
# $Id$
|
||||
# https://pushover.net/api
|
||||
|
||||
#
|
||||
package main;
|
||||
|
||||
use HttpUtils;
|
||||
use utf8;
|
||||
use Data::Dumper;
|
||||
use HttpUtils;
|
||||
use SetExtensions;
|
||||
use Encode;
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# initialize ##################################################################
|
||||
sub Pushover_Initialize($$) {
|
||||
my ($hash) = @_;
|
||||
$hash->{DefFn} = "Pushover_Define";
|
||||
$hash->{UndefFn} = "Pushover_Undefine";
|
||||
$hash->{SetFn} = "Pushover_Set";
|
||||
|
||||
$hash->{AttrList} =
|
||||
"disable:0,1 disabledForIntervals do_not_notify:0,1 timestamp:0,1 title sound:pushover,bike,bugle,cashregister,classical,cosmic,falling,gamelan,incoming,intermission,magic,mechanical,pianobar,siren,spacealarm,tugboat,alien,climb,persistent,echo,updown,none device priority:0,1,2,-1,-2 callbackUrl retry expire "
|
||||
. $readingFnAttributes;
|
||||
@ -27,39 +25,7 @@ sub Pushover_Initialize($$) {
|
||||
$hash->{'.msgParams'} = { parseParams => 1, };
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_addExtension($$$) {
|
||||
my ( $name, $func, $link ) = @_;
|
||||
|
||||
my $url = "/$link";
|
||||
|
||||
return 0
|
||||
if ( defined( $data{FWEXT}{$url} )
|
||||
&& $data{FWEXT}{$url}{deviceName} ne $name );
|
||||
|
||||
Log3 $name, 2,
|
||||
"Pushover $name: Registering Pushover for webhook URI $url ...";
|
||||
$data{FWEXT}{$url}{deviceName} = $name;
|
||||
$data{FWEXT}{$url}{FUNC} = $func;
|
||||
$data{FWEXT}{$url}{LINK} = $link;
|
||||
$name->{HASH}{FHEMWEB_URI} = $url;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_removeExtension($) {
|
||||
my ($link) = @_;
|
||||
|
||||
my $url = "/$link";
|
||||
my $name = $data{FWEXT}{$url}{deviceName};
|
||||
Log3 $name, 2,
|
||||
"Pushover $name: Unregistering Pushover for webhook URI $url...";
|
||||
delete $data{FWEXT}{$url};
|
||||
delete $name->{HASH}{FHEMWEB_URI};
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# regular Fn ##################################################################
|
||||
sub Pushover_Define($$) {
|
||||
my ( $hash, $def ) = @_;
|
||||
|
||||
@ -67,8 +33,8 @@ sub Pushover_Define($$) {
|
||||
my $name = shift @a;
|
||||
my $type = shift @a;
|
||||
|
||||
return
|
||||
"Invalid number of arguments: define <name> Pushover <token> <user> [<infix>]"
|
||||
return "Invalid number of arguments: "
|
||||
. "define <name> Pushover <token> <user> [<infix>]"
|
||||
if ( int(@a) < 2 );
|
||||
|
||||
my ( $token, $user, $infix ) = @a;
|
||||
@ -107,9 +73,10 @@ sub Pushover_Define($$) {
|
||||
else {
|
||||
return "App or user/group token missing.";
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_Undefine($$) {
|
||||
my ( $hash, $name ) = @_;
|
||||
|
||||
@ -122,7 +89,6 @@ sub Pushover_Undefine($$) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_Set($@) {
|
||||
my ( $hash, $name, $cmd, @args ) = @_;
|
||||
my ( $a, $h ) = parseParams( join " ", @args );
|
||||
@ -169,9 +135,199 @@ sub Pushover_Set($@) {
|
||||
|
||||
return Pushover_SetMessage( $hash, @args )
|
||||
if ( $cmd eq 'msg' );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
# module Fn ####################################################################
|
||||
sub Pushover_addExtension($$$) {
|
||||
my ( $name, $func, $link ) = @_;
|
||||
|
||||
my $url = "/$link";
|
||||
|
||||
return 0
|
||||
if ( defined( $data{FWEXT}{$url} )
|
||||
&& $data{FWEXT}{$url}{deviceName} ne $name );
|
||||
|
||||
Log3 $name, 2,
|
||||
"Pushover $name: Registering Pushover for webhook URI $url ...";
|
||||
$data{FWEXT}{$url}{deviceName} = $name;
|
||||
$data{FWEXT}{$url}{FUNC} = $func;
|
||||
$data{FWEXT}{$url}{LINK} = $link;
|
||||
$name->{HASH}{FHEMWEB_URI} = $url;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub Pushover_removeExtension($) {
|
||||
my ($link) = @_;
|
||||
|
||||
my $url = "/$link";
|
||||
my $name = $data{FWEXT}{$url}{deviceName};
|
||||
Log3 $name, 2,
|
||||
"Pushover $name: Unregistering Pushover for webhook URI $url...";
|
||||
delete $data{FWEXT}{$url};
|
||||
delete $name->{HASH}{FHEMWEB_URI};
|
||||
}
|
||||
|
||||
sub Pushover_CGI() {
|
||||
my ($request) = @_;
|
||||
|
||||
my $hash;
|
||||
my $name = "";
|
||||
my $link = "";
|
||||
my $URI = "";
|
||||
|
||||
# data received
|
||||
if ( $request =~ m,^(/[^/]+?)(?:\&|\?)(.*)?$, ) {
|
||||
$link = $1;
|
||||
$URI = $2;
|
||||
|
||||
# get device name
|
||||
$name = $data{FWEXT}{$link}{deviceName} if ( $data{FWEXT}{$link} );
|
||||
$hash = $defs{$name};
|
||||
|
||||
# return error if no such device
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK No Pushover device for callback $link" )
|
||||
unless ($name);
|
||||
|
||||
Log3 $name, 4, "Pushover $name callback: link='$link' URI='$URI'";
|
||||
|
||||
my $webArgs;
|
||||
my $receipt = "";
|
||||
my %revReadings;
|
||||
|
||||
# extract values from URI
|
||||
foreach my $pv ( split( "&", $URI ) ) {
|
||||
next if ( $pv eq "" );
|
||||
$pv =~ s/\+/ /g;
|
||||
$pv =~ s/%([\dA-F][\dA-F])/chr(hex($1))/ige;
|
||||
my ( $p, $v ) = split( "=", $pv, 2 );
|
||||
|
||||
$webArgs->{$p} = $v;
|
||||
}
|
||||
|
||||
if ( defined( $webArgs->{receipt} ) ) {
|
||||
$receipt = $webArgs->{receipt};
|
||||
}
|
||||
elsif ( defined( $webArgs->{FhemCallbackId} ) ) {
|
||||
$receipt = $webArgs->{FhemCallbackId};
|
||||
}
|
||||
else {
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK missing argument receipt or FhemCallbackId" );
|
||||
}
|
||||
|
||||
# search for existing receipt
|
||||
keys %{ $hash->{READINGS} };
|
||||
while ( my ( $key, $value ) = each %{ $hash->{READINGS} } ) {
|
||||
$revReadings{ $value->{VAL} } = $1
|
||||
if ( defined( $value->{VAL} ) && $key =~ /^cb_(\d+)$/ );
|
||||
}
|
||||
|
||||
if ( defined( $revReadings{$receipt} ) ) {
|
||||
my $rAct = "cbAct_" . $revReadings{$receipt};
|
||||
my $rAck = "cbAck_" . $revReadings{$receipt};
|
||||
my $rAckAt = "cbAckAt_" . $revReadings{$receipt};
|
||||
my $rAckBy = "cbAckBy_" . $revReadings{$receipt};
|
||||
my $rCancelId = "cbCancelId_" . $revReadings{$receipt};
|
||||
my $rDev = "cbDev_" . $revReadings{$receipt};
|
||||
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK " . $receipt . ": invalid argument 'acknowledged'" )
|
||||
if ( !defined( $webArgs->{acknowledged} )
|
||||
|| $webArgs->{acknowledged} ne "1" );
|
||||
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK " . $receipt . ": invalid argument 'acknowledged_by'" )
|
||||
if ( !defined( $webArgs->{acknowledged_by} )
|
||||
|| $webArgs->{acknowledged_by} ne $hash->{USER_KEY} );
|
||||
|
||||
if ( ReadingsVal( $name, $rAck, "1" ) eq "0"
|
||||
&& $revReadings{$receipt} > int( time() ) )
|
||||
{
|
||||
delete $hash->{READINGS}{$rCancelId}
|
||||
if ( defined( $hash->{READINGS}{$rCancelId} ) );
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
readingsBulkUpdate( $hash, $rAck, "1" );
|
||||
readingsBulkUpdate( $hash, $rAckBy,
|
||||
$webArgs->{acknowledged_by} );
|
||||
|
||||
if ( defined( $webArgs->{acknowledged_at} )
|
||||
&& $webArgs->{acknowledged_at} ne "" )
|
||||
{
|
||||
readingsBulkUpdate( $hash, $rAckAt,
|
||||
$webArgs->{acknowledged_at} );
|
||||
}
|
||||
else {
|
||||
readingsBulkUpdate( $hash, $rAckAt, int( time() ) );
|
||||
}
|
||||
|
||||
my $redirect = "";
|
||||
|
||||
# run FHEM command if desired
|
||||
if ( ReadingsVal( $name, $rAct, "pushover://" ) !~
|
||||
/^[\w-]+:\/\/.*$/ )
|
||||
{
|
||||
$redirect = "pushover://";
|
||||
|
||||
fhem ReadingsVal( $name, $rAct, "" );
|
||||
readingsBulkUpdate( $hash, $rAct,
|
||||
"executed: " . ReadingsVal( $name, $rAct, "" ) );
|
||||
}
|
||||
|
||||
# redirect to presented URL
|
||||
if ( ReadingsVal( $name, $rAct, "none" ) =~ /^[\w-]+:\/\/.*$/ )
|
||||
{
|
||||
$redirect = ReadingsVal( $name, $rAct, "" );
|
||||
}
|
||||
|
||||
readingsEndUpdate( $hash, 1 );
|
||||
|
||||
return (
|
||||
"text/html; charset=utf-8",
|
||||
"<html><head><meta http-equiv=\"refresh\" content=\"0;url="
|
||||
. $redirect
|
||||
. "\"></head><body><a href=\""
|
||||
. $redirect
|
||||
. "\">Click here to get redirected to your destination"
|
||||
. "</a></body></html>"
|
||||
) if ( $redirect ne "" );
|
||||
|
||||
}
|
||||
else {
|
||||
Log3 $name, 4,
|
||||
"Pushover $name callback: " . $receipt . " has expired";
|
||||
return (
|
||||
"text/plain; charset=utf-8",
|
||||
"NOK " . $receipt . " has expired"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Log3 $name, 4,
|
||||
"Pushover $name callback: unable to find existing receipt "
|
||||
. $receipt;
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK unable to find existing receipt " . $receipt );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# no data received
|
||||
else {
|
||||
Log3 $name, 5,
|
||||
"Pushover $name callback: received malformed request\n$request";
|
||||
return ( "text/plain; charset=utf-8", "NOK malformed request" );
|
||||
}
|
||||
|
||||
return ( "text/plain; charset=utf-8", "OK" );
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_SendCommand($$;$\%) {
|
||||
my ( $hash, $service, $cmd, $type ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -267,6 +423,10 @@ sub Pushover_SendCommand($$;$\%) {
|
||||
Accept => 'application/json;charset=UTF-8',
|
||||
'Accept-Charset' => 'UTF-8',
|
||||
},
|
||||
|
||||
# sslargs => {
|
||||
# SSL_verify_mode => 'SSL_verify_PEER',
|
||||
# },
|
||||
}
|
||||
);
|
||||
|
||||
@ -316,7 +476,6 @@ sub Pushover_SendCommand($$;$\%) {
|
||||
return;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_ReceiveCommand($$$) {
|
||||
my ( $param, $err, $data ) = @_;
|
||||
my $hash = $param->{hash};
|
||||
@ -711,7 +870,6 @@ sub Pushover_ReceiveCommand($$$) {
|
||||
return;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_ValidateUser ($;$) {
|
||||
my ( $hash, $update ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -739,7 +897,6 @@ sub Pushover_ValidateUser ($;$) {
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_SetMessage {
|
||||
my $hash = shift;
|
||||
my $name = $hash->{NAME};
|
||||
@ -843,7 +1000,6 @@ sub Pushover_SetMessage {
|
||||
return Pushover_SetMessage2( $hash, "msg", undef, \%values );
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_SetMessage2 ($$$$) {
|
||||
my ( $hash, $cmd, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -1236,165 +1392,6 @@ sub Pushover_CancelMessage ($$$$) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
sub Pushover_CGI() {
|
||||
my ($request) = @_;
|
||||
|
||||
my $hash;
|
||||
my $name = "";
|
||||
my $link = "";
|
||||
my $URI = "";
|
||||
|
||||
# data received
|
||||
if ( $request =~ m,^(/[^/]+?)(?:\&|\?)(.*)?$, ) {
|
||||
$link = $1;
|
||||
$URI = $2;
|
||||
|
||||
# get device name
|
||||
$name = $data{FWEXT}{$link}{deviceName} if ( $data{FWEXT}{$link} );
|
||||
$hash = $defs{$name};
|
||||
|
||||
# return error if no such device
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK No Pushover device for callback $link" )
|
||||
unless ($name);
|
||||
|
||||
Log3 $name, 4, "Pushover $name callback: link='$link' URI='$URI'";
|
||||
|
||||
my $webArgs;
|
||||
my $receipt = "";
|
||||
my %revReadings;
|
||||
|
||||
# extract values from URI
|
||||
foreach my $pv ( split( "&", $URI ) ) {
|
||||
next if ( $pv eq "" );
|
||||
$pv =~ s/\+/ /g;
|
||||
$pv =~ s/%([\dA-F][\dA-F])/chr(hex($1))/ige;
|
||||
my ( $p, $v ) = split( "=", $pv, 2 );
|
||||
|
||||
$webArgs->{$p} = $v;
|
||||
}
|
||||
|
||||
if ( defined( $webArgs->{receipt} ) ) {
|
||||
$receipt = $webArgs->{receipt};
|
||||
}
|
||||
elsif ( defined( $webArgs->{FhemCallbackId} ) ) {
|
||||
$receipt = $webArgs->{FhemCallbackId};
|
||||
}
|
||||
else {
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK missing argument receipt or FhemCallbackId" );
|
||||
}
|
||||
|
||||
# search for existing receipt
|
||||
keys %{ $hash->{READINGS} };
|
||||
while ( my ( $key, $value ) = each %{ $hash->{READINGS} } ) {
|
||||
$revReadings{ $value->{VAL} } = $1
|
||||
if ( defined( $value->{VAL} ) && $key =~ /^cb_(\d+)$/ );
|
||||
}
|
||||
|
||||
if ( defined( $revReadings{$receipt} ) ) {
|
||||
my $rAct = "cbAct_" . $revReadings{$receipt};
|
||||
my $rAck = "cbAck_" . $revReadings{$receipt};
|
||||
my $rAckAt = "cbAckAt_" . $revReadings{$receipt};
|
||||
my $rAckBy = "cbAckBy_" . $revReadings{$receipt};
|
||||
my $rCancelId = "cbCancelId_" . $revReadings{$receipt};
|
||||
my $rDev = "cbDev_" . $revReadings{$receipt};
|
||||
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK " . $receipt . ": invalid argument 'acknowledged'" )
|
||||
if ( !defined( $webArgs->{acknowledged} )
|
||||
|| $webArgs->{acknowledged} ne "1" );
|
||||
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK " . $receipt . ": invalid argument 'acknowledged_by'" )
|
||||
if ( !defined( $webArgs->{acknowledged_by} )
|
||||
|| $webArgs->{acknowledged_by} ne $hash->{USER_KEY} );
|
||||
|
||||
if ( ReadingsVal( $name, $rAck, "1" ) eq "0"
|
||||
&& $revReadings{$receipt} > int( time() ) )
|
||||
{
|
||||
delete $hash->{READINGS}{$rCancelId}
|
||||
if ( defined( $hash->{READINGS}{$rCancelId} ) );
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
readingsBulkUpdate( $hash, $rAck, "1" );
|
||||
readingsBulkUpdate( $hash, $rAckBy,
|
||||
$webArgs->{acknowledged_by} );
|
||||
|
||||
if ( defined( $webArgs->{acknowledged_at} )
|
||||
&& $webArgs->{acknowledged_at} ne "" )
|
||||
{
|
||||
readingsBulkUpdate( $hash, $rAckAt,
|
||||
$webArgs->{acknowledged_at} );
|
||||
}
|
||||
else {
|
||||
readingsBulkUpdate( $hash, $rAckAt, int( time() ) );
|
||||
}
|
||||
|
||||
my $redirect = "";
|
||||
|
||||
# run FHEM command if desired
|
||||
if ( ReadingsVal( $name, $rAct, "pushover://" ) !~
|
||||
/^[\w-]+:\/\/.*$/ )
|
||||
{
|
||||
$redirect = "pushover://";
|
||||
|
||||
fhem ReadingsVal( $name, $rAct, "" );
|
||||
readingsBulkUpdate( $hash, $rAct,
|
||||
"executed: " . ReadingsVal( $name, $rAct, "" ) );
|
||||
}
|
||||
|
||||
# redirect to presented URL
|
||||
if ( ReadingsVal( $name, $rAct, "none" ) =~ /^[\w-]+:\/\/.*$/ )
|
||||
{
|
||||
$redirect = ReadingsVal( $name, $rAct, "" );
|
||||
}
|
||||
|
||||
readingsEndUpdate( $hash, 1 );
|
||||
|
||||
return (
|
||||
"text/html; charset=utf-8",
|
||||
"<html><head><meta http-equiv=\"refresh\" content=\"0;url="
|
||||
. $redirect
|
||||
. "\"></head><body><a href=\""
|
||||
. $redirect
|
||||
. "\">Click here to get redirected to your destination"
|
||||
. "</a></body></html>"
|
||||
) if ( $redirect ne "" );
|
||||
|
||||
}
|
||||
else {
|
||||
Log3 $name, 4,
|
||||
"Pushover $name callback: " . $receipt . " has expired";
|
||||
return (
|
||||
"text/plain; charset=utf-8",
|
||||
"NOK " . $receipt . " has expired"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
Log3 $name, 4,
|
||||
"Pushover $name callback: unable to find existing receipt "
|
||||
. $receipt;
|
||||
return ( "text/plain; charset=utf-8",
|
||||
"NOK unable to find existing receipt " . $receipt );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# no data received
|
||||
else {
|
||||
Log3 $name, 5,
|
||||
"Pushover $name callback: received malformed request\n$request";
|
||||
return ( "text/plain; charset=utf-8", "NOK malformed request" );
|
||||
}
|
||||
|
||||
return ( "text/plain; charset=utf-8", "OK" );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
###############################################################################
|
||||
|
@ -1,50 +1,13 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# 70_ONKYO_AVR_ZONE.pm
|
||||
# An FHEM Perl module for controlling ONKYO A/V receivers
|
||||
# via network connection.
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Time::HiRes qw(usleep);
|
||||
use Symbol qw<qualify_to_ref>;
|
||||
use Data::Dumper;
|
||||
use Symbol qw<qualify_to_ref>;
|
||||
|
||||
$Data::Dumper::Sortkeys = 1;
|
||||
|
||||
sub ONKYO_AVR_ZONE_Set($$$);
|
||||
sub ONKYO_AVR_ZONE_Get($$$);
|
||||
sub ONKYO_AVR_ZONE_Define($$$);
|
||||
sub ONKYO_AVR_ZONE_Undefine($$);
|
||||
|
||||
#########################
|
||||
# Forward declaration for remotecontrol module
|
||||
sub ONKYO_AVR_ZONE_RClayout_TV();
|
||||
sub ONKYO_AVR_ZONE_RCmakenotify($$);
|
||||
|
||||
###################################
|
||||
# initialize ##################################################################
|
||||
sub ONKYO_AVR_ZONE_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
@ -52,22 +15,17 @@ sub ONKYO_AVR_ZONE_Initialize($) {
|
||||
|
||||
require "$attr{global}{modpath}/FHEM/ONKYOdb.pm";
|
||||
|
||||
$hash->{Match} = ".+";
|
||||
|
||||
$hash->{DefFn} = "ONKYO_AVR_ZONE_Define";
|
||||
$hash->{UndefFn} = "ONKYO_AVR_ZONE_Undefine";
|
||||
|
||||
# $hash->{DeleteFn} = "ONKYO_AVR_ZONE_Delete";
|
||||
$hash->{SetFn} = "ONKYO_AVR_ZONE_Set";
|
||||
$hash->{GetFn} = "ONKYO_AVR_ZONE_Get";
|
||||
|
||||
# $hash->{AttrFn} = "ONKYO_AVR_ZONE_Attr";
|
||||
# $hash->{NotifyFn} = "ONKYO_AVR_ZONE_Notify";
|
||||
$hash->{SetFn} = "ONKYO_AVR_ZONE_Set";
|
||||
$hash->{GetFn} = "ONKYO_AVR_ZONE_Get";
|
||||
$hash->{ParseFn} = "ONKYO_AVR_ZONE_Parse";
|
||||
|
||||
$hash->{Match} = ".+";
|
||||
|
||||
$hash->{AttrList} =
|
||||
"IODev do_not_notify:1,0 "
|
||||
. "volumeSteps:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 inputs disable:0,1 model wakeupCmd:textField "
|
||||
"IODev disable:0,1 disabledForIntervals do_not_notify:1,0 "
|
||||
. "volumeSteps:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 inputs model wakeupCmd:textField "
|
||||
. $readingFnAttributes;
|
||||
|
||||
# $data{RC_layout}{ONKYO_AVR_ZONE_SVG} = "ONKYO_AVR_ZONE_RClayout_SVG";
|
||||
@ -90,7 +48,7 @@ sub ONKYO_AVR_ZONE_Initialize($) {
|
||||
$hash->{parseParams} = 1;
|
||||
}
|
||||
|
||||
###################################
|
||||
# regular Fn ##################################################################
|
||||
sub ONKYO_AVR_ZONE_Define($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -125,8 +83,8 @@ sub ONKYO_AVR_ZONE_Define($$$) {
|
||||
. $modules{ONKYO_AVR_ZONE}{defptr}{$IOname}{$zone}{NAME};
|
||||
}
|
||||
elsif ( !defined($IOhash) ) {
|
||||
return
|
||||
"No matching I/O device found, please define a ONKYO_AVR device first";
|
||||
return "No matching I/O device found, "
|
||||
. "please define a ONKYO_AVR device first";
|
||||
}
|
||||
elsif ( !defined( $IOhash->{TYPE} ) || !defined( $IOhash->{NAME} ) ) {
|
||||
return "IODev does not seem to be existing";
|
||||
@ -182,10 +140,9 @@ sub ONKYO_AVR_ZONE_Define($$$) {
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "mute", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "volume", "query" );
|
||||
|
||||
return;
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub ONKYO_AVR_ZONE_Undefine($$) {
|
||||
my ( $hash, $name ) = @_;
|
||||
my $zone = $hash->{ZONE};
|
||||
@ -207,300 +164,6 @@ sub ONKYO_AVR_ZONE_Undefine($$) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
#############################
|
||||
sub ONKYO_AVR_ZONE_Parse($$) {
|
||||
my ( $IOhash, $msg ) = @_;
|
||||
my @matches;
|
||||
my $IOname = $IOhash->{NAME};
|
||||
my $zone = $msg->{zone} || "";
|
||||
|
||||
delete $msg->{zone} if ( defined( $msg->{zone} ) );
|
||||
|
||||
Log3 $IOname, 5,
|
||||
"ONKYO_AVR $IOname: called function ONKYO_AVR_ZONE_Parse()";
|
||||
|
||||
foreach my $d ( keys %defs ) {
|
||||
my $hash = $defs{$d};
|
||||
my $name = $hash->{NAME};
|
||||
my $state = ReadingsVal( $name, "power", "off" );
|
||||
|
||||
if ( $hash->{TYPE} eq "ONKYO_AVR_ZONE"
|
||||
&& $hash->{IODev} eq $IOhash
|
||||
&& ( $zone eq "" || $hash->{ZONE} eq $zone ) )
|
||||
{
|
||||
push @matches, $d;
|
||||
|
||||
# Update readings
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
foreach my $cmd ( keys %{$msg} ) {
|
||||
my $value = $msg->{$cmd};
|
||||
|
||||
$hash->{INPUT} = $value and next if ( $cmd eq "INPUT_RAW" );
|
||||
$hash->{CHANNEL} = $value and next if ( $cmd eq "CHANNEL_RAW" );
|
||||
|
||||
Log3 $name, 4, "ONKYO_AVR_ZONE $name: rcv $cmd = $value";
|
||||
|
||||
# presence
|
||||
if ( $cmd eq "presence" && $value eq "present" ) {
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "power", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "input", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "mute", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "volume", "query" );
|
||||
}
|
||||
|
||||
# input
|
||||
elsif ( $cmd eq "input" ) {
|
||||
|
||||
# Input alias handling
|
||||
if (
|
||||
defined(
|
||||
$hash->{helper}{receiver}{input_aliases}{$value}
|
||||
)
|
||||
)
|
||||
{
|
||||
Log3 $name, 4,
|
||||
"ONKYO_AVR_AVR $name: Input aliasing '$value' to '"
|
||||
. $hash->{helper}{receiver}{input_aliases}{$value}
|
||||
. "'";
|
||||
$value =
|
||||
$hash->{helper}{receiver}{input_aliases}{$value};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# power
|
||||
elsif ( $cmd eq "power" ) {
|
||||
readingsBulkUpdate( $hash, "presence", "present" )
|
||||
if ( ReadingsVal( $name, "presence", "-" ) ne "present" );
|
||||
}
|
||||
|
||||
# balance
|
||||
elsif ( $cmd eq "balance" ) {
|
||||
my $prefix = "";
|
||||
$prefix = "-" if ( $value =~ /^\-.*/ );
|
||||
$value = substr( $value, 1 ) if ( $value =~ /^[\+|\-].*/ );
|
||||
|
||||
$value = $prefix . ONKYO_AVR_hex2dec($value);
|
||||
}
|
||||
|
||||
# preset
|
||||
elsif ( $cmd eq "preset" ) {
|
||||
|
||||
if ( defined( $IOhash->{helper}{receiver}{preset} ) ) {
|
||||
|
||||
foreach my $id (
|
||||
sort keys %{ $IOhash->{helper}{receiver}{preset} } )
|
||||
{
|
||||
my $presetName =
|
||||
$IOhash->{helper}{receiver}{preset}{$id};
|
||||
next if ( !$presetName || $presetName eq "" );
|
||||
|
||||
$presetName =~ s/\s/_/g;
|
||||
|
||||
if ( $id eq ONKYO_AVR_dec2hex($value) ) {
|
||||
$value = $presetName;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = "" if ( $value eq "0" );
|
||||
}
|
||||
|
||||
# tone
|
||||
if ( $cmd =~ /^tone/ ) {
|
||||
if ( $value =~ /^B(..)T(..)$/ ) {
|
||||
my $bass = $1;
|
||||
my $treble = $2;
|
||||
my $bassName = $cmd . "-bass";
|
||||
my $trebleName = $cmd . "-treble";
|
||||
my $prefixBass = "";
|
||||
my $prefixTreble = "";
|
||||
|
||||
# tone-bass
|
||||
$prefixBass = "-" if ( $bass =~ /^\-.*/ );
|
||||
$bass = substr( $bass, 1 ) if ( $bass =~ /^[\+|\-].*/ );
|
||||
$bass = $prefixBass . ONKYO_AVR_hex2dec($bass);
|
||||
readingsBulkUpdate( $hash, $bassName, $bass )
|
||||
if ( ReadingsVal( $name, $bassName, "-" ) ne $bass );
|
||||
|
||||
# tone-treble
|
||||
$prefixTreble = "-" if ( $treble =~ /^\-.*/ );
|
||||
$treble = substr( $treble, 1 )
|
||||
if ( $treble =~ /^[\+|\-].*/ );
|
||||
$treble = $prefixTreble . ONKYO_AVR_hex2dec($treble);
|
||||
readingsBulkUpdate( $hash, $trebleName, $treble )
|
||||
if (
|
||||
ReadingsVal( $name, $trebleName, "-" ) ne $treble );
|
||||
}
|
||||
}
|
||||
|
||||
# all other commands
|
||||
else {
|
||||
readingsBulkUpdate( $hash, $cmd, $value )
|
||||
if ( ReadingsVal( $name, $cmd, "-" ) ne $value
|
||||
|| $cmd =~ /^currentAlbumArt.*/ );
|
||||
}
|
||||
}
|
||||
|
||||
# stateAV
|
||||
my $stateAV = ONKYO_AVR_ZONE_GetStateAV($hash);
|
||||
readingsBulkUpdate( $hash, "stateAV", $stateAV )
|
||||
if ( ReadingsVal( $name, "stateAV", "-" ) ne $stateAV );
|
||||
|
||||
readingsEndUpdate( $hash, 1 );
|
||||
last;
|
||||
}
|
||||
}
|
||||
return @matches if (@matches);
|
||||
return "UNDEFINED ONKYO_AVR_ZONE";
|
||||
}
|
||||
|
||||
###################################
|
||||
sub ONKYO_AVR_ZONE_Get($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $zone = $hash->{ZONE};
|
||||
my $IOhash = $hash->{IODev};
|
||||
my $IOname = $IOhash->{NAME};
|
||||
my $state = ReadingsVal( $name, "power", "off" );
|
||||
my $presence = ReadingsVal( $name, "presence", "absent" );
|
||||
my $commands = ONKYOdb::ONKYO_GetRemotecontrolCommand($zone);
|
||||
my $commands_details = ONKYOdb::ONKYO_GetRemotecontrolCommandDetails($zone);
|
||||
my $return;
|
||||
|
||||
Log3 $name, 5, "ONKYO_AVR_ZONE $name: called function ONKYO_AVR_ZONE_Get()";
|
||||
|
||||
return "Argument is missing" if ( int(@$a) < 1 );
|
||||
|
||||
# readings
|
||||
return $hash->{READINGS}{ @$a[1] }{VAL}
|
||||
if ( defined( $hash->{READINGS}{ @$a[1] } ) );
|
||||
|
||||
return "Device is offline and cannot be controlled at that stage."
|
||||
if ( $presence eq "absent" );
|
||||
|
||||
# statusRequest
|
||||
if ( lc( @$a[1] ) eq "statusrequest" ) {
|
||||
Log3 $name, 3, "ONKYO_AVR_ZONE get $name " . @$a[1];
|
||||
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "power", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "input", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "mute", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "volume", "query" );
|
||||
}
|
||||
|
||||
# remoteControl
|
||||
elsif ( lc( @$a[1] ) eq "remotecontrol" ) {
|
||||
|
||||
# Output help for commands
|
||||
if ( !defined( @$a[2] ) || @$a[2] eq "help" || @$a[2] eq "?" ) {
|
||||
|
||||
my $valid_commands =
|
||||
"Usage: <command> <value>\n\nValid commands in zone$zone:\n\n\n"
|
||||
. "COMMAND\t\t\tDESCRIPTION\n\n";
|
||||
|
||||
# For each valid command
|
||||
foreach my $command ( sort keys %{$commands} ) {
|
||||
my $command_raw = $commands->{$command};
|
||||
|
||||
# add command including description if found
|
||||
if ( defined( $commands_details->{$command_raw}{description} ) )
|
||||
{
|
||||
$valid_commands .=
|
||||
$command
|
||||
. "\t\t\t"
|
||||
. $commands_details->{$command_raw}{description} . "\n";
|
||||
}
|
||||
|
||||
# add command only
|
||||
else {
|
||||
$valid_commands .= $command . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$valid_commands .=
|
||||
"\nTry '<command> help' to find out well known values.\n\n\n";
|
||||
|
||||
$return = $valid_commands;
|
||||
}
|
||||
else {
|
||||
# Reading values for command from HASH table
|
||||
my $values =
|
||||
ONKYOdb::ONKYO_GetRemotecontrolValue( $zone,
|
||||
$commands->{ @$a[2] } );
|
||||
|
||||
@$a[3] = "query"
|
||||
if ( !defined( @$a[3] ) && defined( $values->{query} ) );
|
||||
|
||||
# Output help for values
|
||||
if ( !defined( @$a[3] ) || @$a[3] eq "help" || @$a[3] eq "?" ) {
|
||||
|
||||
# Get all details for command
|
||||
my $command_details =
|
||||
ONKYOdb::ONKYO_GetRemotecontrolCommandDetails( $zone,
|
||||
$commands->{ @$a[2] } );
|
||||
|
||||
my $valid_values =
|
||||
"Usage: "
|
||||
. @$a[2]
|
||||
. " <value>\n\nWell known values:\n\n\n"
|
||||
. "VALUE\t\t\tDESCRIPTION\n\n";
|
||||
|
||||
# For each valid value
|
||||
foreach my $value ( sort keys %{$values} ) {
|
||||
|
||||
# add value including description if found
|
||||
if ( defined( $command_details->{description} ) ) {
|
||||
$valid_values .=
|
||||
$value
|
||||
. "\t\t\t"
|
||||
. $command_details->{description} . "\n";
|
||||
}
|
||||
|
||||
# add value only
|
||||
else {
|
||||
$valid_values .= $value . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$valid_values .= "\n\n\n";
|
||||
|
||||
$return = $valid_values;
|
||||
}
|
||||
|
||||
# normal processing
|
||||
else {
|
||||
Log3 $name, 3,
|
||||
"ONKYO_AVR_ZONE get $name "
|
||||
. @$a[1] . " "
|
||||
. @$a[2] . " "
|
||||
. @$a[3]
|
||||
if ( !@$a[4] || @$a[4] ne "quiet" );
|
||||
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, @$a[2], @$a[3] );
|
||||
$return = "Sent command: " . @$a[2] . " " . @$a[3]
|
||||
if ( !@$a[4] || @$a[4] ne "quiet" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
$return =
|
||||
"Unknown argument " . @$a[1] . ", choose one of statusRequest:noArg";
|
||||
|
||||
# remoteControl
|
||||
$return .= " remoteControl:";
|
||||
foreach my $command ( sort keys %{$commands} ) {
|
||||
$return .= "," . $command;
|
||||
}
|
||||
}
|
||||
|
||||
return $return if ($return);
|
||||
}
|
||||
|
||||
###################################
|
||||
sub ONKYO_AVR_ZONE_Set($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $IOhash = $hash->{IODev};
|
||||
@ -1443,13 +1106,298 @@ sub ONKYO_AVR_ZONE_Set($$$) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
############################################################################################################
|
||||
#
|
||||
# Begin of helper functions
|
||||
#
|
||||
############################################################################################################
|
||||
sub ONKYO_AVR_ZONE_Get($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $zone = $hash->{ZONE};
|
||||
my $IOhash = $hash->{IODev};
|
||||
my $IOname = $IOhash->{NAME};
|
||||
my $state = ReadingsVal( $name, "power", "off" );
|
||||
my $presence = ReadingsVal( $name, "presence", "absent" );
|
||||
my $commands = ONKYOdb::ONKYO_GetRemotecontrolCommand($zone);
|
||||
my $commands_details = ONKYOdb::ONKYO_GetRemotecontrolCommandDetails($zone);
|
||||
my $return;
|
||||
|
||||
###################################
|
||||
Log3 $name, 5, "ONKYO_AVR_ZONE $name: called function ONKYO_AVR_ZONE_Get()";
|
||||
|
||||
return "Argument is missing" if ( int(@$a) < 1 );
|
||||
|
||||
# readings
|
||||
return $hash->{READINGS}{ @$a[1] }{VAL}
|
||||
if ( defined( $hash->{READINGS}{ @$a[1] } ) );
|
||||
|
||||
return "Device is offline and cannot be controlled at that stage."
|
||||
if ( $presence eq "absent" );
|
||||
|
||||
# statusRequest
|
||||
if ( lc( @$a[1] ) eq "statusrequest" ) {
|
||||
Log3 $name, 3, "ONKYO_AVR_ZONE get $name " . @$a[1];
|
||||
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "power", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "input", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "mute", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "volume", "query" );
|
||||
}
|
||||
|
||||
# remoteControl
|
||||
elsif ( lc( @$a[1] ) eq "remotecontrol" ) {
|
||||
|
||||
# Output help for commands
|
||||
if ( !defined( @$a[2] ) || @$a[2] eq "help" || @$a[2] eq "?" ) {
|
||||
|
||||
my $valid_commands =
|
||||
"Usage: <command> <value>\n\nValid commands in zone$zone:\n\n\n"
|
||||
. "COMMAND\t\t\tDESCRIPTION\n\n";
|
||||
|
||||
# For each valid command
|
||||
foreach my $command ( sort keys %{$commands} ) {
|
||||
my $command_raw = $commands->{$command};
|
||||
|
||||
# add command including description if found
|
||||
if ( defined( $commands_details->{$command_raw}{description} ) )
|
||||
{
|
||||
$valid_commands .=
|
||||
$command
|
||||
. "\t\t\t"
|
||||
. $commands_details->{$command_raw}{description} . "\n";
|
||||
}
|
||||
|
||||
# add command only
|
||||
else {
|
||||
$valid_commands .= $command . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$valid_commands .=
|
||||
"\nTry '<command> help' to find out well known values.\n\n\n";
|
||||
|
||||
$return = $valid_commands;
|
||||
}
|
||||
else {
|
||||
# Reading values for command from HASH table
|
||||
my $values =
|
||||
ONKYOdb::ONKYO_GetRemotecontrolValue( $zone,
|
||||
$commands->{ @$a[2] } );
|
||||
|
||||
@$a[3] = "query"
|
||||
if ( !defined( @$a[3] ) && defined( $values->{query} ) );
|
||||
|
||||
# Output help for values
|
||||
if ( !defined( @$a[3] ) || @$a[3] eq "help" || @$a[3] eq "?" ) {
|
||||
|
||||
# Get all details for command
|
||||
my $command_details =
|
||||
ONKYOdb::ONKYO_GetRemotecontrolCommandDetails( $zone,
|
||||
$commands->{ @$a[2] } );
|
||||
|
||||
my $valid_values =
|
||||
"Usage: "
|
||||
. @$a[2]
|
||||
. " <value>\n\nWell known values:\n\n\n"
|
||||
. "VALUE\t\t\tDESCRIPTION\n\n";
|
||||
|
||||
# For each valid value
|
||||
foreach my $value ( sort keys %{$values} ) {
|
||||
|
||||
# add value including description if found
|
||||
if ( defined( $command_details->{description} ) ) {
|
||||
$valid_values .=
|
||||
$value
|
||||
. "\t\t\t"
|
||||
. $command_details->{description} . "\n";
|
||||
}
|
||||
|
||||
# add value only
|
||||
else {
|
||||
$valid_values .= $value . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$valid_values .= "\n\n\n";
|
||||
|
||||
$return = $valid_values;
|
||||
}
|
||||
|
||||
# normal processing
|
||||
else {
|
||||
Log3 $name, 3,
|
||||
"ONKYO_AVR_ZONE get $name "
|
||||
. @$a[1] . " "
|
||||
. @$a[2] . " "
|
||||
. @$a[3]
|
||||
if ( !@$a[4] || @$a[4] ne "quiet" );
|
||||
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, @$a[2], @$a[3] );
|
||||
$return = "Sent command: " . @$a[2] . " " . @$a[3]
|
||||
if ( !@$a[4] || @$a[4] ne "quiet" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
$return =
|
||||
"Unknown argument " . @$a[1] . ", choose one of statusRequest:noArg";
|
||||
|
||||
# remoteControl
|
||||
$return .= " remoteControl:";
|
||||
foreach my $command ( sort keys %{$commands} ) {
|
||||
$return .= "," . $command;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
sub ONKYO_AVR_ZONE_Parse($$) {
|
||||
my ( $IOhash, $msg ) = @_;
|
||||
my @matches;
|
||||
my $IOname = $IOhash->{NAME};
|
||||
my $zone = $msg->{zone} || "";
|
||||
|
||||
delete $msg->{zone} if ( defined( $msg->{zone} ) );
|
||||
|
||||
Log3 $IOname, 5,
|
||||
"ONKYO_AVR $IOname: called function ONKYO_AVR_ZONE_Parse()";
|
||||
|
||||
foreach my $d ( keys %defs ) {
|
||||
my $hash = $defs{$d};
|
||||
my $name = $hash->{NAME};
|
||||
my $state = ReadingsVal( $name, "power", "off" );
|
||||
|
||||
if ( $hash->{TYPE} eq "ONKYO_AVR_ZONE"
|
||||
&& $hash->{IODev} eq $IOhash
|
||||
&& ( $zone eq "" || $hash->{ZONE} eq $zone ) )
|
||||
{
|
||||
push @matches, $d;
|
||||
|
||||
# Update readings
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
foreach my $cmd ( keys %{$msg} ) {
|
||||
my $value = $msg->{$cmd};
|
||||
|
||||
$hash->{INPUT} = $value and next if ( $cmd eq "INPUT_RAW" );
|
||||
$hash->{CHANNEL} = $value and next if ( $cmd eq "CHANNEL_RAW" );
|
||||
|
||||
Log3 $name, 4, "ONKYO_AVR_ZONE $name: rcv $cmd = $value";
|
||||
|
||||
# presence
|
||||
if ( $cmd eq "presence" && $value eq "present" ) {
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "power", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "input", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "mute", "query" );
|
||||
ONKYO_AVR_ZONE_SendCommand( $hash, "volume", "query" );
|
||||
}
|
||||
|
||||
# input
|
||||
elsif ( $cmd eq "input" ) {
|
||||
|
||||
# Input alias handling
|
||||
if (
|
||||
defined(
|
||||
$hash->{helper}{receiver}{input_aliases}{$value}
|
||||
)
|
||||
)
|
||||
{
|
||||
Log3 $name, 4,
|
||||
"ONKYO_AVR_AVR $name: Input aliasing '$value' to '"
|
||||
. $hash->{helper}{receiver}{input_aliases}{$value}
|
||||
. "'";
|
||||
$value =
|
||||
$hash->{helper}{receiver}{input_aliases}{$value};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# power
|
||||
elsif ( $cmd eq "power" ) {
|
||||
readingsBulkUpdate( $hash, "presence", "present" )
|
||||
if ( ReadingsVal( $name, "presence", "-" ) ne "present" );
|
||||
}
|
||||
|
||||
# balance
|
||||
elsif ( $cmd eq "balance" ) {
|
||||
my $prefix = "";
|
||||
$prefix = "-" if ( $value =~ /^\-.*/ );
|
||||
$value = substr( $value, 1 ) if ( $value =~ /^[\+|\-].*/ );
|
||||
|
||||
$value = $prefix . ONKYO_AVR_hex2dec($value);
|
||||
}
|
||||
|
||||
# preset
|
||||
elsif ( $cmd eq "preset" ) {
|
||||
|
||||
if ( defined( $IOhash->{helper}{receiver}{preset} ) ) {
|
||||
|
||||
foreach my $id (
|
||||
sort keys %{ $IOhash->{helper}{receiver}{preset} } )
|
||||
{
|
||||
my $presetName =
|
||||
$IOhash->{helper}{receiver}{preset}{$id};
|
||||
next if ( !$presetName || $presetName eq "" );
|
||||
|
||||
$presetName =~ s/\s/_/g;
|
||||
|
||||
if ( $id eq ONKYO_AVR_dec2hex($value) ) {
|
||||
$value = $presetName;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$value = "" if ( $value eq "0" );
|
||||
}
|
||||
|
||||
# tone
|
||||
if ( $cmd =~ /^tone/ ) {
|
||||
if ( $value =~ /^B(..)T(..)$/ ) {
|
||||
my $bass = $1;
|
||||
my $treble = $2;
|
||||
my $bassName = $cmd . "-bass";
|
||||
my $trebleName = $cmd . "-treble";
|
||||
my $prefixBass = "";
|
||||
my $prefixTreble = "";
|
||||
|
||||
# tone-bass
|
||||
$prefixBass = "-" if ( $bass =~ /^\-.*/ );
|
||||
$bass = substr( $bass, 1 ) if ( $bass =~ /^[\+|\-].*/ );
|
||||
$bass = $prefixBass . ONKYO_AVR_hex2dec($bass);
|
||||
readingsBulkUpdate( $hash, $bassName, $bass )
|
||||
if ( ReadingsVal( $name, $bassName, "-" ) ne $bass );
|
||||
|
||||
# tone-treble
|
||||
$prefixTreble = "-" if ( $treble =~ /^\-.*/ );
|
||||
$treble = substr( $treble, 1 )
|
||||
if ( $treble =~ /^[\+|\-].*/ );
|
||||
$treble = $prefixTreble . ONKYO_AVR_hex2dec($treble);
|
||||
readingsBulkUpdate( $hash, $trebleName, $treble )
|
||||
if (
|
||||
ReadingsVal( $name, $trebleName, "-" ) ne $treble );
|
||||
}
|
||||
}
|
||||
|
||||
# all other commands
|
||||
else {
|
||||
readingsBulkUpdate( $hash, $cmd, $value )
|
||||
if ( ReadingsVal( $name, $cmd, "-" ) ne $value
|
||||
|| $cmd =~ /^currentAlbumArt.*/ );
|
||||
}
|
||||
}
|
||||
|
||||
# stateAV
|
||||
my $stateAV = ONKYO_AVR_ZONE_GetStateAV($hash);
|
||||
readingsBulkUpdate( $hash, "stateAV", $stateAV )
|
||||
if ( ReadingsVal( $name, "stateAV", "-" ) ne $stateAV );
|
||||
|
||||
readingsEndUpdate( $hash, 1 );
|
||||
last;
|
||||
}
|
||||
}
|
||||
return @matches if (@matches);
|
||||
return "UNDEFINED ONKYO_AVR_ZONE";
|
||||
}
|
||||
|
||||
# module Fn ####################################################################
|
||||
sub ONKYO_AVR_ZONE_SendCommand($$$) {
|
||||
my ( $hash, $cmd, $value ) = @_;
|
||||
my $IOhash = $hash->{IODev};
|
||||
@ -1523,7 +1471,6 @@ sub ONKYO_AVR_ZONE_SendCommand($$$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub ONKYO_AVR_ZONE_GetStateAV($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
@ -1,30 +1,5 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# 74_THINKINGCLEANER.pm
|
||||
# An FHEM Perl module for controlling ThinkingCleaner connected
|
||||
# Roomba vacuum cleaning robot.
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
@ -34,15 +9,7 @@ use HttpUtils;
|
||||
use Encode;
|
||||
use Data::Dumper;
|
||||
|
||||
no warnings "all";
|
||||
|
||||
sub THINKINGCLEANER_Set($@);
|
||||
sub THINKINGCLEANER_GetStatus($;$);
|
||||
sub THINKINGCLEANER_Attr($@);
|
||||
sub THINKINGCLEANER_Define($$);
|
||||
sub THINKINGCLEANER_Undefine($$);
|
||||
|
||||
###################################
|
||||
# initialize ##################################################################
|
||||
sub THINKINGCLEANER_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
@ -51,14 +18,14 @@ sub THINKINGCLEANER_Initialize($) {
|
||||
my $webhookFWinstance =
|
||||
join( ",", devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') );
|
||||
|
||||
$hash->{SetFn} = "THINKINGCLEANER_Set";
|
||||
$hash->{DefFn} = "THINKINGCLEANER_Define";
|
||||
$hash->{AttrFn} = "THINKINGCLEANER_Attr";
|
||||
$hash->{UndefFn} = "THINKINGCLEANER_Undefine";
|
||||
$hash->{SetFn} = "THINKINGCLEANER_Set";
|
||||
$hash->{AttrFn} = "THINKINGCLEANER_Attr";
|
||||
$hash->{parseParams} = 1;
|
||||
|
||||
$hash->{AttrList} =
|
||||
"disable:0,1 timeout:1,2,3,4,5 pollInterval:30,45,60,75,90 pollMultiplierWebhook pollMultiplierCleaning model webhookHttpHostname webhookPort webhookFWinstance:$webhookFWinstance restart:noArg "
|
||||
"disable:0,1 disabledForIntervals timeout:1,2,3,4,5 pollInterval:30,45,60,75,90 pollMultiplierWebhook pollMultiplierCleaning model webhookHttpHostname webhookPort webhookFWinstance:$webhookFWinstance restart:noArg "
|
||||
. $readingFnAttributes;
|
||||
|
||||
# 98_powerMap.pm support
|
||||
@ -89,50 +56,82 @@ sub THINKINGCLEANER_Initialize($) {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub THINKINGCLEANER_GetStatus($;$) {
|
||||
my ( $hash, $delay ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
$hash->{INTERVAL_MULTIPLIER} = (
|
||||
ReadingsVal( $name, "state", "off" ) ne "off"
|
||||
&& ReadingsVal( $name, "state", "absent" ) ne "absent"
|
||||
&& ReadingsVal( $name, "state", "standby" ) ne "standby"
|
||||
? AttrVal( $name, "pollMultiplierCleaning", "0.5" )
|
||||
: (
|
||||
$hash->{WEBHOOK_REGISTER} eq "success"
|
||||
? AttrVal( $name, "pollMultiplierWebhook", "2" )
|
||||
: "1"
|
||||
)
|
||||
);
|
||||
|
||||
$hash->{INTERVAL} =
|
||||
AttrVal( $name, "pollInterval", "45" ) * $hash->{INTERVAL_MULTIPLIER};
|
||||
my $interval = (
|
||||
$delay
|
||||
? $delay
|
||||
: $hash->{INTERVAL}
|
||||
);
|
||||
# regular Fn ##################################################################
|
||||
sub THINKINGCLEANER_Define($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $infix = "THINKINGCLEANER";
|
||||
|
||||
Log3 $name, 5,
|
||||
"THINKINGCLEANER $name: called function THINKINGCLEANER_GetStatus()";
|
||||
"THINKINGCLEANER $name: called function THINKINGCLEANER_Define()";
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer( gettimeofday() + $interval,
|
||||
"THINKINGCLEANER_GetStatus", $hash, 0 );
|
||||
eval {
|
||||
require JSON;
|
||||
import JSON qw( decode_json );
|
||||
};
|
||||
return "Please install Perl JSON to use module THINKINGCLEANER"
|
||||
if ($@);
|
||||
|
||||
return
|
||||
if ( $delay || AttrVal( $name, "disable", 0 ) == 1 );
|
||||
if ( int(@$a) < 2 ) {
|
||||
my $msg =
|
||||
"Wrong syntax: define <name> THINKINGCLEANER <ip-or-hostname>";
|
||||
Log3 $name, 4, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
THINKINGCLEANER_SendCommand( $hash, "full_status.json" );
|
||||
$hash->{TYPE} = "THINKINGCLEANER";
|
||||
|
||||
return;
|
||||
my $address = @$a[2];
|
||||
$hash->{DeviceName} = $address;
|
||||
|
||||
# set reverse pointer
|
||||
$modules{THINKINGCLEANER}{defptr}{$name} = \$hash;
|
||||
|
||||
# set default settings on first define
|
||||
if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
|
||||
$attr{$name}{cmdIcon} =
|
||||
'on-max:text_max on-spot:refresh on-delayed:time_timer dock:measure_battery_50 locate:rc_SEARCH';
|
||||
$attr{$name}{devStateIcon} =
|
||||
'on-delayed:rc_STOP@green:off on-max:rc_BLUE@green:off on-spot:rc_GREEN@red:off on.*:rc_GREEN@green:off dock:rc_GREEN@orange:off off:rc_STOP:on standby|remote:rc_YELLOW:on locate:rc_YELLOW .*:rc_RED';
|
||||
$attr{$name}{icon} = 'scene_cleaning';
|
||||
$attr{$name}{webCmd} = 'on-max:on-spot:on-delayed:dock:locate';
|
||||
}
|
||||
|
||||
if ( THINKINGCLEANER_addExtension( $name, "THINKINGCLEANER_CGI", $infix ) )
|
||||
{
|
||||
$hash->{fhem}{infix} = $infix;
|
||||
}
|
||||
|
||||
$hash->{WEBHOOK_REGISTER} = "unregistered";
|
||||
|
||||
# start the status update timer
|
||||
THINKINGCLEANER_GetStatus( $hash, 2 );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub THINKINGCLEANER_Undefine($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
if ( defined( $hash->{fhem}{infix} ) ) {
|
||||
THINKINGCLEANER_removeExtension( $hash->{fhem}{infix} );
|
||||
}
|
||||
|
||||
Log3 $name, 5,
|
||||
"THINKINGCLEANER $name: called function THINKINGCLEANER_Undefine()";
|
||||
|
||||
# Stop the internal GetStatus-Loop and exit
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
# release reverse pointer
|
||||
delete $modules{THINKINGCLEANER}{defptr}{$name};
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_Set($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -842,64 +841,9 @@ sub THINKINGCLEANER_Set($$$) {
|
||||
return $usage;
|
||||
}
|
||||
|
||||
return;
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_Define($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $infix = "THINKINGCLEANER";
|
||||
|
||||
Log3 $name, 5,
|
||||
"THINKINGCLEANER $name: called function THINKINGCLEANER_Define()";
|
||||
|
||||
eval {
|
||||
require JSON;
|
||||
import JSON qw( decode_json );
|
||||
};
|
||||
return "Please install Perl JSON to use module THINKINGCLEANER"
|
||||
if ($@);
|
||||
|
||||
if ( int(@$a) < 2 ) {
|
||||
my $msg =
|
||||
"Wrong syntax: define <name> THINKINGCLEANER <ip-or-hostname>";
|
||||
Log3 $name, 4, $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
$hash->{TYPE} = "THINKINGCLEANER";
|
||||
|
||||
my $address = @$a[2];
|
||||
$hash->{DeviceName} = $address;
|
||||
|
||||
# set reverse pointer
|
||||
$modules{THINKINGCLEANER}{defptr}{$name} = \$hash;
|
||||
|
||||
# set default settings on first define
|
||||
if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
|
||||
$attr{$name}{cmdIcon} =
|
||||
'on-max:text_max on-spot:refresh on-delayed:time_timer dock:measure_battery_50 locate:rc_SEARCH';
|
||||
$attr{$name}{devStateIcon} =
|
||||
'on-delayed:rc_STOP@green:off on-max:rc_BLUE@green:off on-spot:rc_GREEN@red:off on.*:rc_GREEN@green:off dock:rc_GREEN@orange:off off:rc_STOP:on standby|remote:rc_YELLOW:on locate:rc_YELLOW .*:rc_RED';
|
||||
$attr{$name}{icon} = 'scene_cleaning';
|
||||
$attr{$name}{webCmd} = 'on-max:on-spot:on-delayed:dock:locate';
|
||||
}
|
||||
|
||||
if ( THINKINGCLEANER_addExtension( $name, "THINKINGCLEANER_CGI", $infix ) )
|
||||
{
|
||||
$hash->{fhem}{infix} = $infix;
|
||||
}
|
||||
|
||||
$hash->{WEBHOOK_REGISTER} = "unregistered";
|
||||
|
||||
# start the status update timer
|
||||
THINKINGCLEANER_GetStatus( $hash, 2 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_Attr(@) {
|
||||
my ( $cmd, $name, $attrName, $attrVal ) = @_;
|
||||
my $hash = $defs{$name};
|
||||
@ -1004,7 +948,7 @@ sub THINKINGCLEANER_Attr(@) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
# module Fn ####################################################################
|
||||
sub THINKINGCLEANER_addExtension($$$) {
|
||||
my ( $name, $func, $link ) = @_;
|
||||
|
||||
@ -1023,7 +967,6 @@ sub THINKINGCLEANER_addExtension($$$) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_removeExtension($) {
|
||||
my ($link) = @_;
|
||||
|
||||
@ -1034,13 +977,88 @@ sub THINKINGCLEANER_removeExtension($) {
|
||||
delete $data{FWEXT}{$url};
|
||||
}
|
||||
|
||||
############################################################################################################
|
||||
#
|
||||
# Begin of helper functions
|
||||
#
|
||||
############################################################################################################
|
||||
sub THINKINGCLEANER_CGI() {
|
||||
my ($request) = @_;
|
||||
|
||||
# data received
|
||||
if ( defined( $FW_httpheader{UUID} ) ) {
|
||||
if ( defined( $modules{THINKINGCLEANER}{defptr} ) ) {
|
||||
while ( my ( $key, $value ) =
|
||||
each %{ $modules{THINKINGCLEANER}{defptr} } )
|
||||
{
|
||||
|
||||
my $uuid = ReadingsVal( $key, "uuid", undef );
|
||||
next if ( !$uuid || $uuid ne $FW_httpheader{UUID} );
|
||||
|
||||
$defs{$key}{WEBHOOK_COUNTER}++;
|
||||
$defs{$key}{WEBHOOK_LAST} = TimeNow();
|
||||
|
||||
Log3 $key, 4,
|
||||
"THINKINGCLEANER $key: Received webhook for matching UUID at device $key";
|
||||
|
||||
my $delay = undef;
|
||||
|
||||
# we need some delay as to the Robo seems to send webhooks but it's status does
|
||||
# not really reflect the change we'd expect to get here already so give 'em some
|
||||
# more time to think about it...
|
||||
$delay = "2"
|
||||
if ( defined( $defs{$key}{LAST_COMMAND} )
|
||||
&& time() - time_str2num( $defs{$key}{LAST_COMMAND} ) < 3 );
|
||||
|
||||
THINKINGCLEANER_GetStatus( $defs{$key}, $delay );
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return ( undef, undef );
|
||||
}
|
||||
|
||||
# no data received
|
||||
else {
|
||||
Log3 undef, 5, "THINKINGCLEANER: received malformed request\n$request";
|
||||
}
|
||||
|
||||
return ( "text/plain; charset=utf-8", "Call failure: " . $request );
|
||||
}
|
||||
|
||||
sub THINKINGCLEANER_GetStatus($;$) {
|
||||
my ( $hash, $delay ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
$hash->{INTERVAL_MULTIPLIER} = (
|
||||
ReadingsVal( $name, "state", "off" ) ne "off"
|
||||
&& ReadingsVal( $name, "state", "absent" ) ne "absent"
|
||||
&& ReadingsVal( $name, "state", "standby" ) ne "standby"
|
||||
? AttrVal( $name, "pollMultiplierCleaning", "0.5" )
|
||||
: (
|
||||
$hash->{WEBHOOK_REGISTER} eq "success"
|
||||
? AttrVal( $name, "pollMultiplierWebhook", "2" )
|
||||
: "1"
|
||||
)
|
||||
);
|
||||
|
||||
$hash->{INTERVAL} =
|
||||
AttrVal( $name, "pollInterval", "45" ) * $hash->{INTERVAL_MULTIPLIER};
|
||||
my $interval = (
|
||||
$delay
|
||||
? $delay
|
||||
: $hash->{INTERVAL}
|
||||
);
|
||||
|
||||
Log3 $name, 5,
|
||||
"THINKINGCLEANER $name: called function THINKINGCLEANER_GetStatus()";
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer( gettimeofday() + $interval,
|
||||
"THINKINGCLEANER_GetStatus", $hash, 0 );
|
||||
|
||||
return
|
||||
if ( $delay || AttrVal( $name, "disable", 0 ) == 1 );
|
||||
|
||||
THINKINGCLEANER_SendCommand( $hash, "full_status.json" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_SendCommand($$;$$) {
|
||||
my ( $hash, $service, $cmd, $type ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -1166,7 +1184,6 @@ sub THINKINGCLEANER_SendCommand($$;$$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_ReceiveCommand($$$) {
|
||||
my ( $param, $err, $data ) = @_;
|
||||
my $hash = $param->{hash};
|
||||
@ -1728,73 +1745,6 @@ sub THINKINGCLEANER_ReceiveCommand($$$) {
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_CGI() {
|
||||
my ($request) = @_;
|
||||
|
||||
# data received
|
||||
if ( defined( $FW_httpheader{UUID} ) ) {
|
||||
if ( defined( $modules{THINKINGCLEANER}{defptr} ) ) {
|
||||
while ( my ( $key, $value ) =
|
||||
each %{ $modules{THINKINGCLEANER}{defptr} } )
|
||||
{
|
||||
|
||||
my $uuid = ReadingsVal( $key, "uuid", undef );
|
||||
next if ( !$uuid || $uuid ne $FW_httpheader{UUID} );
|
||||
|
||||
$defs{$key}{WEBHOOK_COUNTER}++;
|
||||
$defs{$key}{WEBHOOK_LAST} = TimeNow();
|
||||
|
||||
Log3 $key, 4,
|
||||
"THINKINGCLEANER $key: Received webhook for matching UUID at device $key";
|
||||
|
||||
my $delay = undef;
|
||||
|
||||
# we need some delay as to the Robo seems to send webhooks but it's status does
|
||||
# not really reflect the change we'd expect to get here already so give 'em some
|
||||
# more time to think about it...
|
||||
$delay = "2"
|
||||
if ( defined( $defs{$key}{LAST_COMMAND} )
|
||||
&& time() - time_str2num( $defs{$key}{LAST_COMMAND} ) < 3 );
|
||||
|
||||
THINKINGCLEANER_GetStatus( $defs{$key}, $delay );
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return ( undef, undef );
|
||||
}
|
||||
|
||||
# no data received
|
||||
else {
|
||||
Log3 undef, 5, "THINKINGCLEANER: received malformed request\n$request";
|
||||
}
|
||||
|
||||
return ( "text/plain; charset=utf-8", "Call failure: " . $request );
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_Undefine($$$) {
|
||||
my ( $hash, $a, $h ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
if ( defined( $hash->{fhem}{infix} ) ) {
|
||||
THINKINGCLEANER_removeExtension( $hash->{fhem}{infix} );
|
||||
}
|
||||
|
||||
Log3 $name, 5,
|
||||
"THINKINGCLEANER $name: called function THINKINGCLEANER_Undefine()";
|
||||
|
||||
# Stop the internal GetStatus-Loop and exit
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
# release reverse pointer
|
||||
delete $modules{THINKINGCLEANER}{defptr}{$name};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_time2sec($) {
|
||||
my ($timeString) = @_;
|
||||
my @time = split /:/, $timeString;
|
||||
@ -1802,7 +1752,6 @@ sub THINKINGCLEANER_time2sec($) {
|
||||
return $time[0] * 3600 + $time[1] * 60;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub THINKINGCLEANER_sec2time($) {
|
||||
my ($sec) = @_;
|
||||
|
||||
@ -1818,6 +1767,7 @@ sub THINKINGCLEANER_sec2time($) {
|
||||
|
||||
return "$hours:$minutes:$seconds";
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
@ -1,41 +1,11 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# 97_msgConfig.pm
|
||||
# Global configuration settings for FHEM msg command.
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
|
||||
sub msgConfig_Set($@);
|
||||
sub msgConfig_Get($@);
|
||||
sub msgConfig_Define($$);
|
||||
sub msgConfig_Undefine($$);
|
||||
|
||||
###################################
|
||||
# initialize ##################################################################
|
||||
sub msgConfig_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
@ -173,7 +143,7 @@ sub msgConfig_Initialize($) {
|
||||
}
|
||||
}
|
||||
|
||||
###################################
|
||||
# regular Fn ##################################################################
|
||||
sub msgConfig_Define($$) {
|
||||
|
||||
my ( $hash, $def ) = @_;
|
||||
@ -212,7 +182,6 @@ sub msgConfig_Define($$) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub msgConfig_Undefine($$) {
|
||||
|
||||
my ( $hash, $name ) = @_;
|
||||
@ -223,7 +192,6 @@ sub msgConfig_Undefine($$) {
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub msgConfig_Set($@) {
|
||||
my ( $hash, @a ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -275,7 +243,7 @@ sub msgConfig_Set($@) {
|
||||
$attr{$device}{userattr} .= " msgLocationName"
|
||||
if ( defined( $attr{$device}{userattr} )
|
||||
&& $attr{$device}{userattr} !~
|
||||
/^msgLocationName$|^msgLocationName\s|\smsgLocationName\s|\smsgLocationName$/
|
||||
m/^msgLocationName$|^msgLocationName\s|\smsgLocationName\s|\smsgLocationName$/
|
||||
);
|
||||
$attr{$device}{userattr} = "msgLocationName"
|
||||
if ( !defined( $attr{$device}{userattr} ) );
|
||||
@ -399,9 +367,10 @@ sub msgConfig_Set($@) {
|
||||
return
|
||||
"Unknown argument $what, choose one of cleanReadings addLocation createSwitcherDev:de,en createResidentsDev:de,en";
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
###################################
|
||||
sub msgConfig_Get($@) {
|
||||
my ( $hash, @a ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
@ -578,9 +547,11 @@ sub msgConfig_Get($@) {
|
||||
return
|
||||
"Unknown argument $what, choose one of routeCmd:,audio,light,mail,push,screen,queue";
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
########################################
|
||||
# module Fn ####################################################################
|
||||
sub MSG_FindAttrVal($$$$) {
|
||||
my ( $d, $n, $msgType, $default ) = @_;
|
||||
$msgType = "" unless ($msgType);
|
||||
@ -636,7 +607,6 @@ sub MSG_FindAttrVal($$$$) {
|
||||
);
|
||||
}
|
||||
|
||||
########################################
|
||||
sub msgConfig_FindReadingsVal($$$$) {
|
||||
my ( $d, $n, $msgType, $default ) = @_;
|
||||
$msgType = ucfirst($msgType) if ($msgType);
|
||||
@ -664,7 +634,6 @@ sub msgConfig_FindReadingsVal($$$$) {
|
||||
);
|
||||
}
|
||||
|
||||
########################################
|
||||
sub msgConfig_QueueAdd(@) {
|
||||
my (
|
||||
$msgA, $params, $datetime, $msgID,
|
||||
@ -703,7 +672,6 @@ sub msgConfig_QueueAdd(@) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
########################################
|
||||
sub msgConfig_QueueReleaseMsgId($$) {
|
||||
my ( $recipient, $msgID ) = @_;
|
||||
|
||||
|
@ -1,59 +1,18 @@
|
||||
################################################################################
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# 98_powerMap.pm
|
||||
# Original version by igami
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
################################################################################
|
||||
# TODO
|
||||
# - document how to include powerMap for other module maintainers
|
||||
# (see 50_HP1000)
|
||||
#
|
||||
|
||||
package main;
|
||||
use strict;
|
||||
use warnings;
|
||||
use Data::Dumper;
|
||||
|
||||
use Unit;
|
||||
|
||||
# forward declarations #########################################################
|
||||
sub powerMap_Initialize($);
|
||||
|
||||
sub powerMap_Define($$);
|
||||
sub powerMap_Undefine($$);
|
||||
sub powerMap_Set($@);
|
||||
sub powerMap_Get($@);
|
||||
sub powerMap_Attr(@);
|
||||
sub powerMap_Notify($$);
|
||||
|
||||
sub powerMap_AttrVal($$$$);
|
||||
sub powerMap_load($$;$$);
|
||||
sub powerMap_unload($$);
|
||||
sub powerMap_findPowerMaps($;$);
|
||||
sub powerMap_verifyEventChain($$$);
|
||||
sub powerMap_power($$$;$);
|
||||
sub powerMap_energy($$;$);
|
||||
sub powerMap_update($;$);
|
||||
|
||||
# module hashes ################################################################
|
||||
# module hashes ###############################################################
|
||||
my %powerMap_tmpl = (
|
||||
|
||||
# Format example for devices w/ model support:
|
||||
@ -540,7 +499,7 @@ my %powerMap_tmpl = (
|
||||
},
|
||||
);
|
||||
|
||||
# initialize ###################################################################
|
||||
# initialize ##################################################################
|
||||
sub powerMap_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
my $TYPE = "powerMap";
|
||||
@ -553,7 +512,7 @@ sub powerMap_Initialize($) {
|
||||
$hash->{NotifyFn} = $TYPE . "_Notify";
|
||||
|
||||
$hash->{AttrList} =
|
||||
"disable:1,0 "
|
||||
"disable:1,0 disabledForIntervals do_not_notify:1,0 "
|
||||
. $TYPE
|
||||
. "_gridV:230,110 "
|
||||
. $TYPE
|
||||
@ -568,7 +527,7 @@ sub powerMap_Initialize($) {
|
||||
addToAttrList( $TYPE . ":textField-long" );
|
||||
}
|
||||
|
||||
# regular Fn ###################################################################
|
||||
# regular Fn ##################################################################
|
||||
sub powerMap_Define($$) {
|
||||
my ( $hash, $def ) = @_;
|
||||
my ( $name, $type, $rest ) = split( /[\s]+/, $def, 3 );
|
||||
@ -747,7 +706,7 @@ sub powerMap_Notify($$) {
|
||||
next unless ( defined($event) );
|
||||
|
||||
# initialize or terminate powerMap for each device
|
||||
if ( $event =~ /^(INITIALIZED|SHUTDOWN)$/ ) {
|
||||
if ( $event =~ /^(INITIALIZED|REREADCFG|SHUTDOWN)$/ ) {
|
||||
foreach ( keys %{ powerMap_findPowerMaps( $name, ":PM_$1" ) } )
|
||||
{
|
||||
next
|
||||
@ -1337,6 +1296,8 @@ sub powerMap_verifyEventChain($$$) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub powerMap_power($$$;$);
|
||||
|
||||
sub powerMap_power($$$;$) {
|
||||
my ( $name, $dev, $event, $loop ) = @_;
|
||||
my $hash = $defs{$name};
|
||||
@ -1579,7 +1540,7 @@ sub powerMap_update($;$) {
|
||||
|
||||
1;
|
||||
|
||||
# commandref ###################################################################
|
||||
# commandref ##################################################################
|
||||
|
||||
=pod
|
||||
=item helper
|
||||
|
@ -1,34 +1,9 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# ONKYOdb.pm
|
||||
# ONKYO command database for ONKYO AVR module to split DB from code
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
sub ONKYOdb_Initialize() {
|
||||
}
|
||||
package main;
|
||||
sub ONKYOdb_Initialize() { }
|
||||
|
||||
package ONKYOdb;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
|
@ -541,10 +541,10 @@ return;;\
|
||||
Log3 $NAME, 3,
|
||||
"RESIDENTStk $NAME: "
|
||||
. "new notify macro device $macroRNameGotosleep created";
|
||||
fhem
|
||||
"define $macroRNameGotosleep notify $macroRNameGotosleep $templateGotosleep";
|
||||
fhem
|
||||
"attr $macroRNameGotosleep comment Auto-created by RESIDENTS Toolkit: FHEM commands to run when all residents are gettin' ready for bed";
|
||||
fhem "define $macroRNameGotosleep "
|
||||
. "notify $macroRNameGotosleep $templateGotosleep";
|
||||
fhem "attr $macroRNameGotosleep "
|
||||
. "comment Auto-created by RESIDENTS Toolkit: FHEM commands to run when all residents are gettin' ready for bed";
|
||||
fhem "attr $macroRNameGotosleep room $room"
|
||||
if ($room);
|
||||
}
|
||||
@ -2061,15 +2061,19 @@ sub RESIDENTStk_RG_Attr(@) {
|
||||
|
||||
if ( $lang eq "DE" ) {
|
||||
$attr{$name}{devStateIcon} =
|
||||
'.*zuhause:user_available:absent .*anwesend:user_available:absent .*abwesend:user_away:home .*verreist:user_ext_away:home .*bettfertig:scene_toilet:asleep .*schlaeft:scene_sleeping:awoken .*schläft:scene_sleeping:awoken .*aufgestanden:scene_sleeping_alternat:home .*:user_unknown:home';
|
||||
'.*zuhause:user_available:absent '
|
||||
. '.*anwesend:user_available:absent .*abwesend:user_away:home .*verreist:user_ext_away:home .*bettfertig:scene_toilet:asleep .*schlaeft:scene_sleeping:awoken .*schläft:scene_sleeping:awoken .*aufgestanden:scene_sleeping_alternat:home .*:user_unknown:home';
|
||||
$attr{$name}{eventMap} =
|
||||
"home:zuhause absent:abwesend gone:verreist gotosleep:bettfertig asleep:schläft awoken:aufgestanden";
|
||||
"home:zuhause absent:abwesend gone:verreist "
|
||||
. "gotosleep:bettfertig asleep:schläft awoken:aufgestanden";
|
||||
$attr{$name}{widgetOverride} =
|
||||
"state:zuhause,bettfertig,schläft,aufgestanden,abwesend,verreist";
|
||||
"state:zuhause,bettfertig,schläft,"
|
||||
. "aufgestanden,abwesend,verreist";
|
||||
}
|
||||
elsif ( $lang eq "EN" ) {
|
||||
$attr{$name}{devStateIcon} =
|
||||
'.*home:user_available:absent .*absent:user_away:home .*gone:user_ext_away:home .*gotosleep:scene_toilet:asleep .*asleep:scene_sleeping:awoken .*awoken:scene_sleeping_alternat:home .*:user_unknown:home';
|
||||
'.*home:user_available:absent .*absent:user_away:home '
|
||||
. '.*gone:user_ext_away:home .*gotosleep:scene_toilet:asleep .*asleep:scene_sleeping:awoken .*awoken:scene_sleeping_alternat:home .*:user_unknown:home';
|
||||
delete $attr{$name}{eventMap}
|
||||
if ( defined( $attr{$name}{eventMap} ) );
|
||||
delete $attr{$name}{widgetOverride}
|
||||
|
@ -1,38 +1,9 @@
|
||||
###############################################################################
|
||||
# $Id$
|
||||
##############################################################################
|
||||
#
|
||||
# msgSchema.pm
|
||||
# Schema database for FHEM modules and their messaging options.
|
||||
# These commands are being used as default setting for FHEM command 'msg'
|
||||
# unless there is an explicit msgCmd* attribute.
|
||||
#
|
||||
# FHEM module authors may request to extend this file
|
||||
#
|
||||
# Copyright by Julian Pawlowski
|
||||
# e-mail: julian.pawlowski at gmail.com
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
sub msgSchema_Initialize() {
|
||||
}
|
||||
package main;
|
||||
sub msgSchema_Initialize() { }
|
||||
|
||||
package msgSchema;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user