mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
1a1632ef26
git-svn-id: https://svn.fhem.de/fhem/trunk@26846 2b470e98-0d58-463d-a4d8-8e2adae1ed80
3308 lines
165 KiB
Perl
Executable File
3308 lines
165 KiB
Perl
Executable File
# $Id$
|
|
##############################################################################
|
|
#
|
|
# 71_YAMAHA_AVR.pm
|
|
# An FHEM Perl module for controlling Yamaha AV-Receivers
|
|
# via network connection. As the interface is standardized
|
|
# within all Yamaha AV-Receivers, this module should work
|
|
# with any receiver which has an ethernet or wlan connection.
|
|
#
|
|
# Copyright by Markus Bloch
|
|
#
|
|
# 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 FHEM::YAMAHA_AVR;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Time::HiRes qw(gettimeofday sleep);
|
|
use Encode qw(decode encode);
|
|
use HttpUtils;
|
|
use Carp qw(carp);
|
|
use GPUtils qw(GP_Import);
|
|
|
|
use List::Util qw(max min);
|
|
use Scalar::Util qw(looks_like_number);
|
|
#use FHEM::Meta;
|
|
|
|
sub ::YAMAHA_AVR_Initialize { goto &Initialize }
|
|
|
|
BEGIN {
|
|
|
|
GP_Import( qw(
|
|
readingsSingleUpdate
|
|
readingsBeginUpdate
|
|
readingsBulkUpdate
|
|
readingsBulkUpdateIfChanged
|
|
readingsEndUpdate
|
|
Log3
|
|
modules attr defs
|
|
init_done
|
|
InternalTimer
|
|
RemoveInternalTimer
|
|
readingFnAttributes
|
|
IsDisabled
|
|
AttrVal
|
|
InternalVal
|
|
ReadingsVal
|
|
ReadingsNum
|
|
HttpUtils_NonblockingGet
|
|
trim
|
|
) )
|
|
};
|
|
|
|
###################################
|
|
sub
|
|
Initialize
|
|
{
|
|
my $hash = shift;
|
|
|
|
$hash->{GetFn} = \&Get;
|
|
$hash->{SetFn} = \&Set;
|
|
$hash->{DefFn} = \&Define;
|
|
$hash->{AttrFn} = \&Attr;
|
|
$hash->{UndefFn} = \&Undefine;
|
|
|
|
$hash->{AttrList} = 'do_not_notify:0,1 '.
|
|
'disable:0,1 '.
|
|
'disabledForIntervals '.
|
|
'requestTimeout:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 '.
|
|
'model '.
|
|
'volumeSteps:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 '.
|
|
'volumeMax '.
|
|
'volumeSmoothChange:0,1 '.
|
|
'volumeSmoothSteps:1,2,3,4,5,6,7,8,9,10 '.
|
|
$readingFnAttributes;
|
|
|
|
$hash->{AttrRenameMap} = { 'request-timeout' => 'requestTimeout',
|
|
'volume-smooth-change' => 'volumeSmoothChange',
|
|
'volume-smooth-steps' => 'volumeSmoothSteps'
|
|
};
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
sub Define {
|
|
my $hash = shift // return;
|
|
my $def = shift // return;
|
|
my @arr = split m{\s+}xms, $def;
|
|
my $name = shift @arr;
|
|
|
|
if(@arr < 2)
|
|
{
|
|
my $msg = 'wrong syntax: define <name> YAMAHA_AVR <ip-or-hostname> [<zone>] [<ON-statusinterval>] [<OFF-statusinterval>] ';
|
|
Log3($name, 2, $msg);
|
|
return $msg;
|
|
}
|
|
|
|
my $address = $arr[1];
|
|
|
|
$hash->{helper}{ADDRESS} = $address;
|
|
|
|
# if a zone was given, use it, otherwise use the mainzone
|
|
$hash->{helper}{SELECTED_ZONE} = $arr[2] // 'mainzone';
|
|
|
|
# if an update interval was given which is greater than zero, use it.
|
|
if ( defined $arr[3] && $arr[3] > 0 )
|
|
{
|
|
$hash->{helper}{OFF_INTERVAL} = $arr[3];
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{OFF_INTERVAL} = 30;
|
|
}
|
|
|
|
if ( defined $arr[4] && $arr[4] > 0 )
|
|
{
|
|
$hash->{helper}{ON_INTERVAL} = $arr[4];
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL};
|
|
}
|
|
|
|
$hash->{helper}{CMD_QUEUE} = [];
|
|
delete $hash->{helper}{'.HTTP_CONNECTION'} if exists $hash->{helper}{'.HTTP_CONNECTION'};
|
|
|
|
# In case of a redefine, check the zone parameter if the specified zone exist, otherwise use the main zone
|
|
if ( defined $hash->{helper}{ZONES} && length $hash->{helper}{ZONES} > 0 )
|
|
{
|
|
if ( defined YAMAHA_AVR_getParamName($hash, lc $hash->{helper}{SELECTED_ZONE}, $hash->{helper}{ZONES}) )
|
|
{
|
|
$hash->{ACTIVE_ZONE} = lc $hash->{helper}{SELECTED_ZONE};
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 2, "YAMAHA_AVR ($name) - selected zone >>".$hash->{helper}{SELECTED_ZONE}."<< is not available on device ".$hash->{NAME}.". Using Main Zone instead";
|
|
$hash->{ACTIVE_ZONE} = "mainzone";
|
|
}
|
|
YAMAHA_AVR_getInputs($hash);
|
|
}
|
|
|
|
unless( exists $hash->{helper}{AVAILABLE} and $hash->{helper}{AVAILABLE} == 0 )
|
|
{
|
|
$hash->{helper}{AVAILABLE} = 1;
|
|
readingsSingleUpdate($hash, 'presence', 'present', 1);
|
|
}
|
|
|
|
# start the status update timer
|
|
YAMAHA_AVR_ResetTimer($hash,1);
|
|
|
|
return;
|
|
}
|
|
|
|
###################################
|
|
sub
|
|
YAMAHA_AVR_GetStatus #($;$)
|
|
{
|
|
my $hash = shift // return;
|
|
my $local = shift // 0;
|
|
my $name = $hash->{NAME};
|
|
my $power;
|
|
|
|
return '' if !defined $hash->{helper}{ADDRESS} || !defined $hash->{helper}{OFF_INTERVAL} || !defined $hash->{helper}{ON_INTERVAL};
|
|
|
|
my $device = $hash->{helper}{ADDRESS};
|
|
|
|
# get the model informations and available zones if no informations are available
|
|
if ( !defined $hash->{ACTIVE_ZONE} || !defined $hash->{helper}{ZONES} || !defined$hash->{MODEL} || !defined $hash->{FIRMWARE} )
|
|
{
|
|
YAMAHA_AVR_getModel($hash);
|
|
}
|
|
|
|
# get all available inputs and scenes if nothing is available
|
|
if( !defined($hash->{helper}{INPUTS}) || length $hash->{helper}{INPUTS} == 0 )
|
|
{
|
|
YAMAHA_AVR_getInputs($hash);
|
|
}
|
|
|
|
my $zone = YAMAHA_AVR_getParamName($hash, $hash->{ACTIVE_ZONE}, $hash->{helper}{ZONES});
|
|
|
|
if ( !defined $zone )
|
|
{
|
|
YAMAHA_AVR_ResetTimer($hash) if $local != 1;
|
|
return 'No Zone available';
|
|
}
|
|
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Basic_Status>GetParam</Basic_Status></$zone></YAMAHA_AV>", "statusRequest", "basicStatus");
|
|
|
|
if ( $hash->{ACTIVE_ZONE} eq 'mainzone' && ( !exists $hash->{helper}{SUPPORT_PARTY_MODE} || $hash->{helper}{SUPPORT_PARTY_MODE} ) )
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Party_Mode><Mode>GetParam</Mode></Party_Mode></System></YAMAHA_AV>", "statusRequest", "partyModeStatus", {options => {can_fail => 1}});
|
|
}
|
|
elsif ( $hash->{ACTIVE_ZONE} ne 'mainzone' && ( !exists $hash->{helper}{SUPPORT_PARTY_MODE} || $hash->{helper}{SUPPORT_PARTY_MODE} ) )
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Party_Mode><Target_Zone>GetParam</Target_Zone></Party_Mode></System></YAMAHA_AV>", "statusRequest", "partyModeZones", {options => {can_fail => 1}});
|
|
}
|
|
|
|
if ( $hash->{ACTIVE_ZONE} eq 'mainzone' && ( !exists $hash->{helper}{SUPPORT_SURROUND_DECODER} || $hash->{helper}{SUPPORT_SURROUND_DECODER} ) )
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Surround><Sound_Program_Param><SUR_DECODE>GetParam</SUR_DECODE></Sound_Program_Param></Surround></$zone></YAMAHA_AV>", "statusRequest", "surroundDecoder", {options => {can_fail => 1}});
|
|
}
|
|
|
|
if ( $hash->{ACTIVE_ZONE} eq 'mainzone' && ( !exists $hash->{helper}{SUPPORT_DISPLAY_BRIGHTNESS} || $hash->{helper}{SUPPORT_DISPLAY_BRIGHTNESS}) )
|
|
{
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Display><FL>GetParam</FL></Display></System></YAMAHA_AV>", "statusRequest", "displayBrightness", {options => {can_fail => 1}});
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Display><FL>GetParam</FL></Display></Misc></System></YAMAHA_AV>", "statusRequest", "displayBrightness", {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
|
|
if ( !exists $hash->{helper}{SUPPORT_TONE_STATUS} || ( exists $hash->{helper}{SUPPORT_TONE_STATUS} && exists $hash->{MODEL} && $hash->{helper}{SUPPORT_TONE_STATUS}))
|
|
{
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
if ( $zone eq 'Main_Zone' )
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Tone><Speaker><Bass>GetParam</Bass></Speaker></Tone></$zone></YAMAHA_AV>", "statusRequest", "toneStatus", {options => {can_fail => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Tone><Speaker><Treble>GetParam</Treble></Speaker></Tone></$zone></YAMAHA_AV>", "statusRequest", "toneStatus", {options => {can_fail => 1}});
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Tone><Bass>GetParam</Bass></Tone></$zone></YAMAHA_AV>", "statusRequest", "toneStatus", {options => {can_fail => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Tone><Treble>GetParam</Treble></Tone></$zone></YAMAHA_AV>", "statusRequest", "toneStatus", {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Sound_Video><Tone><Bass>GetParam</Bass></Tone></Sound_Video></$zone></YAMAHA_AV>", "statusRequest", "toneStatus", {options => {can_fail => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Sound_Video><Tone><Treble>GetParam</Treble></Tone></Sound_Video></$zone></YAMAHA_AV>", "statusRequest", "toneStatus", {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
|
|
# check for FW update
|
|
if ( defined $hash->{MODEL} )
|
|
{
|
|
if($hash->{MODEL} =~ /^RX-(?:A\d{1,2}10|V\d{1,2}71)$/) # RX-Vx71 / RX-Ax10 have different firmware status request
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Update><Status>GetParam</Status></Update></Network></Misc></System></YAMAHA_AV>", "statusRequest", "fwUpdate", {options => {can_fail => 1}});
|
|
}
|
|
elsif($hash->{MODEL} =~ /^RX-(?:A\d{1,2}20|V\d{1,2}73)$/) # RX-Vx73 / RX-Ax20 have different firmware status request
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Update><YAMAHA_Network_Site><Status>GetParam</Status></YAMAHA_Network_Site></Update></Misc></System></YAMAHA_AV>", "statusRequest", "fwUpdate", {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
|
|
# check hdmi output state, if supported
|
|
if ( $hash->{ACTIVE_ZONE} eq 'mainzone' && $hash->{helper}{SUPPORT_HDMI_OUT} )
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Sound_Video><HDMI><Output><OUT_1>GetParam</OUT_1></Output></HDMI></Sound_Video></System></YAMAHA_AV>", "statusRequest", "hdmiOut1", {options => {can_fail => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Sound_Video><HDMI><Output><OUT_2>GetParam</OUT_2></Output></HDMI></Sound_Video></System></YAMAHA_AV>", "statusRequest", "hdmiOut2", {options => {can_fail => 1}});
|
|
}
|
|
|
|
YAMAHA_AVR_ResetTimer($hash) if $local != 1;
|
|
|
|
return;
|
|
}
|
|
|
|
###################################
|
|
sub Get {
|
|
my ($hash, @arr) = @_;
|
|
|
|
return 'argument is missing' if @arr != 2;
|
|
|
|
my $what = $arr[1];
|
|
|
|
return ReadingsVal($hash->{NAME}, $what, '') if defined ReadingsVal($hash->{NAME}, $what, undef);
|
|
|
|
my $return = "unknown argument $what, choose one of";
|
|
|
|
for my $reading (keys %{$hash->{READINGS}})
|
|
{
|
|
$return .= " $reading:noArg";
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
|
|
###################################
|
|
sub Set {
|
|
my ($hash, @a) = @_;
|
|
|
|
my $name = $hash->{NAME};
|
|
my $address = $hash->{helper}{ADDRESS};
|
|
|
|
# get the model informations and available zones if no informations are available
|
|
if( !defined $hash->{ACTIVE_ZONE} || !defined $hash->{helper}{ZONES} )
|
|
{
|
|
YAMAHA_AVR_getModel($hash);
|
|
}
|
|
|
|
# get all available inputs if nothing is available
|
|
YAMAHA_AVR_getInputs($hash) if !defined $hash->{helper}{INPUTS} || !length $hash->{helper}{INPUTS};
|
|
|
|
my $zone = YAMAHA_AVR_getParamName($hash, $hash->{ACTIVE_ZONE}, $hash->{helper}{ZONES});
|
|
if ( !defined $zone && $a[1] ne '?' ) {
|
|
Log3( $name, 3, "YAMAHA_AVR ($name) - could not determine addressed zone!");
|
|
return 'could not determine addressed zone!';
|
|
}
|
|
|
|
my $inputs_piped = defined $hash->{helper}{INPUTS} ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{INPUTS}), 0) : '' ;
|
|
my $inputs_comma = defined $hash->{helper}{INPUTS} ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{INPUTS}), 1) : '' ;
|
|
|
|
my $scenes_piped = defined $hash->{helper}{SCENES} ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{SCENES}), 0) : '' ;
|
|
my $scenes_comma = defined $hash->{helper}{SCENES} ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{SCENES}), 1) : '' ;
|
|
|
|
my $dsp_modes_piped = defined $hash->{helper}{DSP_MODES} ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{DSP_MODES}), 0) : '' ;
|
|
my $dsp_modes_comma = defined $hash->{helper}{DSP_MODES} ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{DSP_MODES}), 1) : '' ;
|
|
|
|
my $decoders_piped = defined($hash->{helper}{SURROUND_DECODERS}) ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{SURROUND_DECODERS}), 0) : '' ;
|
|
my $decoders_comma = defined($hash->{helper}{SURROUND_DECODERS}) ? YAMAHA_AVR_Param2Fhem(lc($hash->{helper}{SURROUND_DECODERS}), 1) : '' ;
|
|
|
|
my $what = $a[1] // return 'No Argument given';
|
|
my $usage = "Unknown argument $what, choose one of ". "on:noArg ".
|
|
"off:noArg ".
|
|
"volumeStraight:slider,-80,1,16 ".
|
|
"volume:slider,0,1,100 ".
|
|
(defined(ReadingsVal($name, "volume", undef)) ? "volumeUp volumeDown " : "").
|
|
(exists($hash->{helper}{INPUTS}) ? "input:".$inputs_comma." " : "").
|
|
"mute:on,off,toggle ".
|
|
"remoteControl:setup,up,down,left,right,return,option,display,tunerPresetUp,tunerPresetDown,enter ".
|
|
(exists($hash->{helper}{SCENES}) ? "scene:".$scenes_comma." " : "").
|
|
((exists($hash->{ACTIVE_ZONE}) and $hash->{ACTIVE_ZONE} eq "mainzone") ?
|
|
"straight:on,off 3dCinemaDsp:off,auto adaptiveDrc:off,auto ".
|
|
(exists($hash->{helper}{DIRECT_TAG}) ? "direct:on,off " : "").
|
|
(exists($hash->{helper}{SURROUND_DECODERS}) ? "surroundDecoder:".$decoders_comma." " : "").
|
|
($hash->{helper}{SUPPORT_DISPLAY_BRIGHTNESS} ? "displayBrightness:slider,-4,1,0 " : "").
|
|
(exists($hash->{helper}{DSP_MODES}) ? "dsp:".$dsp_modes_comma." " : "").
|
|
"enhancer:on,off ".
|
|
($hash->{helper}{SUPPORT_HDMI_OUT} ? "hdmiOut1:on,off hdmiOut2:on,off " : "")
|
|
:"").
|
|
(exists($hash->{helper}{CURRENT_INPUT_TAG}) ?
|
|
"navigateListMenu play:noArg pause:noArg stop:noArg skip:reverse,forward ".
|
|
"preset:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40 ".
|
|
"presetUp:noArg presetDown:noArg ".
|
|
(($hash->{helper}{SUPPORT_SHUFFLE_REPEAT}) ? "shuffle:on,off repeat:off,one,all " : "")
|
|
:"").
|
|
"sleep:off,30min,60min,90min,120min,last ".
|
|
(($hash->{helper}{SUPPORT_TONE_STATUS} and exists($hash->{ACTIVE_ZONE}) and $hash->{ACTIVE_ZONE} eq "mainzone") ? "bass:slider,-6,0.5,6 treble:slider,-6,0.5,6 " : "").
|
|
(($hash->{helper}{SUPPORT_TONE_STATUS} and exists($hash->{ACTIVE_ZONE}) and ($hash->{ACTIVE_ZONE} ne "mainzone") and _isModel_DSP($hash)) ? "bass:slider,-10,1,10 treble:slider,-10,1,10 " : "").
|
|
(($hash->{helper}{SUPPORT_TONE_STATUS} and exists($hash->{ACTIVE_ZONE}) and ($hash->{ACTIVE_ZONE} ne "mainzone") and not _isModel_DSP($hash)) ? "bass:slider,-10,2,10 treble:slider,-10,2,10 " : "").
|
|
($hash->{helper}{SUPPORT_PARTY_MODE} ? "partyMode:on,off " : "").
|
|
($hash->{helper}{SUPPORT_EXTRA_BASS} ? "extraBass:off,auto " : "").
|
|
($hash->{helper}{SUPPORT_YPAO_VOLUME} ? "ypaoVolume:off,auto " : "").
|
|
($hash->{helper}{SUPPORT_DAB} ? "tunerFrequencyBand:FM,DAB " : "").
|
|
"tunerFrequency ".
|
|
"displayBrightness:slider,-4,1,0 ".
|
|
"statusRequest:noArg";
|
|
return $usage if $what eq '?';
|
|
|
|
# number of seconds to wait after on/off was executed (DSP based: 3 sec, other models: 2 sec)
|
|
my $powerCmdDelay = _isModel_DSP($hash) ? 3 : 2;
|
|
|
|
Log3( $name, 5, "YAMAHA_AVR ($name) - set ".join(" ", @a) ) if _Log3Demand($hash,5);
|
|
|
|
if($what eq 'on')
|
|
{
|
|
return YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Power>On</Power></Power_Control></$zone></YAMAHA_AV>" ,$what, undef, {options => {wait_after_response => $powerCmdDelay}});
|
|
}
|
|
if($what eq 'off')
|
|
{
|
|
return YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Power>Standby</Power></Power_Control></$zone></YAMAHA_AV>", $what, undef, {options => {wait_after_response => $powerCmdDelay}});
|
|
}
|
|
if($what eq "input")
|
|
{
|
|
if(defined($a[2]))
|
|
{
|
|
if(not $inputs_piped eq "")
|
|
{
|
|
if($a[2] =~ /^($inputs_piped)$/)
|
|
{
|
|
my $command = YAMAHA_AVR_getParamName($hash, $a[2], $hash->{helper}{INPUTS});
|
|
if(defined($command) and length($command) > 0)
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Input><Input_Sel>".$command."</Input_Sel></Input></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
return YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Basic_Status>GetParam</Basic_Status></$zone></YAMAHA_AV>", "statusRequest", "basicStatus", {options => {no_playinfo => 1}});
|
|
}
|
|
else
|
|
{
|
|
return "invalid input: ".$a[2];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "No inputs are avaible. Please try an statusUpdate.";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (($inputs_piped eq "") ? "No inputs are available. Please try an statusUpdate." : "No input parameter was given");
|
|
}
|
|
}
|
|
if($what eq "scene")
|
|
{
|
|
if(defined($a[2]))
|
|
{
|
|
|
|
if(not $scenes_piped eq "")
|
|
{
|
|
if($a[2] =~ /^($scenes_piped)$/)
|
|
{
|
|
my $command = YAMAHA_AVR_getParamName($hash, $a[2], $hash->{helper}{SCENES});
|
|
|
|
if(defined($command) and length($command) > 0)
|
|
{
|
|
return YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Scene><Scene_Sel>".$command."</Scene_Sel></Scene></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return "invalid input: ".$a[2];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "No scenes are avaible. Please try an statusUpdate.";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (($scenes_piped eq "") ? "No scenes are available. Please try an statusUpdate." : "No scene parameter was given");
|
|
}
|
|
}
|
|
elsif($what eq "mute" and defined($a[2]))
|
|
{
|
|
|
|
# Depending on the status response, use the short or long Volume command
|
|
my $volume_cmd = (_isModel_DSP($hash) ? "Vol" : "Volume");
|
|
|
|
if( $a[2] eq "on" or ($a[2] eq "toggle" and ReadingsVal($name, "mute", "off") eq "off"))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Mute>On</Mute></$volume_cmd></$zone></YAMAHA_AV>", $what, "on");
|
|
}
|
|
elsif($a[2] eq "off" or ($a[2] eq "toggle" and ReadingsVal($name, "mute", "off") eq "on"))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Mute>Off</Mute></$volume_cmd></$zone></YAMAHA_AV>", $what, "off");
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
|
|
}
|
|
elsif ( $what =~ m{\AvolumeStraight|volume|volumeUp|volumeDown\z}x )
|
|
{
|
|
return 'volume command requires an additional numeric parameter' if
|
|
!defined $a[2] && $what !~ m{\AvolumeUp|volumeDown\z}x || defined $a[2] && !looks_like_number($a[2]); #non-numeric second parameter is faulty also with up/down commands!
|
|
|
|
my $target_volume;
|
|
|
|
if ( $what eq 'volumeStraight' ) {
|
|
$target_volume = $a[2];
|
|
} else {
|
|
my $act_vol = ReadingsNum($name, 'volume', 0);
|
|
if ( $a[2] =~ m{\A[+-].*} ) {
|
|
$target_volume = $act_vol + $a[2];
|
|
} else {
|
|
my $change = $a[2] // AttrVal($hash->{NAME}, 'volumeSteps',5);
|
|
$target_volume =
|
|
$what eq 'volumeDown' ? $act_vol - $change :
|
|
$what eq 'volumeUp' ? $act_vol + $change :
|
|
$a[2];
|
|
}
|
|
$target_volume = YAMAHA_AVR_volume_rel2abs($target_volume);
|
|
}
|
|
|
|
return 'error calculating target volume' if !defined $target_volume;
|
|
|
|
$target_volume = min($target_volume, YAMAHA_AVR_volume_rel2abs(AttrVal($name, 'volumeMax','100')));
|
|
|
|
# if lower than minimum (-80.5) or higher than max (16.5) set target volume to the corresponding boundary
|
|
|
|
$target_volume = min(max(-80.5,$target_volume),16.5);
|
|
# ensure $target_volume mod 0.5 == 0
|
|
$target_volume = int($target_volume / 0.5) * 0.5;
|
|
|
|
Log3($name, 4, "YAMAHA_AVR ($name) - new target volume: $target_volume") if _Log3Demand($hash, 4);
|
|
|
|
# DSP based models use "Vol" instead of "Volume"
|
|
my $volume_cmd = (_isModel_DSP($hash) ? 'Vol' : 'Volume');
|
|
|
|
if(AttrVal($name, 'volumeSmoothChange', '1') eq '1')
|
|
{
|
|
my $steps = AttrVal($name, 'volumeSmoothSteps', 5);
|
|
my $diff = int(($target_volume - ReadingsVal($name, 'volumeStraight', $target_volume)) / $steps / 0.5) * 0.5;
|
|
my $current_volume = ReadingsVal($name, 'volumeStraight', undef);
|
|
|
|
if ( _Log3Demand($hash, 4) ) {
|
|
my $difftext = $diff > 0 ? qq(+$diff) : $diff;
|
|
Log3($name, 4, "YAMAHA_AVR ($name) - use smooth volume change (with $steps steps of $difftext volume change to reach $target_volume)") ;
|
|
}
|
|
|
|
# Only if a volume reading exists and smoohing is really needed (step difference is not zero)
|
|
if( defined $current_volume && $diff != 0 && !defined $a[3] || $a[3] ne 'direct' )
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - set volume to ".($current_volume + $diff)." dB (target is $target_volume dB)";
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Lvl><Val>".(($current_volume + $diff)*10)."</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></$volume_cmd></$zone></YAMAHA_AV>", "volume", ($current_volume + $diff), {options => {volume_diff => $diff, volume_target => $target_volume}});
|
|
}
|
|
else
|
|
{
|
|
# Set the desired volume
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - set volume to ".$target_volume." dB";
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Lvl><Val>".($target_volume*10)."</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></$volume_cmd></$zone></YAMAHA_AV>", "volume", $target_volume, {options => {volume_diff => $diff, volume_target => $target_volume}});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# Set the desired volume
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - set volume to ".$target_volume." dB";
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Lvl><Val>".($target_volume*10)."</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></$volume_cmd></$zone></YAMAHA_AV>", "volume", $target_volume, {options => {volume_diff => 0, volume_target => $target_volume}});
|
|
}
|
|
|
|
}
|
|
elsif($what eq "bass" and defined($a[2]))
|
|
{
|
|
my $bassVal = $a[2];
|
|
if((exists($hash->{ACTIVE_ZONE})) && ($hash->{ACTIVE_ZONE} eq "mainzone"))
|
|
{
|
|
$bassVal = int($a[2]) if not (($a[2] =~ /^\d$/ ) || ($a[2] =~ /\.5/) || ($a[2] =~ /\.0/));
|
|
$bassVal = -6 if($bassVal < -6);
|
|
$bassVal = 6 if($bassVal > 6);
|
|
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Tone><Speaker><Bass><Cross_Over><Val>" . ReadingsVal($name,"bassCrossover","125") . "</Val><Exp>0</Exp><Unit>Hz</Unit></Cross_Over><Lvl><Val>" . $bassVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Bass></Speaker></Tone></$zone></YAMAHA_AV>", $what, $bassVal);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Tone><Bass><Val>" . $bassVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Bass></Tone></Sound_Video></$zone></YAMAHA_AV>", $what, $bassVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
$bassVal = max(-10,min(int($a[2]),10));
|
|
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Tone><Bass><Val>" . $bassVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Bass></Tone></$zone></YAMAHA_AV>", $what, $bassVal);
|
|
}
|
|
else
|
|
{
|
|
# step range is 2 dB for non DSP based models. add/subtract 1 if modulus 2 != 0
|
|
$bassVal-- if(($bassVal % 2 != 0) && ($bassVal > 0));
|
|
$bassVal++ if(($bassVal % 2 != 0) && ($bassVal < 0));
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Tone><Bass><Val>" . $bassVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Bass></Tone></Sound_Video></$zone></YAMAHA_AV>", $what, $bassVal);
|
|
}
|
|
}
|
|
}
|
|
elsif($what eq "treble" and defined($a[2]))
|
|
{
|
|
my $trebleVal = $a[2];
|
|
if((exists($hash->{ACTIVE_ZONE})) && ($hash->{ACTIVE_ZONE} eq "mainzone"))
|
|
{
|
|
$trebleVal = int($a[2]) if not (($a[2] =~ /^\d$/ ) || ($a[2] =~ /\.5/) || ($a[2] =~ /\.0/));
|
|
$trebleVal = -6 if($trebleVal < -6);
|
|
$trebleVal = 6 if($trebleVal > 6);
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Tone><Speaker><Treble><Cross_Over><Val>" . ReadingsVal($name,"trebleCrossover","35") . "</Val><Exp>1</Exp><Unit>kHz</Unit></Cross_Over><Lvl><Val>" . $trebleVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Treble></Speaker></Tone></$zone></YAMAHA_AV>", $what, $trebleVal);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Tone><Treble><Val>" . $trebleVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Treble></Tone></Sound_Video></$zone></YAMAHA_AV>", $what, $trebleVal);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$trebleVal = int($trebleVal);
|
|
$trebleVal = -10 if($trebleVal < -10);
|
|
$trebleVal = 10 if($trebleVal > 10);
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Tone><Treble><Val>" . $trebleVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Treble></Tone></$zone></YAMAHA_AV>", $what, $trebleVal);
|
|
}
|
|
else
|
|
{
|
|
# step range is 2 dB for non DSP based models. add/subtract 1 if modulus 2 != 0
|
|
$trebleVal-- if(($trebleVal % 2 != 0) && ($trebleVal > 0));
|
|
$trebleVal++ if(($trebleVal % 2 != 0) && ($trebleVal < 0));
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Tone><Treble><Val>" . $trebleVal*10 . "</Val><Exp>1</Exp><Unit>dB</Unit></Treble></Tone></Sound_Video></$zone></YAMAHA_AV>", $what, $trebleVal);
|
|
}
|
|
}
|
|
}
|
|
elsif($what eq "dsp")
|
|
{
|
|
if(defined($a[2]))
|
|
{
|
|
if(not $dsp_modes_piped eq "")
|
|
{
|
|
if($a[2] =~ /^($dsp_modes_piped)$/)
|
|
{
|
|
my $command = YAMAHA_AVR_getParamName($hash, $a[2],$hash->{helper}{DSP_MODES});
|
|
|
|
if(defined($command) and length($command) > 0)
|
|
{
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
if($hash->{MODEL} eq "RX-V2065")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surr><Pgm_Sel>$command</Pgm_Sel></Surr></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surr><Pgm_Sel><Pgm>$command</Pgm></Pgm_Sel></Surr></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
my $straight_command = ((defined($hash->{MODEL}) && $hash->{MODEL} =~ /^RX-(?:A\d{1,2}00|V\d{1,2}67)$/) ? "<Straight>Off</Straight>" : "");
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><Program_Sel><Current>$straight_command<Sound_Program>$command</Sound_Program></Current></Program_Sel></Surround></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "invalid dsp mode: ".$a[2];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "No DSP presets are avaible. Please try an statusUpdate.";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (($dsp_modes_piped eq "") ? "No dsp presets are available. Please try an statusUpdate." : "No dsp preset was given");
|
|
}
|
|
}
|
|
elsif($what eq "straight" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surr><Pgm_Sel><Straight>On</Straight></Pgm_Sel></Surr></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><Program_Sel><Current><Straight>On</Straight></Current></Program_Sel></Surround></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surr><Pgm_Sel><Straight>Off</Straight></Pgm_Sel></Surr></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><Program_Sel><Current><Straight>Off</Straight></Current></Program_Sel></Surround></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "3dCinemaDsp" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "auto")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><_3D_Cinema_DSP>Auto</_3D_Cinema_DSP></Surround></$zone></YAMAHA_AV>", "3dCinemaDsp", "auto");
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><_3D_Cinema_DSP>Off</_3D_Cinema_DSP></Surround></$zone></YAMAHA_AV>", "3dCinemaDsp", "off");
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "adaptiveDrc" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "auto")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Adaptive_DRC>Auto</Adaptive_DRC></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Adaptive_DRC>Off</Adaptive_DRC></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "enhancer" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><Program_Sel><Current><Enhancer>On</Enhancer></Current></Program_Sel></Surround></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><Program_Sel><Current><Enhancer>Off</Enhancer></Current></Program_Sel></Surround></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "direct" and defined($a[2]))
|
|
{
|
|
if(exists($hash->{helper}{DIRECT_TAG}))
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><".$hash->{helper}{DIRECT_TAG}."><Mode>On</Mode></".$hash->{helper}{DIRECT_TAG}."></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><".$hash->{helper}{DIRECT_TAG}."><Mode>Off</Mode></".$hash->{helper}{DIRECT_TAG}."></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "Unable to execute \"$what ".$a[2]."\" - please execute a statusUpdate first before you use this command";
|
|
}
|
|
}
|
|
elsif($what eq "sleep" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Sleep>Off</Sleep></Power_Control></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "30min")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Sleep>30 min</Sleep></Power_Control></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "60min")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Sleep>60 min</Sleep></Power_Control></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "90min")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Sleep>90 min</Sleep></Power_Control></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "120min")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Sleep>120 min</Sleep></Power_Control></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "last")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Power_Control><Sleep>Last</Sleep></Power_Control></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "remoteControl" and defined($a[2]))
|
|
{
|
|
# the RX-Vx71, RX-Vx73, RX-Ax10, RX-Ax20 series use a different tag name to access the remoteControl commands
|
|
my $control_tag = exists $hash->{MODEL} && $hash->{MODEL} =~ /^RX-V\d{1,2}7(1|3)|RX-A\d{1,2}(1|2)0$/ ? 'List_Control' : 'Cursor_Control';
|
|
#Log3($name, 3, "YAMAHA_AVR ($name) - set remoteControl called with arg $a[2]");
|
|
|
|
if($a[2] eq "up")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Cursor>Up</Cursor></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "down")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Cursor>Down</Cursor></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "left")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Cursor>Left</Cursor></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "right")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Cursor>Right</Cursor></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "display")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Menu_Control>Display</Menu_Control></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "return")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Cursor>Return</Cursor></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "enter")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Cursor>Sel</Cursor></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "setup")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Menu_Control>On Screen</Menu_Control></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "option")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><$zone><$control_tag><Menu_Control>Option</Menu_Control></$control_tag></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "tunerPresetUp")
|
|
{
|
|
if($hash->{helper}{SUPPORT_DAB})
|
|
{
|
|
if(ReadingsVal($name, "tunerFrequencyBand", "FM") eq "DAB")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><DAB><Preset><Preset_Sel>Up</Preset_Sel></Preset></DAB></Play_Control></DAB></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><FM><Preset><Preset_Sel>Up</Preset_Sel></Preset></FM></Play_Control></DAB></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Preset><Preset_Sel>Up</Preset_Sel></Preset></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
elsif($a[2] eq "tunerPresetDown")
|
|
{
|
|
if($hash->{helper}{SUPPORT_DAB})
|
|
{
|
|
if(ReadingsVal($name, "tunerFrequencyBand", "FM") eq "DAB")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><DAB><Preset><Preset_Sel>Down</Preset_Sel></Preset></DAB></Play_Control></DAB></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><FM><Preset><Preset_Sel>Down</Preset_Sel></Preset></FM></Play_Control></DAB></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Preset><Preset_Sel>Down</Preset_Sel></Preset></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "play")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Playback>Play</Playback></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($what eq "stop")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Playback>Stop</Playback></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($what eq "pause")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Playback>Pause</Playback></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($what eq "navigateListMenu")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Basic_Status>GetParam</Basic_Status></$zone></YAMAHA_AV>", "statusRequest", "basicStatus", {options => {no_playinfo => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><[CURRENT_INPUT_TAG]><List_Info>GetParam</List_Info></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, join(" ", @a[2..$#a]), {options => {init => 1}});
|
|
}
|
|
elsif($what eq "preset" and $a[2] =~ /^\d+$/ and $a[2] >= 1 and $a[2] <= 40)
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Preset><Preset_Sel>".$a[2]."</Preset_Sel></Preset></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2], {options => {can_fail => 1, preset => $a[2]}});
|
|
}
|
|
elsif($what eq "presetUp")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Preset><Preset_Sel>Up</Preset_Sel></Preset></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2], {options => {can_fail => 1, preset => "Up"}});
|
|
}
|
|
elsif($what eq "presetDown")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Preset><Preset_Sel>Down</Preset_Sel></Preset></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2], {options => {can_fail => 1, preset => "Down"}});
|
|
}
|
|
elsif($what eq "skip" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "forward")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Playback>Skip Fwd</Playback></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "reverse")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Playback>Skip Rev</Playback></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "shuffle" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Play_Mode><Shuffle>On</Shuffle></Play_Mode></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Play_Mode><Shuffle>Off</Shuffle></Play_Mode></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "repeat" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "one")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Play_Mode><Repeat>One</Repeat></Play_Mode></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Play_Mode><Repeat>Off</Repeat></Play_Mode></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "all")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><Play_Control><Play_Mode><Repeat>All</Repeat></Play_Mode></Play_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "partyMode" and defined($a[2]))
|
|
{
|
|
if($hash->{helper}{SUPPORT_PARTY_MODE} and $hash->{ACTIVE_ZONE} eq "mainzone")
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Mode>On</Mode></Party_Mode></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Mode>Off</Mode></Party_Mode></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
elsif($hash->{helper}{SUPPORT_PARTY_MODE} and $hash->{ACTIVE_ZONE} ne "mainzone")
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Target_Zone><$zone>Enable</$zone></Target_Zone></Party_Mode></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Target_Zone><$zone>Disable</$zone></Target_Zone></Party_Mode></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
}
|
|
elsif($what eq "tunerFrequency" and defined($a[2]))
|
|
{
|
|
if($a[2] =~ /^\d+(?:(?:\.|,)\d{1,2})?$/)
|
|
{
|
|
$a[2] =~ s/,/./;
|
|
|
|
if((defined($a[3]) and $a[3] eq "AM" )) # AM Band
|
|
{
|
|
if($hash->{helper}{SUPPORT_DAB})
|
|
{
|
|
return "no AM band supported by DAB based models";
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Tuning><Band>AM</Band><Freq><AM><Val>".$a[2]."</Val><Exp>0</Exp><Unit>kHz</Unit></AM></Freq></Tuning></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
else # FM Band
|
|
{
|
|
if($hash->{helper}{SUPPORT_DAB})
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><FM><Tuning><Freq><Val>".($a[2] * 100)."</Val><Exp>2</Exp><Unit>MHz</Unit></Freq></Tuning></FM></Play_Control></DAB></YAMAHA_AV>", $what, $a[2], {options => {can_fail => 1}});
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Tuning><Band>FM</Band><Freq><FM><Val>".($a[2] * 100)."</Val><Exp>2</Exp><Unit>MHz</Unit></FM></Freq></Tuning></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "invalid tuner frequency value: ".$a[2];
|
|
}
|
|
}
|
|
elsif($what eq "tunerFrequencyBand" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "FM")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><Band>FM</Band></Play_Control></DAB></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "DAB")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><Band>DAB</Band></Play_Control></DAB></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "surroundDecoder")
|
|
{
|
|
if(defined($a[2]))
|
|
{
|
|
if(not $decoders_piped eq "")
|
|
{
|
|
if($a[2] =~ /^($decoders_piped)$/)
|
|
{
|
|
my $command = YAMAHA_AVR_getParamName($hash, $a[2],$hash->{helper}{SURROUND_DECODERS});
|
|
|
|
if(defined($command) and length($command) > 0)
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Surround><Sound_Program_Param><SUR_DECODE><Decoder_Type>$command</Decoder_Type></SUR_DECODE></Sound_Program_Param></Surround></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return "invalid surround decoder: ".$a[2];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "No surround decoders are avaible. Please try an statusUpdate.";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (($decoders_piped eq "") ? "No surround decoders are available. Please try an statusUpdate." : "No surround decoder was given");
|
|
}
|
|
}
|
|
elsif($what eq "displayBrightness")
|
|
{
|
|
if($a[2] =~ /^-?\d+$/ and $a[2] >= -4 and $a[2] <= 0)
|
|
{
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><System><Display><FL><Dimmer><Val>".$a[2]."</Val><Exp>0</Exp><Unit></Unit></Dimmer></FL></Display></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><System><Misc><Display><FL><Dimmer>".$a[2]."</Dimmer></FL></Display></Misc></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return "invalid tuner frequency value: ".$a[2];
|
|
}
|
|
}
|
|
elsif($what eq "ypaoVolume" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "auto")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><YPAO_Volume>Auto</YPAO_Volume></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><YPAO_Volume>Off</YPAO_Volume></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "extraBass" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "auto")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Extra_Bass>Auto</Extra_Bass></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><Sound_Video><Extra_Bass>Off</Extra_Bass></Sound_Video></$zone></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "hdmiOut1" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Sound_Video><HDMI><Output><OUT_1>On</OUT_1></Output></HDMI></Sound_Video></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Sound_Video><HDMI><Output><OUT_1>Off</OUT_1></Output></HDMI></Sound_Video></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "hdmiOut2" and defined($a[2]))
|
|
{
|
|
if($a[2] eq "on")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Sound_Video><HDMI><Output><OUT_2>On</OUT_2></Output></HDMI></Sound_Video></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
elsif($a[2] eq "off")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Sound_Video><HDMI><Output><OUT_2>Off</OUT_2></Output></HDMI></Sound_Video></System></YAMAHA_AV>", $what, $a[2]);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
}
|
|
elsif($what eq "statusRequest")
|
|
{
|
|
YAMAHA_AVR_GetStatus($hash, 1);
|
|
}
|
|
else
|
|
{
|
|
return $usage;
|
|
}
|
|
return;
|
|
}
|
|
|
|
##########################
|
|
sub Attr {
|
|
my ($cmd, $name, $attr, $val) = @_;
|
|
|
|
my $hash = $defs{$name} // return;
|
|
|
|
if($attr eq 'disable')
|
|
{
|
|
# Start/Stop Timer according to new disabled-Value
|
|
YAMAHA_AVR_ResetTimer($hash, 1);
|
|
}
|
|
|
|
if($cmd eq "set")
|
|
{
|
|
if($attr =~ /^(?:volumeMax|volumeSteps)$/)
|
|
{
|
|
if( $val !~ m/^\d+$/ )
|
|
{
|
|
return "invalid attribute value for attribute $attr: $val";
|
|
}
|
|
|
|
if ( $attr eq 'volumeMax' && ($val < 0 || $val > 100) )
|
|
{
|
|
return "value is out of range (0-100) for attribute $attr: $val";
|
|
}
|
|
|
|
if ( $attr eq 'volumeSteps' && $val < 1 )
|
|
{
|
|
return "value is out of range (1-*) for attribute $attr: $val";
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
sub Undefine {
|
|
my $hash = shift // return;
|
|
my $name = shift // return;
|
|
|
|
# Stop all timers and exit
|
|
RemoveInternalTimer($hash);
|
|
|
|
if(exists($hash->{SYSTEM_ID}) and exists($hash->{ACTIVE_ZONE}) and exists($modules{YAMAHA_AVR}{defptr}{$hash->{SYSTEM_ID}}{$hash->{ACTIVE_ZONE}}))
|
|
{
|
|
delete($modules{YAMAHA_AVR}{defptr}{$hash->{SYSTEM_ID}}{$hash->{ACTIVE_ZONE}});
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
############################################################################################################
|
|
#
|
|
# Begin of helper functions
|
|
#
|
|
############################################################################################################
|
|
|
|
#
|
|
# Structure of a request hash
|
|
# ===========================
|
|
#
|
|
# {
|
|
# data => XML data to send without <?xml> prefix
|
|
# cmd => name of the command which is related to the request
|
|
# arg => optional argument related to the command and request
|
|
# original_hash => $hash of the originating definition. must be set, if a zone definition sends a request via the mainzones command queue.
|
|
# options => optional values, see following list of possibilities.
|
|
# }
|
|
#
|
|
# following option values can be used to control the execution of the command:
|
|
#
|
|
# {
|
|
# unless_in_queue => don't insert the command if an equivalent command already exists in the queue. (flag: 0,1 - default: 0)
|
|
# priority => integer value of priority. lower values will be executed before higher values in the appropriate order. (integer value - default value: 3)
|
|
# at_first => insert the command at the beginning of the queue, not at the end. (flag: 0,1 - default: 0)
|
|
# not_before => don't execute the command before the given Unix timestamp is reached (integer/float value)
|
|
# wait_after_response => wait the given number of seconds before processing further queue commands (integer/float value)
|
|
# can_fail => the request can return an error. If this flag is set, don't treat this as an communication error, ignore it instead. (flag: 0,1 - default: 0)
|
|
# no_playinfo => (only relevant for "statusRequest basicStatus") - don't retrieve extended playback information, after receiving a successful response (flag: 0,1 - default: 0)
|
|
# init => (only relevant for navigateListMenu) - marks the initial request to obtain the current menu level (flag: 0,1 - default: 0)
|
|
# last_layer => (only relevant for navigateListMenu) - the menu layer that was reached within the last request (integer value)
|
|
# item_selected => (only relevant for navigateListMenu) - is set, when the final item is going to be selected with the current request. (flag: 0,1 - default: 0)
|
|
# volume_target => (only relevant for volume) - the target volume, that should be reached by smoothing. (float value)
|
|
# volume_diff => (only relevant for volume) - the volume difference between each step to reach the target volume (float value)
|
|
# input_tag => (only relevant for "statusRequest playInfo") - contains the input tag name when requesting playInfo
|
|
# preset => (only relevant for preset/presetUp/presetDown) - contains the value for the preset to select (Up/Down/<NUMBER>). If set and the receiver model contains DAB radio, the command will be changed to DAB specific.
|
|
# }
|
|
#
|
|
|
|
|
|
#############################
|
|
# sends a command to the receiver via HTTP
|
|
sub
|
|
YAMAHA_AVR_SendCommand #($$$$;$)
|
|
{
|
|
# my ($hash, $data,$cmd,$arg,$additional_args) = @_;
|
|
my $hash = shift // return;
|
|
my $data = shift; # // return;
|
|
my $cmd = shift; # // return;
|
|
my $arg = shift; # // return;
|
|
my $additional_args = shift; #if set, this should be HASH type arg
|
|
my $name = $hash->{NAME};
|
|
my $options;
|
|
|
|
$data = "<?xml version=\"1.0\" encoding=\"utf-8\"?>".$data if($data);
|
|
|
|
# In case any URL changes must be made, this part is separated in this function".
|
|
|
|
my $param = {
|
|
data => $data,
|
|
cmd => $cmd,
|
|
arg => $arg
|
|
};
|
|
|
|
map {$param->{$_} = $additional_args->{$_}} keys %{$additional_args};
|
|
|
|
$options = $additional_args->{options} if exists $additional_args->{options};
|
|
|
|
my $device = $hash;
|
|
|
|
# if device is not mainzone and mainzone is defined via defptr
|
|
if(exists($hash->{SYSTEM_ID}) and exists($hash->{ACTIVE_ZONE}) and $hash->{ACTIVE_ZONE} ne "mainzone" and exists($modules{YAMAHA_AVR}{defptr}{$hash->{SYSTEM_ID}}{mainzone}))
|
|
{
|
|
$hash->{MAIN_ZONE} = $modules{YAMAHA_AVR}{defptr}{$hash->{SYSTEM_ID}}{mainzone}->{NAME};
|
|
|
|
# DSP based models only: use the http queue from mainzone to execute command
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
$device = $modules{YAMAHA_AVR}{defptr}{$hash->{SYSTEM_ID}}{mainzone};
|
|
$param->{original_hash} = $hash;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete($hash->{MAIN_ZONE}) if(exists($hash->{MAIN_ZONE}));
|
|
}
|
|
|
|
if($options->{unless_in_queue} and grep( ($_->{cmd} eq $cmd and ( (not(defined($arg) or defined($_->{arg}))) or $_->{arg} eq $arg)) ,@{$device->{helper}{CMD_QUEUE}}))
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - comand \"$cmd".(defined($arg) ? " ".$arg : "")."\" is already in queue, skip adding another one";
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - append to queue ".($options->{at_first} ? "(at first) ":"")."of device ".$device->{NAME}." \"$cmd".(defined($arg) ? " ".$arg : "")."\": $data";
|
|
|
|
if($options->{at_first})
|
|
{
|
|
unshift @{$device->{helper}{CMD_QUEUE}}, $param;
|
|
}
|
|
else
|
|
{
|
|
push @{$device->{helper}{CMD_QUEUE}}, $param;
|
|
}
|
|
}
|
|
|
|
YAMAHA_AVR_HandleCmdQueue($device);
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# starts http requests from cmd queue
|
|
sub
|
|
YAMAHA_AVR_HandleCmdQueue #($)
|
|
{
|
|
my $hash = shift // return;
|
|
my $name = $hash->{NAME};
|
|
my $address = $hash->{helper}{ADDRESS};
|
|
|
|
if(not($hash->{helper}{RUNNING_REQUEST}) and @{$hash->{helper}{CMD_QUEUE}})
|
|
{
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - no commands currently running, but queue has pending commands. preparing new request";
|
|
my $params = {
|
|
url => "http://".$address."/YamahaRemoteControl/ctrl",
|
|
timeout => AttrVal($name, "requestTimeout", 10),
|
|
noshutdown => 1,
|
|
keepalive => 0,
|
|
httpversion => "1.1",
|
|
loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
|
|
hash => $hash,
|
|
callback => \&YAMAHA_AVR_ParseResponse
|
|
};
|
|
|
|
my $request = YAMAHA_AVR_getNextRequestHash($hash);
|
|
|
|
if ( !defined $request )
|
|
{
|
|
# still request in queue, but not mentioned to be executed now
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - still requests in queue, but no command shall be executed at the moment. Retry in 1 second.";
|
|
RemoveInternalTimer($hash, \&YAMAHA_AVR_HandleCmdQueue);
|
|
InternalTimer(gettimeofday()+1,\&YAMAHA_AVR_HandleCmdQueue, $hash);
|
|
return;
|
|
}
|
|
|
|
$request->{options}{priority} = 3 if !exists $request->{options}{priority};
|
|
delete $request->{data} if exists $request->{data} && !$request->{data};
|
|
$request->{data}=~ s/\[CURRENT_INPUT_TAG\]/$hash->{helper}{CURRENT_INPUT_TAG}/g if exists $request->{data} && exists $hash->{helper}{CURRENT_INPUT_TAG};
|
|
|
|
if($request->{options}{preset} and $hash->{helper}{SUPPORT_DAB} and $hash->{helper}{CURRENT_INPUT_TAG} eq "DAB")
|
|
{
|
|
if(ReadingsVal($name, "tunerFrequencyBand","") eq "DAB")
|
|
{
|
|
$request->{data} = "<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><DAB><Preset><Preset_Sel>".$request->{options}{preset}."</Preset_Sel></Preset></DAB></Play_Control></DAB></YAMAHA_AV>";
|
|
}
|
|
elsif(ReadingsVal($name, "tunerFrequencyBand","") eq "FM")
|
|
{
|
|
$request->{data} = "<YAMAHA_AV cmd=\"PUT\"><DAB><Play_Control><FM><Preset><Preset_Sel>".$request->{options}{preset}."</Preset_Sel></Preset></FM></Play_Control></DAB></YAMAHA_AV>";
|
|
}
|
|
}
|
|
|
|
map {$hash->{helper}{".HTTP_CONNECTION"}{$_} = $params->{$_}} keys %{$params};
|
|
map {$hash->{helper}{".HTTP_CONNECTION"}{$_} = $request->{$_}} keys %{$request};
|
|
|
|
$hash->{helper}{RUNNING_REQUEST} = 1;
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - send command \"$request->{cmd}".(defined($request->{arg}) ? " ".$request->{arg} : "")."\"".(exists($request->{data}) ? ": ".$request->{data} : "");
|
|
HttpUtils_NonblockingGet($hash->{helper}{".HTTP_CONNECTION"});
|
|
}
|
|
|
|
$hash->{CMDs_pending} = @{$hash->{helper}{CMD_QUEUE}};
|
|
delete $hash->{CMDs_pending} if !$hash->{CMDs_pending};
|
|
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# selects the next command from command queue that has to be executed (undef if no command has to be executed now)
|
|
sub YAMAHA_AVR_getNextRequestHash #($)
|
|
{
|
|
my $hash = shift // return;
|
|
my $name = $hash->{NAME};
|
|
|
|
if(@{$hash->{helper}{CMD_QUEUE}})
|
|
{
|
|
my $last = $#{$hash->{helper}{CMD_QUEUE}};
|
|
|
|
my $next_item;
|
|
my $next_item_prio;
|
|
|
|
for my $item (0 .. $last)
|
|
{
|
|
my $param = $hash->{helper}{CMD_QUEUE}[$item];
|
|
|
|
if(defined($param))
|
|
{
|
|
my $cmd = (defined($param->{cmd}) ? $param->{cmd} : "");
|
|
my $arg = (defined($param->{arg}) ? $param->{arg} : "");
|
|
my $data = (defined($param->{data}) ? "1" : "0");
|
|
my $options = $param->{options};
|
|
|
|
my $opt_not_before = (exists($options->{not_before}) ? sprintf("%.2fs", ($options->{not_before} - gettimeofday())): "0");
|
|
my $opt_priority = (exists($options->{priority}) ? $options->{priority} : "-");
|
|
my $opt_at_first = (exists($options->{at_first}) ? $options->{at_first} : "0");
|
|
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - checking cmd queue item: $item (cmd: $cmd, arg: $arg, data: $data, priority: $opt_priority, at_first: $opt_at_first, not_before: $opt_not_before)";
|
|
|
|
if(exists($param->{data}))
|
|
{
|
|
if(defined($next_item) and ((defined($next_item_prio) and exists($options->{priority}) and $options->{priority} < $next_item_prio) or (defined($options->{priority}) and not defined($next_item_prio))))
|
|
{
|
|
# choose actual item if priority of previous selected item is higher or not set
|
|
$next_item = $item;
|
|
$next_item_prio = $options->{priority};
|
|
}
|
|
|
|
unless((exists($options->{not_before}) and $options->{not_before} > gettimeofday()) or (defined($next_item)))
|
|
{
|
|
$next_item = $item;
|
|
$next_item_prio = $options->{priority};
|
|
}
|
|
}
|
|
else # dummy command to delay the execution of further commands in queue
|
|
{
|
|
if(exists($options->{not_before}) and $options->{not_before} <= gettimeofday() and not(defined($next_item)))
|
|
{
|
|
# if not_before timestamp of dummy item is reached, delete it and continue processing for next command
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - item $item is a dummy cmd item with 'not_before' set which is already expired, delete it and recheck index $item again";
|
|
splice(@{$hash->{helper}{CMD_QUEUE}}, $item, 1);
|
|
redo;
|
|
}
|
|
elsif(exists($options->{not_before}) and not(defined($next_item) and defined($next_item_prio)))
|
|
{
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - we have to wait ".sprintf("%.2fs", ($options->{not_before} - gettimeofday()))." seconds before next item can be checked";
|
|
last;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(defined($next_item))
|
|
{
|
|
if(exists($hash->{helper}{CMD_QUEUE}[$next_item]{options}{not_before}))
|
|
{
|
|
delete($hash->{helper}{CMD_QUEUE}[$next_item]{options}{not_before});
|
|
}
|
|
|
|
my $return = $hash->{helper}{CMD_QUEUE}[$next_item];
|
|
|
|
splice(@{$hash->{helper}{CMD_QUEUE}}, $next_item, 1);
|
|
$hash->{helper}{CMD_QUEUE} = () unless(defined($hash->{helper}{CMD_QUEUE}));
|
|
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - choosed item $next_item as next command";
|
|
return $return;
|
|
}
|
|
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - no suitable command item found";
|
|
return;
|
|
}
|
|
}
|
|
|
|
#############################
|
|
# parses the receiver response
|
|
sub
|
|
YAMAHA_AVR_ParseResponse #($$$)
|
|
{
|
|
my $param = shift // return;
|
|
my $err = shift // q{};
|
|
my $data = shift // q{};
|
|
|
|
my $hash = $param->{hash};
|
|
my $queue_hash = $param->{hash};
|
|
|
|
my $cmd = $param->{cmd};
|
|
my $arg = $param->{arg};
|
|
my $options = $param->{options};
|
|
|
|
$hash->{helper}{RUNNING_REQUEST} = 0;
|
|
delete $hash->{helper}{'.HTTP_CONNECTION'} if !$param->{keepalive};
|
|
|
|
# if request is from an other definition (zone2, zone3, ...)
|
|
$hash = $param->{original_hash} if exists $param->{original_hash};
|
|
|
|
my $name = $hash->{NAME};
|
|
my $zone = YAMAHA_AVR_getParamName($hash, $hash->{ACTIVE_ZONE}, $hash->{helper}{ZONES});
|
|
|
|
if ( exists $param->{code} )
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - received HTTP code ".$param->{code}." for command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\"";
|
|
|
|
if($cmd eq "statusRequest" and $param->{code} ne "200")
|
|
{
|
|
if($arg eq "playShuffle")
|
|
{
|
|
$hash->{helper}{SUPPORT_SHUFFLE_REPEAT} = 0;
|
|
}
|
|
elsif($arg eq "toneStatus")
|
|
{
|
|
$hash->{helper}{SUPPORT_TONE_STATUS} = 0;
|
|
}
|
|
elsif($arg eq "partyModeStatus" or $arg eq "partyModeZones")
|
|
{
|
|
$hash->{helper}{SUPPORT_PARTY_MODE} = 0;
|
|
}
|
|
elsif($arg eq "surroundDecoder")
|
|
{
|
|
$hash->{helper}{SUPPORT_SURROUND_DECODER} = 0;
|
|
}
|
|
elsif($arg eq "displayBrightness")
|
|
{
|
|
$hash->{helper}{SUPPORT_DISPLAY_BRIGHTNESS} = 0;
|
|
}
|
|
elsif($arg eq "hdmiOut1" or $arg eq "hdmiOut2")
|
|
{
|
|
$hash->{helper}{SUPPORT_HDMI_OUT} = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if($err ne "" and not $options->{can_fail})
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - could not execute command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $err";
|
|
|
|
if((not exists($hash->{helper}{AVAILABLE})) or (exists($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 1))
|
|
{
|
|
Log3 $name, 3, "YAMAHA_AVR ($name) - could not execute command on device $name. Please turn on your device in case of deactivated network standby or check for correct hostaddress.";
|
|
readingsSingleUpdate($hash, "presence", "absent", 1);
|
|
readingsSingleUpdate($hash, "state", "absent", 1);
|
|
}
|
|
|
|
$hash->{helper}{AVAILABLE} = 0;
|
|
}
|
|
|
|
if($data ne "")
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data";
|
|
|
|
# add a dummy queue entry to wait a specific time before next command starts
|
|
if($options->{wait_after_response})
|
|
{
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - next command for device ".$queue_hash->{NAME}." has to wait at least ".$options->{wait_after_response}." seconds before execution";
|
|
unshift @{$queue_hash->{helper}{CMD_QUEUE}}, {options=> { priority => 1, not_before => (gettimeofday()+$options->{wait_after_response})} };
|
|
}
|
|
|
|
if(defined($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 0)
|
|
{
|
|
Log3 $name, 3, "YAMAHA_AVR ($name) - device $name reappeared";
|
|
readingsSingleUpdate($hash, "presence", "present", 1);
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Basic_Status>GetParam</Basic_Status></$zone></YAMAHA_AV>", "statusRequest", "basicStatus", {options => {at_first => 1}}) if(defined($zone));
|
|
}
|
|
|
|
$hash->{helper}{AVAILABLE} = 1;
|
|
|
|
if(not $data =~ / RC="0"/ and $data =~ / RC="(\d+)"/ and not $options->{can_fail})
|
|
{
|
|
# if the returncode isn't 0, than the command was not successful
|
|
Log3 $name, 3, "YAMAHA_AVR ($name) - Could not execute \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": received return code $1";
|
|
}
|
|
|
|
readingsBeginUpdate($hash);
|
|
|
|
if($cmd eq "statusRequest")
|
|
{
|
|
if($arg eq "unitDescription")
|
|
{
|
|
if($data =~ /<URL>(.+?)<\/URL>/)
|
|
{
|
|
$hash->{helper}{XML} = $1;
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{XML} = "/YamahaRemoteControl/desc.xml";
|
|
}
|
|
|
|
Log3 $name, 5, "YAMAHA_AVR ($name) - requesting unit description XML: http://".$hash->{helper}{ADDRESS}.$hash->{helper}{XML};
|
|
|
|
YAMAHA_AVR_SendCommand($hash,0,"statusRequest","retrieveDescXML", {
|
|
url => "http://".$hash->{helper}{ADDRESS}.$hash->{helper}{XML} ,
|
|
callback => \&YAMAHA_AVR_ParseXML,
|
|
options => {priority => 2}
|
|
});
|
|
}
|
|
elsif($arg eq "systemConfig")
|
|
{
|
|
if($data =~ /<Model_Name>(.+?)<\/Model_Name>.*?<System_ID>(.+?)<\/System_ID>.*?<Version>.*?<Main>(.+?)<\/Main>.*?<Sub>(.+?)<\/Sub>.*?<\/Version>/) # DSP based models
|
|
{
|
|
$hash->{MODEL} = $1;
|
|
$hash->{SYSTEM_ID} = $2;
|
|
$hash->{FIRMWARE} = $3." ".$4;
|
|
}
|
|
elsif($data =~ /<Model_Name>(.+?)<\/Model_Name>.*?<System_ID>(.+?)<\/System_ID>.*?<Version>(.+?)<\/Version>/)
|
|
{
|
|
$hash->{MODEL} = $1;
|
|
$hash->{SYSTEM_ID} = $2;
|
|
$hash->{FIRMWARE} = $3;
|
|
}
|
|
|
|
$attr{$name}{model} = $hash->{MODEL};
|
|
}
|
|
elsif($arg eq "getInputs")
|
|
{
|
|
delete($hash->{helper}{INPUTS}) if(exists($hash->{helper}{INPUTS}));
|
|
|
|
while($data =~ /<Param>(.+?)<\/Param>/gc)
|
|
{
|
|
if(defined($hash->{helper}{INPUTS}) and length($hash->{helper}{INPUTS}) > 0)
|
|
{
|
|
$hash->{helper}{INPUTS} .= "|";
|
|
}
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - found input: $1";
|
|
$hash->{helper}{INPUTS} .= $1;
|
|
}
|
|
|
|
$hash->{helper}{INPUTS} = join("|", sort split("\\|", $hash->{helper}{INPUTS}));
|
|
}
|
|
elsif($arg eq "getScenes")
|
|
{
|
|
delete($hash->{helper}{SCENES}) if(exists($hash->{helper}{SCENES}));
|
|
|
|
# get all available scenes from response
|
|
while($data =~ /<Item_\d+>.*?<Param>(.+?)<\/Param>.*?<RW>(\w+)<\/RW>.*?<\/Item_\d+>/gc)
|
|
{
|
|
# check if the RW-value is "W" (means: writeable => can be set through FHEM)
|
|
if($2 eq "W")
|
|
{
|
|
if(defined($hash->{helper}{SCENES}) and length($hash->{helper}{SCENES}) > 0)
|
|
{
|
|
$hash->{helper}{SCENES} .= "|";
|
|
}
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - found scene: $1";
|
|
$hash->{helper}{SCENES} .= $1;
|
|
}
|
|
}
|
|
}
|
|
elsif($arg eq "partyModeStatus")
|
|
{
|
|
if($hash->{ACTIVE_ZONE} eq "mainzone" and $data =~ /<Mode>(.+?)<\/Mode>/)
|
|
{
|
|
$hash->{helper}{SUPPORT_PARTY_MODE} = 1;
|
|
readingsBulkUpdate($hash, "partyMode", lc($1));
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{SUPPORT_PARTY_MODE} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "partyModeZones")
|
|
{
|
|
if($hash->{ACTIVE_ZONE} ne "mainzone" and $data =~ /<Target_Zone>.*?<$zone>(.+?)<\/$zone>.*?<\/Target_Zone>/)
|
|
{
|
|
$hash->{helper}{SUPPORT_PARTY_MODE} = 1;
|
|
|
|
if($1 eq "Enable")
|
|
{
|
|
readingsBulkUpdate($hash, "partyModeStatus", "on");
|
|
|
|
}
|
|
elsif($1 eq "Disable")
|
|
{
|
|
readingsBulkUpdate($hash, "partyModeStatus", "off");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{SUPPORT_PARTY_MODE} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "toneStatus")
|
|
{
|
|
if(($data =~ /<Tone><Speaker><Bass><Cross_Over><Val>(.+?)<\/Val><Exp>.*?<\/Exp><Unit>.*?<\/Unit><\/Cross_Over><Lvl><Val>(.+?)<\/Val>.*?<\/Lvl><\/Bass><\/Speaker><\/Tone>/) or ($data =~ /<Tone><Bass><Val>(.+?)<\/Val><Exp>1<\/Exp><Unit>dB<\/Unit><\/Bass><\/Tone>/))
|
|
{
|
|
$hash->{helper}{SUPPORT_TONE_STATUS} = 1;
|
|
|
|
if((exists($hash->{ACTIVE_ZONE})) && ($hash->{ACTIVE_ZONE} eq "mainzone"))
|
|
{
|
|
if(defined($2))
|
|
{
|
|
readingsBulkUpdate($hash, "bass", int($2)/10);
|
|
readingsBulkUpdate($hash, "bassCrossover", lc($1));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdate($hash, "bass", int($1)/10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdate($hash, "bass", int($1)/10);
|
|
}
|
|
}
|
|
elsif(($data =~ /<Tone><Speaker><Treble><Cross_Over><Val>(.+?)<\/Val><Exp>.*?<\/Exp><Unit>.*?<\/Unit><\/Cross_Over><Lvl><Val>(.+?)<\/Val>.*?<\/Lvl><\/Treble><\/Speaker><\/Tone>/) or ($data =~ /<Tone><Treble><Val>(.+?)<\/Val><Exp>1<\/Exp><Unit>dB<\/Unit><\/Treble><\/Tone>/))
|
|
{
|
|
$hash->{helper}{SUPPORT_TONE_STATUS} = 1;
|
|
|
|
if((exists($hash->{ACTIVE_ZONE})) && ($hash->{ACTIVE_ZONE} eq "mainzone"))
|
|
{
|
|
if(defined($2))
|
|
{
|
|
readingsBulkUpdate($hash, "treble", int($2)/10);
|
|
readingsBulkUpdate($hash, "trebleCrossover", lc($1));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdate($hash, "treble", int($1)/10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdate($hash, "treble", int($1)/10);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{SUPPORT_TONE_STATUS} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "basicStatus")
|
|
{
|
|
if($data =~ /<Power>(.+?)<\/Power>/)
|
|
{
|
|
my $power = $1;
|
|
|
|
if($power eq "Standby")
|
|
{
|
|
$power = "off";
|
|
}
|
|
readingsBulkUpdate($hash, "power", lc($power));
|
|
readingsBulkUpdate($hash, "state", lc($power));
|
|
}
|
|
|
|
# current volume and mute status
|
|
if($data =~ /<Volume><Lvl><Val>(.+?)<\/Val><Exp>(.+?)<\/Exp><Unit>.+?<\/Unit><\/Lvl><Mute>(.+?)<\/Mute>.*?<\/Volume>/)
|
|
{
|
|
readingsBulkUpdate($hash, "volumeStraight", ($1 / 10 ** $2));
|
|
readingsBulkUpdate($hash, "volume", YAMAHA_AVR_volume_abs2rel(($1 / 10 ** $2)));
|
|
readingsBulkUpdate($hash, "mute", lc($3));
|
|
}
|
|
elsif($data =~ /<Vol><Lvl><Val>(.+?)<\/Val><Exp>(.+?)<\/Exp><Unit>.+?<\/Unit><\/Lvl><Mute>(.+?)<\/Mute>.*?<\/Vol>/) # DSP based models
|
|
{
|
|
readingsBulkUpdate($hash, "volumeStraight", ($1 / 10 ** $2));
|
|
readingsBulkUpdate($hash, "volume", YAMAHA_AVR_volume_abs2rel(($1 / 10 ** $2)));
|
|
readingsBulkUpdate($hash, "mute", lc($3));
|
|
}
|
|
|
|
# (only available in zones other than mainzone) absolute or relative volume change to the mainzone
|
|
if($data =~ /<Volume>.*?<Output>(.+?)<\/Output>.*?<\/Volume>/)
|
|
{
|
|
readingsBulkUpdate($hash, "output", lc($1));
|
|
}
|
|
elsif($data =~ /<Vol>.*?<Output>(.+?)<\/Output>.*?<\/Vol>/) # DSP based models
|
|
{
|
|
readingsBulkUpdate($hash, "output", lc($1));
|
|
}
|
|
else
|
|
{
|
|
# delete the reading if this information is not available
|
|
delete($hash->{READINGS}{output}) if(exists($hash->{READINGS}{output}));
|
|
}
|
|
|
|
# current input same as the corresponding set command name
|
|
if($data =~ /<Input_Sel>(.+?)<\/Input_Sel>/)
|
|
{
|
|
readingsBulkUpdate($hash, "input", YAMAHA_AVR_Param2Fhem(lc($1), 0));
|
|
|
|
if($data =~ /<Power>On<\/Power>/ and $data =~ /<Src_Name>(.+?)<\/Src_Name>/)
|
|
{
|
|
$hash->{helper}{LAST_INPUT_TAG} = $hash->{helper}{CURRENT_INPUT_TAG} if(exists($hash->{helper}{CURRENT_INPUT_TAG}));
|
|
$hash->{helper}{CURRENT_INPUT_TAG} = $1;
|
|
|
|
if ( !$options->{no_playinfo} )
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - check for extended input informations on <$1>";
|
|
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$1><Play_Info>GetParam</Play_Info></$1></YAMAHA_AV>", "statusRequest", "playInfo", {options => {can_fail => 1, input_tag => $1}});
|
|
|
|
if ( !exists $hash->{helper}{LAST_INPUT_TAG} || $hash->{helper}{LAST_INPUT_TAG} ne $hash->{helper}{CURRENT_INPUT_TAG} || $hash->{helper}{SUPPORT_SHUFFLE_REPEAT} )
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$1><Play_Control><Play_Mode><Repeat>GetParam</Repeat></Play_Mode></Play_Control></$1></YAMAHA_AV>", "statusRequest", "playRepeat", {options => {can_fail => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$1><Play_Control><Play_Mode><Shuffle>GetParam</Shuffle></Play_Mode></Play_Control></$1></YAMAHA_AV>", "statusRequest", "playShuffle", {options => {can_fail => 1}});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - skipping check for extended input informations on <$1>";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete($hash->{helper}{CURRENT_INPUT_TAG}) if(exists($hash->{helper}{CURRENT_INPUT_TAG}));
|
|
delete($hash->{helper}{LAST_INPUT_TAG}) if(exists($hash->{helper}{LAST_INPUT_TAG}));
|
|
$hash->{helper}{SUPPORT_SHUFFLE_REPEAT} = 0;
|
|
readingsBulkUpdateIfChanged($hash, "currentAlbum", "");
|
|
readingsBulkUpdateIfChanged($hash, "currentTitle", "");
|
|
readingsBulkUpdateIfChanged($hash, "currentChannel", "");
|
|
readingsBulkUpdateIfChanged($hash, "currentStation", "");
|
|
readingsBulkUpdateIfChanged($hash, "currentStationFrequency","");
|
|
readingsBulkUpdateIfChanged($hash, "currentArtist", "");
|
|
readingsBulkUpdateIfChanged($hash, "playStatus", "stopped");
|
|
}
|
|
}
|
|
|
|
# input name as it is displayed on the receivers front display
|
|
if($data =~ /<Input>.*?<Title>\s*(.+?)\s*<\/Title>.*?<\/Input>/)
|
|
{
|
|
readingsBulkUpdate($hash, "inputName", $1);
|
|
}
|
|
elsif($data =~ /<Input>.*?<Input_Sel_Title>\s*(.+?)\s*<\/Input_Sel_Title>.*?<\/Input>/)
|
|
{
|
|
readingsBulkUpdate($hash, "inputName", $1);
|
|
}
|
|
|
|
if($data =~ /<Surround>.*?<Current>.*?<Straight>(.+?)<\/Straight>.*?<\/Current>.*?<\/Surround>/)
|
|
{
|
|
readingsBulkUpdate($hash, "straight", lc($1));
|
|
}
|
|
elsif($data =~ /<Surr>.*?<Straight>(.+?)<\/Straight>.*?<\/Surr>/) # DSP-Z based models
|
|
{
|
|
readingsBulkUpdate($hash, "straight", lc($1));
|
|
}
|
|
|
|
if($data =~ /<Surround>.*?<Current>.*?<Enhancer>(.+?)<\/Enhancer>.*?<\/Current>.*?<\/Surround>/)
|
|
{
|
|
readingsBulkUpdate($hash, "enhancer", lc($1));
|
|
}
|
|
|
|
if($data =~ /<Surround>.*?<Current>.*?<Sound_Program>(.+?)<\/Sound_Program>.*?<\/Current>.*?<\/Surround>/)
|
|
{
|
|
readingsBulkUpdate($hash, "dsp", YAMAHA_AVR_Param2Fhem($1, 0));
|
|
}
|
|
elsif($data =~ /<Surr>.*?<Pgm>(.+?)<\/Pgm>.*?<\/Surr>/) # DSP-Z based models
|
|
{
|
|
readingsBulkUpdate($hash, "dsp", YAMAHA_AVR_Param2Fhem($1, 0));
|
|
}
|
|
|
|
if($data =~ /<Surround>.*?<_3D_Cinema_DSP>(.+?)<\/_3D_Cinema_DSP>.*?<\/Surround>/)
|
|
{
|
|
readingsBulkUpdate($hash, "3dCinemaDsp", lc($1));
|
|
}
|
|
|
|
if($data =~ /<Sound_Video>.*?<Adaptive_DRC>(.+?)<\/Adaptive_DRC>.*?<\/Sound_Video>/)
|
|
{
|
|
readingsBulkUpdate($hash, "adaptiveDrc", lc($1));
|
|
}
|
|
|
|
if($data =~ /<Power_Control>.*?<Sleep>(.+?)<\/Sleep>.*?<\/Power_Control>/)
|
|
{
|
|
readingsBulkUpdate($hash, "sleep", YAMAHA_AVR_Param2Fhem($1, 0));
|
|
}
|
|
|
|
if($data =~ /<Sound_Video>.*?<Direct>.*?<Mode>(.+?)<\/Mode>.*?<\/Direct>.*?<\/Sound_Video>/)
|
|
{
|
|
readingsBulkUpdate($hash, "direct", lc($1));
|
|
$hash->{helper}{DIRECT_TAG} = "Direct";
|
|
}
|
|
elsif($data =~ /<Sound_Video>.*?<Pure_Direct>.*?<Mode>(.+?)<\/Mode>.*?<\/Pure_Direct>.*?<\/Sound_Video>/)
|
|
{
|
|
readingsBulkUpdate($hash, "direct", lc($1));
|
|
$hash->{helper}{DIRECT_TAG} = "Pure_Direct";
|
|
}
|
|
else
|
|
{
|
|
delete($hash->{helper}{DIRECT_TAG}) if(exists($hash->{helper}{DIRECT_TAG}));
|
|
}
|
|
|
|
if($data =~ /<Sound_Video>.*?<YPAO_Volume>(.+?)<\/YPAO_Volume>.*?<\/Sound_Video>/)
|
|
{
|
|
readingsBulkUpdate($hash, "ypaoVolume", lc($1));
|
|
$hash->{helper}{SUPPORT_YPAO_VOLUME} = 1;
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{SUPPORT_YPAO_VOLUME} = 0;
|
|
}
|
|
|
|
if($data =~ /<Sound_Video>.*?<Extra_Bass>(.+?)<\/Extra_Bass>.*?<\/Sound_Video>/)
|
|
{
|
|
$hash->{helper}{SUPPORT_EXTRA_BASS} = 1;
|
|
readingsBulkUpdate($hash, "extraBass", lc($1));
|
|
}
|
|
else
|
|
{
|
|
$hash->{helper}{SUPPORT_EXTRA_BASS} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "playInfo")
|
|
{
|
|
if($data =~ /<Meta_Info>.*?<Artist>(.+?)<\/Artist>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentArtist", _html2txt($1));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdateIfChanged($hash, "currentArtist", "");
|
|
}
|
|
|
|
|
|
if($data =~ /<Band>DAB<\/Band>/ and $data =~ /<Meta_Info>.*?<Service_Label>(.+?)<\/Service_Label>.*?<\/Meta_Info>/) # RX-481D provides always Meta-Info for DAB and Tuner
|
|
{
|
|
readingsBulkUpdate($hash, "currentStation", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Station>(.+?)<\/Station>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentStation", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Program_Service>(.+?)<\/Program_Service>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentStation", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Station>(.+?)<\/Station>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentStation", _html2txt($1));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdateIfChanged($hash, "currentStation", "");
|
|
}
|
|
|
|
if($data =~ /<Meta_Info>.*?<Channel>(.+?)<\/Channel>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentChannel", _html2txt($1));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdateIfChanged($hash, "currentChannel", "");
|
|
}
|
|
|
|
if($data =~ /<Meta_Info>.*?<Album>(.+?)<\/Album>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentAlbum", _html2txt($1));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdateIfChanged($hash, "currentAlbum", "");
|
|
}
|
|
|
|
if($data =~ /<Band>DAB<\/Band>/ and $data =~ /<Meta_Info>.*?<DLS>(.+?)<\/DLS>.*?<\/Meta_Info>/) # RX-481D provides always Meta-Info for DAB and FM
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Song>(.+?)<\/Song>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Track>(.+?)<\/Track>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Radio_Text_A>(.+?)<\/Radio_Text_A>.*?<\/Meta_Info>/)
|
|
{
|
|
my $tmp = $1;
|
|
|
|
if($data =~ /<Meta_Info>.*?<Radio_Text_A>(.+?)<\/Radio_Text_A>.*?<Radio_Text_B>(.+?)<\/Radio_Text_B>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt(trim($1)." ".trim($2)));
|
|
}
|
|
else
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt($tmp));
|
|
}
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Radio_Text_B>(.+?)<\/Radio_Text_B>.*?<\/Meta_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt($1));
|
|
}
|
|
elsif($data =~ /<Meta_Info>.*?<Radio_Text>(.+?)<\/Radio_Text>.*?<\/Meta_Info>/) # RX-V481D
|
|
{
|
|
readingsBulkUpdate($hash, "currentTitle", _html2txt($1));
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
{
|
|
readingsBulkUpdateIfChanged($hash, "currentTitle", "");
|
|
}
|
|
|
|
if($data =~ /<Playback_Info>(.+?)<\/Playback_Info>/)
|
|
{
|
|
readingsBulkUpdate($hash, "playStatus", "stopped") if($1 eq "Stop");
|
|
readingsBulkUpdate($hash, "playStatus", "playing") if($1 eq "Play");
|
|
readingsBulkUpdate($hash, "playStatus", "paused") if($1 eq "Pause");
|
|
}
|
|
elsif($options->{input_tag} eq "Tuner")
|
|
{
|
|
readingsBulkUpdate($hash, "playStatus", "playing");
|
|
}
|
|
|
|
if(($data =~ /<Band>DAB<\/Band>/ and $data =~ /<DAB>.*?<Signal_Info>.*?<Freq><Val>(\d+?)<\/Val><Exp>(\d+?)<\/Exp><Unit>(.*?)<\/Unit><\/Freq>.*?<\/Signal_Info>.*?<\/DAB>/) or # RX-481D provides always Meta-Info for DAB and FM
|
|
($data =~ /<Tuning>.*?<Freq>(?:<Current>)?<Val>(\d+?)<\/Val><Exp>(\d+?)<\/Exp><Unit>(.*?)<\/Unit>(?:<\/Current>)?.*?<\/Tuning>/) or
|
|
(_isModel_DSP($hash) and $data =~ /<Tuning>.*?<Freq><Val>(\d+?)<\/Val><Exp>(\d+?)<\/Exp><Unit>(.*?)<\/Unit><\/Freq>.*?<\/Tuning>/))
|
|
{
|
|
readingsBulkUpdate($hash, "currentStationFrequency", sprintf("%.$2f", ($1 / (10 ** $2)))." $3");
|
|
readingsBulkUpdate($hash, "tunerFrequency", sprintf("%.$2f", ($1 / (10 ** $2))));
|
|
|
|
if($data =~ /<Band>(.+?)<\/Band>/)
|
|
{
|
|
readingsBulkUpdate($hash, "tunerFrequencyBand", uc($1));
|
|
}
|
|
}
|
|
elsif(ReadingsVal($name, "currentStationFrequency", "") ne "")
|
|
{
|
|
readingsBulkUpdateIfChanged($hash, "currentStationFrequency","");
|
|
}
|
|
}
|
|
elsif($arg eq "playShuffle")
|
|
{
|
|
if($data =~ /<Shuffle>(.+?)<\/Shuffle>/)
|
|
{
|
|
$hash->{helper}{SUPPORT_SHUFFLE_REPEAT} = 1;
|
|
readingsBulkUpdate($hash, "shuffle", lc($1));
|
|
}
|
|
}
|
|
elsif($arg eq "playRepeat")
|
|
{
|
|
if($data =~ /<Repeat>(.+?)<\/Repeat>/)
|
|
{
|
|
$hash->{helper}{SUPPORT_SHUFFLE_REPEAT} = 1;
|
|
readingsBulkUpdate($hash, "repeat", lc($1));
|
|
}
|
|
}
|
|
elsif($arg eq "fwUpdate")
|
|
{
|
|
if($data =~ /<Status>(.+?)<\/Status>/)
|
|
{
|
|
readingsBulkUpdate($hash, "newFirmware", lc($1));
|
|
}
|
|
}
|
|
elsif($arg eq "tunerFrequency")
|
|
{
|
|
if($data =~ /<Tuning>.*?<Band>(.+?)<\/Band>.*?<\/Tuning>/)
|
|
{
|
|
readingsBulkUpdate($hash, "tunerFrequencyBand", uc($1));
|
|
}
|
|
|
|
if($data =~ /<Tuning>.*?<Freq><Current><Val>(\d+?)<\/Val><Exp>(\d+?)<\/Exp><Unit>(.*?)<\/Unit><\/Current>.*?<\/Tuning>/ or (_isModel_DSP($hash) and $data =~ /<Tuning>.*?<Freq><Val>(\d+?)<\/Val><Exp>(\d+?)<\/Exp><Unit>(.*?)<\/Unit><\/Freq>.*?<\/Tuning>/))
|
|
{
|
|
readingsBulkUpdate($hash, "tunerFrequency", sprintf("%.$2f", ($1 / (10 ** $2))));
|
|
}
|
|
}
|
|
elsif($arg eq 'surroundDecoder')
|
|
{
|
|
if($data =~ /<Decoder_Type>(.+?)<\/Decoder_Type>/)
|
|
{
|
|
$hash->{helper}{SUPPORT_SURROUND_DECODER} = 1;
|
|
readingsBulkUpdate($hash, 'surroundDecoder', YAMAHA_AVR_Param2Fhem($1, 0));
|
|
$hash->{helper}{SURROUND_DECODERS} //= _generateSurroundDecoderList($hash);
|
|
}
|
|
elsif($data =~ /RC="2"/) # is not supported by this specific model
|
|
{
|
|
$hash->{helper}{SUPPORT_SURROUND_DECODER} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "displayBrightness")
|
|
{
|
|
if($data =~ /<Dimmer>(.+?)<\/Dimmer>/ or (_isModel_DSP($hash) and $data =~ /<Val>(.+?)<\/Val>/))
|
|
{
|
|
$hash->{helper}{SUPPORT_DISPLAY_BRIGHTNESS} = 1;
|
|
readingsBulkUpdate($hash, "displayBrightness", $1);
|
|
}
|
|
elsif($data =~ /RC="2"/) # is not supported by this specific model
|
|
{
|
|
$hash->{helper}{SUPPORT_DISPLAY_BRIGHTNESS} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "hdmiOut1")
|
|
{
|
|
if($data =~ /<OUT_1>(.+?)<\/OUT_1>/)
|
|
{
|
|
readingsBulkUpdate($hash, "hdmiOut1", lc($1));
|
|
}
|
|
elsif($data =~ /RC="2"/) # is not supported by this specific model
|
|
{
|
|
$hash->{helper}{SUPPORT_HDMI_OUT} = 0;
|
|
}
|
|
}
|
|
elsif($arg eq "hdmiOut2")
|
|
{
|
|
if($data =~ /<OUT_2>(.+?)<\/OUT_2>/)
|
|
{
|
|
readingsBulkUpdate($hash, "hdmiOut2", lc($1));
|
|
}
|
|
elsif($data =~ /RC="2"/) # is not supported by this specific model
|
|
{
|
|
$hash->{helper}{SUPPORT_HDMI_OUT} = 0;
|
|
}
|
|
}
|
|
}
|
|
elsif($cmd eq "on")
|
|
{
|
|
if($data =~ /RC="0"/ and $data =~ /<Power><\/Power>/)
|
|
{
|
|
readingsBulkUpdate($hash, "power", "on");
|
|
readingsBulkUpdate($hash, "state","on");
|
|
}
|
|
}
|
|
elsif($cmd eq "off")
|
|
{
|
|
if($data =~ /RC="0"/ and $data =~ /<Power><\/Power>/)
|
|
{
|
|
readingsBulkUpdate($hash, "power", "off");
|
|
readingsBulkUpdate($hash, "state","off");
|
|
}
|
|
}
|
|
elsif($cmd eq "navigateListMenu")
|
|
{
|
|
my @list_cmds = split("/", $arg);
|
|
|
|
if($data =~ /<Menu_Layer>(.+?)<\/Menu_Layer><Menu_Name>(.*?)<\/Menu_Name><Current_List>(.+?)<\/Current_List><Cursor_Position><Current_Line>(\d+)<\/Current_Line><Max_Line>(\d+)<\/Max_Line><\/Cursor_Position>/)
|
|
{
|
|
|
|
my $menu_layer = $1;
|
|
my $menu_name = $2;
|
|
my $current_list = $3;
|
|
my $current_line = $4;
|
|
my $max_line = $5;
|
|
|
|
my $menu_status = "Ready"; # RX-Vx71's based series models does not provide <Menu_Status> so "Ready" must be assumed
|
|
|
|
# but check, if <Menu_Status> is provided. Is that so, use the provided value
|
|
if($data =~ /<Menu_Status>(.+?)<\/Menu_Status>/)
|
|
{
|
|
$menu_status = $1;
|
|
}
|
|
|
|
my $last = ($options->{last_menu_item} or ($menu_layer == ($#list_cmds + 1)));
|
|
|
|
if($menu_status eq "Ready")
|
|
{
|
|
# menu browsing finished
|
|
if(exists($options->{last_layer}) and $options->{last_layer} == $menu_layer and $last and $options->{item_selected})
|
|
{
|
|
Log3 $name, 4 ,"YAMAHA_AVR ($name) - menu browsing to $arg is finished. requesting basic status";
|
|
readingsEndUpdate($hash, 1);
|
|
YAMAHA_AVR_GetStatus($hash, 1);
|
|
return;
|
|
}
|
|
|
|
# initialization sequence
|
|
if($options->{init} and $menu_layer > 1)
|
|
{
|
|
Log3 $name, 4 ,"YAMAHA_AVR ($name) - return to start of menu to begin menu browsing";
|
|
|
|
my $back_cmd = "Return to Home";
|
|
my $tries = ++$options->{init};
|
|
my $max_tries = 10;
|
|
|
|
# RX-Vx71's series models and older use a different command to return back to menu root
|
|
$back_cmd = "Back to Home" if(exists($hash->{MODEL}) and $hash->{MODEL} =~ /^(?:RX-A\d{1,2}10|RX-A\d{1,2}00|RX-V\d{1,2}(?:71|67|65))$/);
|
|
|
|
# RX-V2065/RX-V1067 don't support "Back to Home", just "Back" for one level up.
|
|
$back_cmd = "Back" if(exists($hash->{MODEL}) and $hash->{MODEL} =~ /^RX-V\d{1,2}(?:65|67)$/);
|
|
|
|
if($tries <= $max_tries)
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><List_Control><Cursor>$back_cmd</Cursor></List_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg);
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"GET\"><[CURRENT_INPUT_TAG]><List_Info>GetParam</List_Info></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg, {options => {init => $tries}});
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 3 ,"YAMAHA_AVR ($name) - unable to return to top menu after $max_tries tries to navigate to $arg";
|
|
}
|
|
|
|
readingsEndUpdate($hash, 1);
|
|
YAMAHA_AVR_HandleCmdQueue($queue_hash);
|
|
return;
|
|
}
|
|
|
|
if($menu_layer > @list_cmds)
|
|
{
|
|
# menu is still not browsed fully, but no more commands are left.
|
|
Log3 $name, 5 ,"YAMAHA_AVR ($name) - no more commands left to browse deeper into current menu.";
|
|
}
|
|
else # browse through the current item list
|
|
{
|
|
my $search = $list_cmds[($menu_layer - 1)];
|
|
|
|
if($current_list =~ /<Line_(\d+)><Txt>([^<]*$search[^<]*)<\/Txt><Attribute>(.+?)<\/Attribute>/)
|
|
{
|
|
my $last = ($3 eq "Item");
|
|
my $absolute_line_number = $1 + int($current_line / 8) * 8;
|
|
|
|
Log3 $name, 4 ,"YAMAHA_AVR ($name) - selecting menu item \"$2\" (line item: $1, absolute number: $absolute_line_number)";
|
|
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><List_Control><Jump_Line>$absolute_line_number</Jump_Line></List_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg);
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><List_Control><Direct_Sel>Line_$1</Direct_Sel></List_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg);
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"GET\"><[CURRENT_INPUT_TAG]><List_Info>GetParam</List_Info></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg, {options => {last_layer => $menu_layer, item_selected => 1, last_menu_item => $last, not_before => gettimeofday()+1}});
|
|
}
|
|
else
|
|
{
|
|
if(($current_line + 8) < $max_line)
|
|
{
|
|
#request next page
|
|
Log3 $name, 4 ,"YAMAHA_AVR ($name) - request next page of menu (current line: $current_line, max lines: $max_line)";
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><[CURRENT_INPUT_TAG]><List_Control><Page>Down</Page></List_Control></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg);
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"GET\"><[CURRENT_INPUT_TAG]><List_Info>GetParam</List_Info></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg, {options => {not_before => gettimeofday()+1}});
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 3 ,"YAMAHA_AVR ($name) - no more pages left on menu to find item $search in $menu_name. aborting menu browsing";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# list must be checked again in 1 second.
|
|
Log3 $name, 4 ,"YAMAHA_AVR ($name) - menu is busy. retrying in 1 second";
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"GET\"><[CURRENT_INPUT_TAG]><List_Info>GetParam</List_Info></[CURRENT_INPUT_TAG]></YAMAHA_AV>", $cmd, $arg, {options => {not_before => (gettimeofday()+1), last_layer => $menu_layer, at_first => 1}});
|
|
}
|
|
}
|
|
}
|
|
elsif($cmd eq "input")
|
|
{
|
|
# schedule an immediate status request right before the next command to ensure the correct presence of $hash->{helper}{CURRENT_INPUT_TAG} for the next command
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Basic_Status>GetParam</Basic_Status></$zone></YAMAHA_AV>", "statusRequest", "basicStatus", {options => {priority => 1, at_first => 1}});
|
|
}
|
|
elsif($cmd eq "volume" and $data =~ /RC="0"/)
|
|
{
|
|
my $current_volume = $arg;
|
|
my $target_volume = $options->{volume_target};
|
|
my $diff = $options->{volume_diff};
|
|
|
|
# DSP based models use "Vol" instead of "Volume"
|
|
my $volume_cmd = (_isModel_DSP($hash) ? "Vol" : "Volume");
|
|
|
|
my $zone = YAMAHA_AVR_getParamName($hash, $hash->{ACTIVE_ZONE}, $hash->{helper}{ZONES});
|
|
|
|
readingsBulkUpdate($hash, "volumeStraight", $current_volume);
|
|
readingsBulkUpdate($hash, "volume", YAMAHA_AVR_volume_abs2rel($current_volume));
|
|
|
|
if(not $current_volume == $target_volume)
|
|
{
|
|
if($diff == 0 or (abs($current_volume - $target_volume) < abs($diff)))
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - set volume to ".$target_volume." dB (target is $target_volume dB)";
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Lvl><Val>".($target_volume*10)."</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></$volume_cmd></$zone></YAMAHA_AV>", "volume", $target_volume, {options => {volume_diff => $diff, at_first => 1, priority => 1, volume_target => $target_volume}});
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - set volume to ".($current_volume + $diff)." dB (target is $target_volume dB)";
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><$zone><$volume_cmd><Lvl><Val>".(($current_volume + $diff)*10)."</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></$volume_cmd></$zone></YAMAHA_AV>", "volume", ($current_volume + $diff), {options => {volume_diff => $diff, at_first => 1, priority => 1, volume_target => $target_volume}});
|
|
}
|
|
}
|
|
else
|
|
{
|
|
# volume change finished, requesting overall status
|
|
YAMAHA_AVR_GetStatus($hash, 1)
|
|
}
|
|
}
|
|
elsif(($cmd eq "tunerFrequency" or $cmd eq "tunerPreset") and $data =~ /RC="0"/)
|
|
{
|
|
# get new tunerFrequency status if current input != Tuner
|
|
unless(exists($hash->{helper}{CURRENT_INPUT_TAG}) and $hash->{helper}{CURRENT_INPUT_TAG} eq "Tuner")
|
|
{
|
|
YAMAHA_AVR_SendCommand($hash,"<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Info>GetParam</Play_Info></Tuner></YAMAHA_AV>", "statusRequest", "tunerFrequency");
|
|
}
|
|
}
|
|
|
|
readingsEndUpdate($hash, 1);
|
|
|
|
YAMAHA_AVR_GetStatus($hash, 1) unless($cmd =~ /^statusRequest|navigateListMenu|volume|input|tuner.+$/);
|
|
}
|
|
|
|
YAMAHA_AVR_HandleCmdQueue($queue_hash);
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# Converts all Values to FHEM usable command lists
|
|
sub YAMAHA_AVR_Param2Fhem #($$)
|
|
{
|
|
my $param = shift // return;
|
|
my $replace_pipes = shift;
|
|
|
|
$param =~ s/\s+//g;
|
|
$param =~ s/,//g;
|
|
$param =~ s/_//g;
|
|
$param =~ s/\(/_/g;
|
|
$param =~ s/\)//g;
|
|
$param =~ s/\|/,/g if $replace_pipes;
|
|
|
|
return lc $param;
|
|
}
|
|
|
|
#############################
|
|
# Returns the Yamaha Parameter Name for the FHEM like aquivalents
|
|
sub YAMAHA_AVR_getParamName #($$$)
|
|
{
|
|
my $hash = shift // return;
|
|
my $name = shift // return;
|
|
my $list = shift // return;
|
|
|
|
my @commands = split("\\|", $list);
|
|
|
|
for my $item (@commands)
|
|
{
|
|
if(YAMAHA_AVR_Param2Fhem($item, 0) eq $name)
|
|
{
|
|
return $item;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# queries the receiver model, system-id, version and all available zones
|
|
sub YAMAHA_AVR_getModel #($)
|
|
{
|
|
my $hash = shift // return;
|
|
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Config>GetParam</Config></System></YAMAHA_AV>", "statusRequest","systemConfig", {options => {at_first => 1, priority => 1}});
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Unit_Desc>GetParam</Unit_Desc></System></YAMAHA_AV>", "statusRequest","unitDescription", {options => {at_first => 1, priority => 1}});
|
|
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# parses the HTTP response for unit description XML file
|
|
sub
|
|
YAMAHA_AVR_ParseXML #($$$)
|
|
{
|
|
my $param = shift // return;
|
|
my $err = shift // return;
|
|
my $data = shift // return;
|
|
|
|
my $hash = $param->{hash};
|
|
my $name = $hash->{NAME};
|
|
|
|
Log3 $name, 3, "YAMAHA_AVR ($name) - could not get unit description. Please turn on the device or check for correct hostaddress!" if($err ne "" and defined($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 1);
|
|
|
|
$hash->{helper}{RUNNING_REQUEST} = 0;
|
|
delete($hash->{helper}{".HTTP_CONNECTION"}) unless($param->{keepalive});
|
|
|
|
if($data eq '')
|
|
{
|
|
YAMAHA_AVR_HandleCmdQueue($hash);
|
|
return;
|
|
}
|
|
|
|
delete($hash->{helper}{ZONES}) if(exists($hash->{helper}{ZONES}));
|
|
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - checking available zones";
|
|
|
|
while($data =~ /<Menu Func="Subunit" Title_1="(.+?)" YNC_Tag="(.+?)">/gc)
|
|
{
|
|
if(defined($hash->{helper}{ZONES}) and length($hash->{helper}{ZONES}) > 0)
|
|
{
|
|
$hash->{helper}{ZONES} .= "|";
|
|
}
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - adding zone: $2";
|
|
$hash->{helper}{ZONES} .= $2;
|
|
}
|
|
|
|
delete( $hash->{helper}{DSP_MODES}) if(exists($hash->{helper}{DSP_MODES}));
|
|
|
|
if($data =~ /<Menu Func_Ex="Surround" Title_1="Surround">.*?<Get>(.+?)<\/Get>/)
|
|
{
|
|
my $modes = $1;
|
|
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - found DSP modes in XML";
|
|
|
|
while($modes =~ /<Direct.*?>(.+?)<\/Direct>/gc)
|
|
{
|
|
if(defined($hash->{helper}{DSP_MODES}) and length($hash->{helper}{DSP_MODES}) > 0)
|
|
{
|
|
$hash->{helper}{DSP_MODES} .= "|";
|
|
}
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - adding DSP mode $1";
|
|
$hash->{helper}{DSP_MODES} .= $1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - no DSP modes found in XML";
|
|
# DSP-Z based series does not offer DSP modes in unit description
|
|
if(_isModel_DSP($hash))
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - using static DSP mode list für DSP-Z based models";
|
|
$hash->{helper}{DSP_MODES} = "Hall in Munich|".
|
|
"Hall in Vienna|".
|
|
"Hall in Amsterdam|".
|
|
"Church in Freiburg|".
|
|
"Chamber|".
|
|
"Village Vanguard|".
|
|
"Warehouse Loft|".
|
|
"Cellar Club|".
|
|
"The Roxy Theatre|".
|
|
"The Bottom Line|".
|
|
"Sports|".
|
|
"Action Game|".
|
|
"Roleplaying Game|".
|
|
"Music Video|".
|
|
"Recital/Opera|".
|
|
"Standard|".
|
|
"Spectacle|".
|
|
"Sci-Fi|".
|
|
"Adventure|".
|
|
"Drama|".
|
|
"Mono Movie|".
|
|
"2ch Stereo|".
|
|
"7ch Stereo|".
|
|
"Straight Enhancer|".
|
|
"7ch Enhancer|".
|
|
"Surround Decoder";
|
|
|
|
} # RX-Vx67's based series does not offer DSP modes in unit description
|
|
elsif($hash->{MODEL} =~ /^RX-(?:A\d{1,2}00|V\d{1,2}67)$/)
|
|
{
|
|
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - using static DSP mode list for RX-Vx67-based models";
|
|
$hash->{helper}{DSP_MODES} = "Hall in Munich|".
|
|
"Hall in Vienna|".
|
|
"Hall in Amsterdam|".
|
|
"Church in Freiburg|".
|
|
"Church in Royaumont|".
|
|
"Chamber|".
|
|
"Village Vanguard|".
|
|
"Warehouse Loft|".
|
|
"Cellar Club|".
|
|
"The Roxy Theatre|".
|
|
"The Bottom Line|".
|
|
"Sports|".
|
|
"Action Game|".
|
|
"Roleplaying Game|".
|
|
"Music Video|".
|
|
"Recital/Opera|".
|
|
"Standard|".
|
|
"Spectacle|".
|
|
"Sci-Fi|".
|
|
"Adventure|".
|
|
"Drama|".
|
|
"Mono Movie|".
|
|
"2ch Stereo|".
|
|
"7ch Stereo|".
|
|
"Surround Decoder";
|
|
}
|
|
}
|
|
|
|
|
|
# check for hdmi output command
|
|
$hash->{helper}{SUPPORT_HDMI_OUT} = ($data =~ /<Menu Func_Ex="HDMI_Out" Title_1="HDMI OUT">/ ? 1 : 0);
|
|
|
|
# check for DAB support
|
|
$hash->{helper}{SUPPORT_DAB} = ($data =~ /<Menu Func="Source_Device" Func_Ex="[^"]+" YNC_Tag="DAB">/ ? 1 : 0);
|
|
|
|
# uncomment line for zone detection testing
|
|
#
|
|
#$hash->{helper}{ZONES} .= "|Zone_2";
|
|
|
|
$hash->{ZONES_AVAILABLE} = YAMAHA_AVR_Param2Fhem($hash->{helper}{ZONES}, 1);
|
|
|
|
# if explicitly given in the define command, set the desired zone
|
|
if(defined(YAMAHA_AVR_getParamName($hash, lc $hash->{helper}{SELECTED_ZONE}, $hash->{helper}{ZONES})))
|
|
{
|
|
Log3 $name, 4, "YAMAHA_AVR ($name) - using ".YAMAHA_AVR_getParamName($hash, lc $hash->{helper}{SELECTED_ZONE}, $hash->{helper}{ZONES})." as active zone";
|
|
$hash->{ACTIVE_ZONE} = lc $hash->{helper}{SELECTED_ZONE};
|
|
}
|
|
else
|
|
{
|
|
Log3 $name, 2, "YAMAHA_AVR ($name) - selected zone >>".$hash->{helper}{SELECTED_ZONE}."<< is not available. Using Main Zone instead";
|
|
$hash->{ACTIVE_ZONE} = "mainzone";
|
|
}
|
|
|
|
# create device pointer
|
|
$modules{YAMAHA_AVR}{defptr}{$hash->{SYSTEM_ID}}{$hash->{ACTIVE_ZONE}} = $hash if(exists($hash->{SYSTEM_ID}) and exists($hash->{ACTIVE_ZONE}));
|
|
|
|
YAMAHA_AVR_HandleCmdQueue($hash);
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# converts decibal volume in percentage volume (-80.5 .. 16.5dB => 0 .. 100%)
|
|
sub YAMAHA_AVR_volume_rel2abs #($)
|
|
{
|
|
my $percentage = shift;
|
|
|
|
# 0 - 100% -equals 80.5 to 16.5 dB
|
|
return int((($percentage / 100 * 97) - 80.5) / 0.5) * 0.5;
|
|
}
|
|
|
|
#############################
|
|
# converts percentage volume in decibel volume (0 .. 100% => -80.5 .. 16.5dB)
|
|
sub YAMAHA_AVR_volume_abs2rel #($)
|
|
{
|
|
my $absolute = shift // return;
|
|
|
|
# -80.5 to 16.5 dB equals 0 - 100%
|
|
return int(($absolute + 80.5) / 97 * 100);
|
|
}
|
|
|
|
#############################
|
|
# queries all available inputs and scenes
|
|
sub YAMAHA_AVR_getInputs #($)
|
|
{
|
|
my $hash = shift // return;
|
|
my $name = $hash->{NAME};
|
|
my $address = $hash->{helper}{ADDRESS};
|
|
|
|
my $zone = YAMAHA_AVR_getParamName($hash, $hash->{ACTIVE_ZONE}, $hash->{helper}{ZONES});
|
|
|
|
return if !defined $zone || $zone eq '';
|
|
|
|
# query all inputs
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Input><Input_Sel_Item>GetParam</Input_Sel_Item></Input></$zone></YAMAHA_AV>", "statusRequest","getInputs", {options => {at_first => 1, priority => 1}});
|
|
|
|
# query all available scenes (only in mainzone available)
|
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Scene><Scene_Sel_Item>GetParam</Scene_Sel_Item></Scene></$zone></YAMAHA_AV>", "statusRequest","getScenes", {options => {can_fail => 1, at_first => 1, priority => 1}}) if $hash->{ACTIVE_ZONE} eq 'mainzone';
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
# Restarts the internal status request timer according to the given interval or current receiver state
|
|
sub YAMAHA_AVR_ResetTimer #($;$)
|
|
{
|
|
my $hash = shift // return;
|
|
my $interval = shift;
|
|
my $name = $hash->{NAME};
|
|
|
|
RemoveInternalTimer($hash, \&YAMAHA_AVR_GetStatus);
|
|
|
|
return if IsDisabled($name);
|
|
if ( defined $interval )
|
|
{
|
|
return InternalTimer(gettimeofday()+$interval, \&YAMAHA_AVR_GetStatus, $hash);
|
|
}
|
|
if ( ReadingsVal($name, 'presence', 'absent') eq 'present' && ReadingsVal($name, 'power', 'off') eq 'on' )
|
|
{
|
|
return InternalTimer(gettimeofday()+$hash->{helper}{ON_INTERVAL}, \&YAMAHA_AVR_GetStatus, $hash);
|
|
}
|
|
return InternalTimer(gettimeofday()+$hash->{helper}{OFF_INTERVAL}, \&YAMAHA_AVR_GetStatus, $hash);
|
|
}
|
|
|
|
#############################
|
|
# convert all HTML entities into UTF-8 aquivalents
|
|
sub _html2txt #($)
|
|
{
|
|
my $string = shift // return '';
|
|
|
|
$string =~ s/&/&/g;
|
|
$string =~ s/&/&/g;
|
|
$string =~ s/ / /g;
|
|
$string =~ s/'/'/g;
|
|
|
|
$string = decode('UTF-8', $string);
|
|
|
|
$string =~ s/(\xe4|ä)/\xc3\xa4/g;
|
|
$string =~ s/(\xc4|Ä)/\xc3\x84/g;
|
|
$string =~ s/(\xf6|ö)/\xc3\xb6/g;
|
|
$string =~ s/(\xd6|Ö)/\xc3\x96/g;
|
|
$string =~ s/(\xfc|ü)/\xc3\xbc/g;
|
|
$string =~ s/(\xdc|Ü)/\xc3\x9c/g;
|
|
$string =~ s/(\xdf|ß)/\xc3\x9f/g;
|
|
|
|
$string =~ s/<[^>]+>//g;
|
|
|
|
$string =~ s/>/>/g;
|
|
$string =~ s/</</g;
|
|
|
|
$string =~ s/(^\s+|\s+$)//g;
|
|
|
|
return $string;
|
|
}
|
|
|
|
sub _generateSurroundDecoderList #($)
|
|
{
|
|
my $hash = shift // return;
|
|
|
|
if ( defined $hash->{MODEL} )
|
|
{
|
|
if($hash->{MODEL} =~ /^(?:RX-V[67]79|RX-A750|RX-AS710D?)$/) # RX-V679, RX-V779, RX-A750, RX-AS710, RX-AS710D (from RX-Vx79/RX-Ax50 series)
|
|
{
|
|
$hash->{helper}{SURROUND_DECODERS} = "Dolby PLII Movie|Dolby PLII Music|Dolby PLII Game|Dolby PLIIx Movie|Dolby PLIIx Music|Dolby PLIIx Game|DTS NEO:6 Cinema|DTS NEO:6 Music";
|
|
}
|
|
elsif($hash->{MODEL} =~ /^(?:RX-A850|RX-A[123]050|CX-A5100)$/) # RX-A850, RX-A1050, RX-A2050, RX-A3050, CX-A5100 (from RX-Vx79/RX-Ax50 series)
|
|
{
|
|
$hash->{helper}{SURROUND_DECODERS} = "Dolby PLII Movie|Dolby PLII Music|Dolby PLII Game|Dolby PLIIx Movie|Dolby PLIIx Music|Dolby PLIIx Game|Dolby Surround|DTS Neural:X|DTS NEO:6 Cinema|DTS NEO:6 Music";
|
|
}
|
|
elsif($hash->{MODEL} =~ /^RX-(?:V\d{1,2}81|A\d{1,2}60)$/) # RX-Ax60/Vx81 series
|
|
{
|
|
$hash->{helper}{SURROUND_DECODERS} = "Dolby Surround|DTS Neural:X|DTS NEO:6 Cinema|DTS NEO:6 Music"
|
|
}
|
|
else # all other/older models
|
|
{
|
|
$hash->{helper}{SURROUND_DECODERS} = "Dolby PL|Dolby PLII Movie|Dolby PLII Music|Dolby PLII Game|Dolby PLIIx Movie|Dolby PLIIx Music|Dolby PLIIx Game|DTS NEO:6 Cinema|DTS NEO:6 Music";
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
#############################
|
|
# Check if amp is one of these models: DSP-Z7, DSP-Z9, DSP-Z11, RX-Z7, RX-Z9, RX-Z11, RX-V2065, RX-V3900, DSP-AX3900
|
|
# Tested models: DSP-Z7
|
|
sub _isModel_DSP #($)
|
|
{
|
|
my $hash = shift // return;
|
|
|
|
if(exists($hash->{MODEL}) && (($hash->{MODEL} =~ /DSP-Z/) || ($hash->{MODEL} =~ /RX-Z/) || ($hash->{MODEL} =~ /RX-V2065/) || ($hash->{MODEL} =~ /RX-V3900/) || ($hash->{MODEL} =~ /DSP-AX3900/)))
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
sub _Log3Demand {
|
|
my $hash = shift // return 0;
|
|
my $lvl = shift // 3;
|
|
|
|
my $lcllvl = AttrVal($hash->{NAME}, 'verbose', undef);
|
|
return $lcllvl <= $lvl if defined $lcllvl;
|
|
return $lvl <= AttrVal('global', 'verbose', 0);
|
|
}
|
|
|
|
1;
|
|
|
|
__END__
|
|
|
|
=pod
|
|
|
|
=encoding utf8
|
|
=item device
|
|
=item summary controls Yamaha AV receivers via LAN connection
|
|
=item summary_DE steuert Yamaha AV-Receiver über die LAN-Verbindung
|
|
=begin html
|
|
|
|
<a id="YAMAHA_AVR"></a>
|
|
<h3>YAMAHA_AVR</h3>
|
|
<ul>
|
|
<a id="YAMAHA_AVR-define"></a>
|
|
<h4>Define</h4>
|
|
<ul>
|
|
<code>
|
|
define <name> YAMAHA_AVR <ip-address> [<zone>] [<status_interval>]
|
|
<br><br>
|
|
define <name> YAMAHA_AVR <ip-address> [<zone>] [<off_status_interval>] [<on_status_interval>]
|
|
</code>
|
|
<br><br>
|
|
This module controls AV receiver from Yamaha via network connection. You are able
|
|
to power your AV reveiver on and off, query it's power state,
|
|
select the input (HDMI, AV, AirPlay, internet radio, Tuner, ...), select the volume
|
|
or mute/unmute the volume.<br><br>
|
|
Defining a YAMAHA_AVR device will schedule an internal task (interval can be set
|
|
with optional parameter <status_interval> in seconds, if not set, the value is 30
|
|
seconds), which periodically reads the status of the AV receiver (power state, selected
|
|
input, volume and mute status) and triggers notify/filelog commands.
|
|
<br><br>
|
|
Different status update intervals depending on the power state can be given also.
|
|
If two intervals are given in the define statement, the first interval statement stands for the status update
|
|
interval in seconds in case the device is off, absent or any other non-normal state. The second
|
|
interval statement is used when the device is on.
|
|
|
|
Example:<br><br>
|
|
<ul><code>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10
|
|
<br><br>
|
|
# With custom status interval of 60 seconds<br>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10 mainzone 60
|
|
<br><br>
|
|
# With custom "off"-interval of 60 seconds and "on"-interval of 10 seconds<br>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10 mainzone 60 10
|
|
</code></ul>
|
|
|
|
</ul>
|
|
<br><br>
|
|
<b>Zone Selection</b><br>
|
|
<ul>
|
|
If your receiver supports zone selection (e.g. RX-V671, RX-V673,... and the AVANTAGE series)
|
|
you can select the zone which should be controlled. The RX-V3xx and RX-V4xx series for example
|
|
just have a "Main Zone" (which is the whole receiver itself). In general you have the following
|
|
possibilities for the parameter <zone> (depending on your receiver model).<br><br>
|
|
<ul>
|
|
<li><b>mainzone</b> - this is the main zone (standard)</li>
|
|
<li><b>zone2</b> - The second zone (Zone 2)</li>
|
|
<li><b>zone3</b> - The third zone (Zone 3)</li>
|
|
<li><b>zone4</b> - The fourth zone (Zone 4)</li>
|
|
</ul>
|
|
<br>
|
|
Depending on your receiver model you have not all inputs available on these different zones.
|
|
The module just offers the real available inputs.
|
|
<br><br>
|
|
Example:
|
|
<br><br>
|
|
<ul><code>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10 # If no zone is specified, the "Main Zone" will be used.<br>
|
|
attr AV_Receiver YAMAHA_AVR room Livingroom<br>
|
|
<br>
|
|
# Define the second zone<br>
|
|
define AV_Receiver_Zone2 YAMAHA_AVR 192.168.0.10 zone2<br>
|
|
attr AV_Receiver_Zone2 room Bedroom
|
|
</code></ul><br><br>
|
|
For each Zone you will need an own YAMAHA_AVR device, which can be assigned to a different room.
|
|
Each zone can be controlled separatly from all other available zones.
|
|
<br><br>
|
|
</ul>
|
|
|
|
<a id="YAMAHA_AVR-set"></a>
|
|
<h4>Set</h4>
|
|
<ul>
|
|
<code>set <name> <command> [<parameter>]</code>
|
|
<br><br>
|
|
Currently, the following commands are defined; the available inputs are depending on the used receiver.
|
|
The module only offers the real available inputs and scenes. The following input commands are just an example and can differ.
|
|
<br><br>
|
|
<ul>
|
|
<a id="YAMAHA_AVR-set-on"></a>
|
|
<li><b>on</b> - powers on the device</li>
|
|
<a id="YAMAHA_AVR-set-off"></a>
|
|
<li><b>off</b> - shuts down the device </li>
|
|
<a id="YAMAHA_AVR-set-input"></a>
|
|
<li><b>input</b> hdm1,hdmX,... - selects the input channel (only the real available inputs were given)</li>
|
|
<a id="YAMAHA_AVR-set-scene"></a>
|
|
<li><b>scene</b> scene1,sceneX - select the scene</li>
|
|
<a id="YAMAHA_AVR-set-volume"></a>
|
|
<li><b>volume</b> 0...100 [direct] - set the volume level in percentage. If you use "direct" as second argument, no volume smoothing is used (if activated) for this volume change. In this case, the volume will be set immediatly.</li>
|
|
<a id="YAMAHA_AVR-set-volumeStraight"></a>
|
|
<li><b>volumeStraight</b> -80...15 [direct] - set the volume level in decibel. If you use "direct" as second argument, no volume smoothing is used (if activated) for this volume change. In this case, the volume will be set immediatly.</li>
|
|
<a id="YAMAHA_AVR-set-volupdown" data-pattern="volumeUp|volumeDown"></a>
|
|
<li><b>volumeUp</b> [0-100] [direct] - increases the volume level by 5% or the value of attribute <a href="#YAMAHA_AVR-attr-volumeSteps">volumeSteps</a> (optional the increasing level can be given as argument, which will be used instead). If you use "direct" as second argument, no volume smoothing is used (if activated) for this volume change. In this case, the volume will be set immediatly.</li>
|
|
<li><b>volumeDown</b> [0-100] [direct] - decreases the volume level by 5% or the value of attribute <a href="#YAMAHA_AVR-attr-volumeSteps">volumeSteps</a> (optional the decreasing level can be given as argument, which will be used instead). If you use "direct" as second argument, no volume smoothing is used (if activated) for this volume change. In this case, the volume will be set immediatly.</li>
|
|
<a id="YAMAHA_AVR-set-hdmiOut" data-pattern="hdmiOut."></a>
|
|
<li><b>hdmiOut1</b> on|off - controls the HDMI output 1</li>
|
|
<li><b>hdmiOut2</b> on|off - controls the HDMI output 2</li>
|
|
<a id="YAMAHA_AVR-set-mute"></a>
|
|
<li><b>mute</b> on|off|toggle - activates volume mute</li>
|
|
<a id="YAMAHA_AVR-set-basstreble" data-pattern="bass|treble"></a>
|
|
<li><b>bass</b> [-6...6] step 0.5 (main zone), [-10...10] step 2 (other zones), [-10...10] step 1 (other zones, DSP models) - set bass tone level in decibel</li>
|
|
<li><b>treble</b> [-6...6] step 0.5 (main zone), [-10...10] step 2 (other zones), [-10...10] step 1 (other zones, DSP models) - set treble tone level in decibel</li>
|
|
<a id="YAMAHA_AVR-set-dsp"></a>
|
|
<li><b>dsp</b> hallinmunich,hallinvienna,... - sets the DSP mode to the given preset</li>
|
|
<a id="YAMAHA_AVR-set-enhancer"></a>
|
|
<li><b>enhancer</b> on|off - controls the internal sound enhancer</li>
|
|
<a id="YAMAHA_AVR-set-3dCinemaDsp"></a>
|
|
<li><b>3dCinemaDsp</b> auto|off - controls the CINEMA DSP 3D mode</li>
|
|
<a id="YAMAHA_AVR-set-adaptiveDrc"></a>
|
|
<li><b>adaptiveDrc</b> auto|off - controls the Adaptive DRC</li>
|
|
<a id="YAMAHA_AVR-set-partyMode"></a>
|
|
<li><b>partyMode</b> on|off - controls the party mode. In Main Zone the whole party mode is enabled/disabled system wide. In each zone executed, it enables/disables the current zone from party mode.</li>
|
|
<a id="YAMAHA_AVR-set-navigateListMenu"></a>
|
|
<li><b>navigateListMenu</b> <item1>/<item2>/.../<itemN> - select a specific item within a menu structure. for menu-based inputs (e.g. Net Radio, USB, Server, ...) only. See chapter <a href="#YAMAHA_AVR-MenuNavigation">Automatic Menu Navigation</a> for further details and examples.</li>
|
|
<a id="YAMAHA_AVR-set-tunerFrequency"></a>
|
|
<li><b>tunerFrequency</b> <frequency> [AM|FM] - sets the tuner frequency. The first argument is the frequency, second parameter is optional to set the tuner band (AM or FM, default: FM). Depending which tuner band you select, the frequency is given in kHz (AM band) or MHz (FM band). If the second parameter is not set, the FM band will be used. This command can be used even the current input is not "tuner", the new frequency is set and will be played, when the tuner gets active next time.</li>
|
|
<a id="YAMAHA_AVR-set-tunerFrequencyBand"></a>
|
|
<li><b>tunerFrequencyBand</b> FM|DAB - controls the used tuner frequency band ("FM" for analog frequency modulation or "DAB" for digital audio broadcasting. Only available if device supports DAB. On devices using an analog tuner, the frequency band (AM/FM) can be changed via set command "tunerFrequency".</li>
|
|
<a id="YAMAHA_AVR-set-preset">data-pattern="preset.*"></a>
|
|
<li><b>preset</b> 1...40 - selects a saved preset of the currently selected input.</li>
|
|
<li><b>presetUp</b> - selects the next preset of the currently selected input.</li>
|
|
<li><b>presetDown</b> - selects the previous preset of the currently selected input.</li>
|
|
<a id="YAMAHA_AVR-set-straight"></a>
|
|
<li><b>straight</b> on|off - bypasses the internal codec converter and plays the original sound codec</li>
|
|
<a id="YAMAHA_AVR-set-direct"></a>
|
|
<li><b>direct</b> on|off - bypasses all internal sound enhancement features and plays the sound straight directly</li>
|
|
<a id="YAMAHA_AVR-set-sleep"></a>
|
|
<li><b>sleep</b> off,30min,60min,...,last - activates the internal sleep timer</li>
|
|
<a id="YAMAHA_AVR-set-shuffle"></a>
|
|
<li><b>shuffle</b> on,off - activates the shuffle mode on the current input</li>
|
|
<a id="YAMAHA_AVR-set-surroundDecoder"></a>
|
|
<li><b>surroundDecoder</b> dolbypl,... - set the surround decoder. Only the available decoders were given if the device supports the configuration of the surround decoder.</li>
|
|
<a id="YAMAHA_AVR-set-extraBass"></a>
|
|
<li><b>extraBass</b> off,auto - controls the extra bass. Only available if supported by the device.</li>
|
|
<a id="YAMAHA_AVR-set-ypaoVolume"></a>
|
|
<li><b>ypaoVolume</b> off,auto - controls the YPAO volume. Only available if supported by the device.</li>
|
|
<a id="YAMAHA_AVR-set-displayBrightness"></a>
|
|
<li><b>displayBrightness</b> -4...0 - controls brightness reduction of the front display. Only available if supported by the device.</li>
|
|
<a id="YAMAHA_AVR-set-repeat"></a>
|
|
<li><b>repeat</b> one,all,off - activates the repeat mode on the current input for one or all titles</li>
|
|
<a id="YAMAHA_AVR-set-pause"></a>
|
|
<li><b>pause</b> - pause playback on current input</li>
|
|
<a id="YAMAHA_AVR-set-play"></a>
|
|
<li><b>play</b> - start playback on current input</li>
|
|
<a id="YAMAHA_AVR-set-stop"></a>
|
|
<li><b>stop</b> - stop playback on current input</li>
|
|
<a id="YAMAHA_AVR-set-skip"></a>
|
|
<li><b>skip</b> reverse,forward - skip track on current input</li>
|
|
<a id="YAMAHA_AVR-set-statusRequest"></a>
|
|
<li><b>statusRequest</b> - requests the current status of the device</li>
|
|
<a id="YAMAHA_AVR-set-remoteControl"></a>
|
|
<li><b>remoteControl</b> up,down,... - sends remote control commands as listed below</li>
|
|
|
|
</ul>
|
|
</ul><br><br>
|
|
<u>Remote control (not in all zones available, depending on your model)</u><br><br>
|
|
<ul>
|
|
<u>Cursor Selection:</u><br><br>
|
|
<ul><code>
|
|
remoteControl up<br>
|
|
remoteControl down<br>
|
|
remoteControl left<br>
|
|
remoteControl right<br>
|
|
remoteControl enter<br>
|
|
remoteControl return<br>
|
|
</code></ul><br><br>
|
|
|
|
<u>Menu Selection:</u><br><br>
|
|
<ul><code>
|
|
remoteControl setup<br>
|
|
remoteControl option<br>
|
|
remoteControl display<br>
|
|
</code></ul><br><br>
|
|
|
|
<u>Tuner Control:</u><br><br>
|
|
<ul><code>
|
|
remoteControl tunerPresetUp<br>
|
|
remoteControl tunerPresetDown<br>
|
|
</code></ul><br><br>
|
|
|
|
The button names are the same as on your remote control.
|
|
</ul>
|
|
<br>
|
|
<a id="YAMAHA_AVR-MenuNavigation"></a>
|
|
<u>Automatic Menu Navigation (only for menu based inputs like Net Radio, Server, USB, ...)</u><br><br>
|
|
<ul>
|
|
For menu based inputs you have to select a specific item out of a complex menu structure to start playing music.
|
|
Mostly you want to start automatic playback for a specific internet radio (input: Net Radio) or similar, where you have to navigate through several menu and submenu items.
|
|
<br><br>
|
|
To automate such a complex menu navigation, you can use the set command "navigateListMenu".
|
|
As Parameter you give a menu path of the desired item you want to select.
|
|
YAMAHA_AVR will go through the menu and selects all menu items given as parameter from left to right.
|
|
All menu items are separated by a forward slash (/).
|
|
<br><br>
|
|
So here are some examples:
|
|
Receiver's current input is "netradio":<br><br>
|
|
<ul>
|
|
<code>
|
|
set <name> navigateListMenu Countries/Australia/All Stations/1Radio.FM<br>
|
|
set <name> navigateListMenu Bookmarks/Favorites/1LIVE</code>
|
|
</ul><br>
|
|
If you want to turn on your receiver and immediatly select a specific internet radio you may use:<br><br>
|
|
<ul>
|
|
<code>
|
|
set <name> on ; set <name> volume 20 direct ; set <name> input netradio ; set <name> navigateListMenu Bookmarks/Favorites/1LIVE<br><br>
|
|
# for regular execution to a specific time using the <a href="#at">at</a> module<br>
|
|
define turn_on_Radio_morning at *08:00 set <name> on ; set <name> volume 20 direct ; set <name> input netradio ; set <name> navigateListMenu Countries/Australia/All Stations/1Radio.FM<br><br>
|
|
define turn_on_Radio_evening at *17:00 set <name> on ; set <name> volume 20 direct ; set <name> input netradio ; set <name> navigateListMenu Bookmarks/Favorites/1LIVE</code>
|
|
</ul>
|
|
<br>
|
|
Receiver's current input is "server" (network DLNA shares):<br><br>
|
|
<ul>
|
|
<code>
|
|
set <name> navigateListMenu NAS/Music/Sort By Artist/Alicia Keys/Songs in A Minor/Fallin
|
|
</code>
|
|
</ul>
|
|
<br>
|
|
The exact menu structure depends on your own configuration and network devices who provide content.
|
|
Each menu item name has not to be provided fully. Each item name will be treated as keyword search. That means, if any menu item contains the given item name, it will be selected, for example:
|
|
<br><br>
|
|
<ul>
|
|
Your real menu path you want to select looks like this: <code> <i><b>Bookmarks</b></i> => <i><b>Favorites</b></i> => <i><b>foo:BAR 70's-90's [[HITS]]</b></i></code><br><br>
|
|
The last item has many non-word characters, that can cause you trouble in some situations. But you don't have to use the full name to select this entry.
|
|
It's enough to use a specific part of the item name, that only exists in this one particular item. So to select this item you can use for instance the following set command:<br><br>
|
|
<code>
|
|
set <name> navigateListMenu Bookmarks/Favorites/foo:BAR
|
|
</code>
|
|
<br><br>
|
|
This works, even without giving the full item name (<i><code>foo:BAR 70's-90's [[HITS]]</code></i>).
|
|
</ul>
|
|
<br>
|
|
This also allows you to pare down long item names to shorter versions.
|
|
The shorter version must be still unique enough to identify the right item.
|
|
The first item in the list (from top to bottom), that contains the given keyword, will be selected.
|
|
|
|
<br><br>
|
|
</ul>
|
|
<a id="YAMAHA_AVR-get"></a>
|
|
<h4>Get</h4>
|
|
<ul>
|
|
<code>get <name> <reading></code>
|
|
<br><br>
|
|
Currently, the get command only returns the reading values. For a specific list of possible values, see section "Generated Readings/Events".
|
|
<br><br>
|
|
</ul>
|
|
<a id="YAMAHA_AVR-attr"></a>
|
|
<b>Attributes</b>
|
|
<ul>
|
|
<li><a href="#do_not_notify">do_not_notify</a></li>
|
|
<li><a href="#disabledForIntervals">disabledForIntervals</a></li>
|
|
<li><a href="#readingFnAttributes">readingFnAttributes</a></li><br>
|
|
<a id="YAMAHA_AVR-attr-requestTimeout"></a><li>requestTimeout<br>
|
|
Optional attribute change the response timeout in seconds for all queries to the receiver.
|
|
<br><br>
|
|
Possible values: 1-5 seconds. Default value is 4 seconds.</li>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr-disable"></a><li>disable
|
|
Optional attribute to disable the internal cyclic status update of the receiver. Manual status updates via statusRequest command is still possible.
|
|
<br><br>
|
|
Possible values: 0 => perform cyclic status update, 1 => don't perform cyclic status updates.</li>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeSmoothChange"></a><li>volumeSmoothChange<br>
|
|
Optional attribute to activate a smooth volume change.
|
|
<br><br>
|
|
Possible values: 0 => off , 1 => on</li>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeSmoothSteps"></a><li>volumeSmoothSteps<br>
|
|
Optional attribute to define the number of volume changes between the current and the desired volume. Default value is 5 steps</li>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeSteps"></a><li>volumeSteps<br>
|
|
Optional attribute to define the default increasing and decreasing level for the volumeUp and volumeDown set command. Default value is 5%</li>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeMax"></a><li>volumeMax<br>
|
|
Optional attribute to set an upper limit in percentage for volume changes.
|
|
If the user tries to change the volume to a higher level than configured with this attribute, the volume will not exceed this limit.
|
|
<br><br>
|
|
Possible values: 0-100%. Default value is 100% (no limitation)</li><br><br>
|
|
</ul>
|
|
<a id="YAMAHA_AVR-readings"></a>
|
|
<h4>Generated Readings/Events:</h4>
|
|
<ul>
|
|
<li><b>3dCinemaDsp</b> - The status of the CINEMA DSP 3D mode (can be "auto" or "off")</li>
|
|
<li><b>adaptiveDrc</b> - The status of the Adaptive DRC (can be "auto" or "off")</li>
|
|
<li><b>bass</b> Reports the current bass tone level of the receiver or zone in decibel values (between -6 and 6 dB (mainzone) and -10 and 10 dB (other zones)</li>
|
|
<li><b>direct</b> - indicates if all sound enhancement features are bypassed or not ("on" => all features are bypassed, "off" => sound enhancement features are used).</li>
|
|
<li><b>dsp</b> - The current selected DSP mode for sound output</li>
|
|
<li><b>displayBrightness</b> - indicates the brightness reduction of the front display (-4 is the maximum reduction, 0 means no reduction; only available if supported by the device).</li>
|
|
<li><b>enhancer</b> - The status of the internal sound enhancer (can be "on" or "off")</li>
|
|
<li><b>extraBass</b> - The status of the extra bass (can be "auto" or "off", only available if supported by the device)</li>
|
|
<li><b>input</b> - The selected input source according to the FHEM input commands</li>
|
|
<li><b>inputName</b> - The input description as seen on the receiver display</li>
|
|
<li><b>hdmiOut1</b> - The status of the HDMI output 1 (can be "on" or "off")</li>
|
|
<li><b>hdmiOut2</b> - The status of the HDMI output 2 (can be "on" or "off")</li>
|
|
<li><b>mute</b> - Reports the mute status of the receiver or zone (can be "on" or "off")</li>
|
|
<li><b>newFirmware</b> - indicates if a firmware update is available (can be "available" or "unavailable"; only available for RX-Vx71, RX-Vx73, RX-Ax10 or RX-Ax20)</li>
|
|
<li><b>power</b> - Reports the power status of the receiver or zone (can be "on" or "off")</li>
|
|
<li><b>presence</b> - Reports the presence status of the receiver or zone (can be "absent" or "present"). In case of an absent device, it cannot be controlled via FHEM anymore.</li>
|
|
<li><b>partyMode</b> - indicates if the party mode is enabled/disabled for the whole device (in main zone) or if the current zone is enabled for party mode (other zones than main zone)</li>
|
|
<li><b>sleep</b> - indicates if the internal sleep timer is activated or not.</li>
|
|
<li><b>straight</b> - indicates if the internal sound codec converter is bypassed or not (can be "on" or "off")</li>
|
|
<li><b>state</b> - Reports the current power state and an absence of the device (can be "on", "off" or "absent")</li>
|
|
<li><b>surroundDecoder</b> - Reports the selected surround decoder in case of "Surround Decoder" is used as active DSP</li>
|
|
<li><b>tunerFrequency</b> - the current tuner frequency in kHz (AM band) or MHz (FM band)</li>
|
|
<li><b>tunerFrequencyBand</b> - the current tuner band (AM, FM or DAB if supported)</li>
|
|
<li><b>treble</b> Reports the current treble tone level of the receiver or zone in decibel values (between -6 and 6 dB (mainzone) and -10 and 10 dB (other zones)</li>
|
|
<li><b>volume</b> - Reports the current volume level of the receiver or zone in percentage values (between 0 and 100 %)</li>
|
|
<li><b>volumeStraight</b> - Reports the current volume level of the receiver or zone in decibel values (between -80.5 and +15.5 dB)</li>
|
|
<li><b>ypaoVolume</b> - The status of the YPAO valume (can be "auto" or "off", only available if supported by the device)</li>
|
|
<br><u>Input dependent Readings/Events:</u><br><br>
|
|
<li><b>currentChannel</b> - Number of the input channel (SIRIUS only)</li>
|
|
<li><b>currentStation</b> - Station name of the current radio station (available only on TUNER, HD RADIO, NET RADIO or PANDORA)</li>
|
|
<li><b>currentStationFrequency</b> - The tuner frequency of the current station (only available on Tuner or HD Radio)</li>
|
|
<li><b>currentAlbum</b> - Album name of the current song</li>
|
|
<li><b>currentArtist</b> - Artist name of the current song</li>
|
|
<li><b>currentTitle</b> - Title of the current song</li>
|
|
<li><b>playStatus</b> - indicates if the input plays music or not</li>
|
|
<li><b>shuffle</b> - indicates the shuffle status for the current input</li>
|
|
<li><b>repeat</b> - indicates the repeat status for the current input</li>
|
|
</ul>
|
|
<br>
|
|
<b>Implementator's note</b><br>
|
|
<ul>
|
|
The module is only usable if you activate "Network Standby" on your receiver. Otherwise it is not possible to communicate with the receiver when it is turned off.
|
|
</ul>
|
|
<br>
|
|
</ul>
|
|
|
|
|
|
=end html
|
|
=begin html_DE
|
|
|
|
<a id="YAMAHA_AVR"></a>
|
|
<h3>YAMAHA_AVR</h3>
|
|
<ul>
|
|
|
|
<a id="YAMAHA_AVR-define"></a>
|
|
<h4>Definition</h4>
|
|
<ul>
|
|
<code>define <name> YAMAHA_AVR <IP-Addresse> [<Zone>] [<Status_Interval>]
|
|
<br><br>
|
|
define <name> YAMAHA_AVR <IP-Addresse> [<Zone>] [<Off_Interval>] [<On_Interval>]
|
|
</code>
|
|
<br><br>
|
|
|
|
Dieses Modul steuert AV-Receiver des Herstellers Yamaha über die Netzwerkschnittstelle.
|
|
Es bietet die Möglichkeit den Receiver an-/auszuschalten, den Eingangskanal zu wählen,
|
|
die Lautstärke zu ändern, den Receiver "Stumm" zu schalten, sowie den aktuellen Status abzufragen.
|
|
<br><br>
|
|
Bei der Definition eines YAMAHA_AVR-Moduls wird eine interne Routine in Gang gesetzt, welche regelmäßig
|
|
(einstellbar durch den optionalen Parameter <code><Status_Interval></code>; falls nicht gesetzt ist der Standardwert 30 Sekunden)
|
|
den Status des Receivers abfragt und entsprechende Notify-/FileLog-Geräte triggert.
|
|
<br><br>
|
|
Sofern 2 Interval-Argumente übergeben werden, wird der erste Parameter <code><Off_Interval></code> genutzt
|
|
sofern der Receiver ausgeschaltet oder nicht erreichbar ist. Der zweiter Parameter <code><On_Interval></code>
|
|
wird verwendet, sofern der Receiver eingeschaltet ist.
|
|
<br><br>
|
|
Beispiel:<br><br>
|
|
<ul><code>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10
|
|
<br><br>
|
|
# Mit modifiziertem Status Interval (60 Sekunden)<br>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10 mainzone 60
|
|
<br><br>
|
|
# Mit gesetztem "Off"-Interval (60 Sekunden) und "On"-Interval (10 Sekunden)<br>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10 mainzone 60 10
|
|
</code></ul><br><br>
|
|
</ul>
|
|
<b>Zonenauswahl</b><br>
|
|
<ul>
|
|
Wenn der zu steuernde Receiver mehrere Zonen besitzt (z.B. RX-V671, RX-V673,... sowie die AVANTAGE Modellreihe)
|
|
kann die zu steuernde Zone explizit angegeben werden. Die Modellreihen RX-V3xx und RX-V4xx als Beispiel
|
|
haben nur eine Zone (Main Zone). Je nach Receiver-Modell stehen folgende Zonen zur Verfügung, welche mit
|
|
dem optionalen Parameter <Zone> angegeben werden können.<br><br>
|
|
<ul>
|
|
<li><b>mainzone</b> - Das ist die Hauptzone (Standard)</li>
|
|
<li><b>zone2</b> - Die zweite Zone (Zone 2)</li>
|
|
<li><b>zone3</b> - Die dritte Zone (Zone 3)</li>
|
|
<li><b>zone4</b> - Die vierte Zone (Zone 4)</li>
|
|
</ul>
|
|
<br>
|
|
Je nach Receiver-Modell stehen in den verschiedenen Zonen nicht immer alle Eingänge zur Verfügung.
|
|
Dieses Modul bietet nur die tatsächlich verfügbaren Eingänge an.
|
|
<br><br>
|
|
Beispiel:<br><br>
|
|
<ul><code>
|
|
define AV_Receiver YAMAHA_AVR 192.168.0.10 # Wenn keine Zone angegeben ist, wird<br>
|
|
attr AV_Receiver YAMAHA_AVR room Wohnzimmer # standardmäßig "mainzone" verwendet<br>
|
|
<br>
|
|
# Definition der zweiten Zone<br>
|
|
define AV_Receiver_Zone2 YAMAHA_AVR 192.168.0.10 zone2<br>
|
|
attr AV_Receiver_Zone2 room Schlafzimmer<br>
|
|
</code></ul><br><br>
|
|
Für jede Zone muss eine eigene YAMAHA_AVR Definition erzeugt werden, welche dann unterschiedlichen Räumen zugeordnet werden kann.
|
|
Jede Zone kann unabhängig von allen anderen Zonen (inkl. der Main Zone) gesteuert werden.
|
|
<br><br>
|
|
</ul>
|
|
|
|
<a id="YAMAHA_AVR-set"></a>
|
|
<h4>Set-Kommandos</h4>
|
|
<ul>
|
|
<code>set <Name> <Kommando> [<Parameter>]</code>
|
|
<br><br>
|
|
Aktuell werden folgende Kommandos unterstützt. Die verfügbaren Eingänge und Szenen können je nach Receiver-Modell variieren.
|
|
Die folgenden Eingänge stehen beispielhaft an einem RX-V473 Receiver zur Verfügung.
|
|
Aktuell stehen folgende Kommandos zur Verfügung.
|
|
<br><br>
|
|
<ul>
|
|
<a id="YAMAHA_AVR-set-on"></a>
|
|
<li><b>on</b> - Schaltet den Receiver ein</li>
|
|
<a id="YAMAHA_AVR-set-off"></a>
|
|
<li><b>off</b> - Schaltet den Receiver aus</li>
|
|
<a id="YAMAHA_AVR-set-dsp"></a>
|
|
<li><b>dsp</b> hallinmunich,hallinvienna,... - Aktiviert das entsprechende DSP Preset</li>
|
|
<a id="YAMAHA_AVR-set-enhancer"></a>
|
|
<li><b>enhancer</b> on,off - Aktiviert den Sound Enhancer für einen verbesserten Raumklang</li>
|
|
<a id="YAMAHA_AVR-set-3dCinemaDsp"></a>
|
|
<li><b>3dCinemaDsp</b> auto,off - Aktiviert den CINEMA DSP 3D Modus</li>
|
|
<a id="YAMAHA_AVR-set-adaptiveDrc"></a>
|
|
<li><b>adaptiveDrc</b> auto,off - Aktiviert Adaptive DRC</li>
|
|
<a id="YAMAHA_AVR-set-extraBass"></a>
|
|
<li><b>extraBass</b> auto,off - Aktiviert den Extra Bass</li>
|
|
<a id="YAMAHA_AVR-set-ypaoVolume"></a>
|
|
<li><b>ypaoVolume</b> auto,off - Aktiviert YPAO Lautstärke</li>
|
|
<a id="YAMAHA_AVR-set-displayBrightness"></a>
|
|
<li><b>displayBrightness</b> -4...0 - Steuert die Helligkeitsreduzierung des Front-Displays</li>
|
|
<a id="YAMAHA_AVR-set-partyMode"></a>
|
|
<li><b>partyMode</b> on|off - Aktiviert den Party Modus. In der Main Zone wird hierbei der Party Modus geräteweit aktiviert oder deaktiviert. In den anderen Zonen kann man damit die entsprechende Zone dem Party Modus zuschalten oder entziehen.</li>
|
|
<a id="YAMAHA_AVR-set-navigateListMenu"></a>
|
|
<li><b>navigateListMenu</b> [Element 1]/[Element 2]/.../[Element N] - Wählt ein spezifisches Element aus einer Menüstruktur aus. Nur verwendbar bei Menü-basierenden Eingängen (z.B. Net Radio, USB, Server, etc.). Siehe nachfolgendes Kapitel "<a href="#YAMAHA_AVR-MenuNavigation">Automatische Menü Navigation</a>" für weitere Details und Beispiele.</li>
|
|
<a id="YAMAHA_AVR-set-tunerFrequency"></a>
|
|
<li><b>tunerFrequency</b> [Frequenz] [AM|FM] - setzt die Radio-Frequenz. Das erste Argument ist die Frequenz, der zweite dient optional zu Angabe des Bandes (AM oder FM, standardmäßig FM). Abhängig davon, welches Band man benutzt, wird die Frequenz in kHz (AM-Band) oder MHz (FM-Band) angegeben. Wenn im zweiten Argument kein Band angegeben ist, wird standardmäßig das FM-Band benutzt. Dieser Befehl kann auch benutzt werden, wenn der aktuelle Eingang nicht "tuner" ist. Die neue Frequenz wird dennoch gesetzt und bei der nächsten Benutzung abgespielt.</li>
|
|
<a id="YAMAHA_AVR-set-tunerFrequencyBand"></a>
|
|
<li><b>tunerFrequencyBand</b> FM|DAB - setzt das zu nutzende Frequenzband bzw. Empfangstechnologie für den Radioempfang ("FM" f&uumLr analoge Frequenzmodulation oder "DAB" für digitalen Radioempfang). Nur verfügbar wenn DAB unterstüzt wird.</li>
|
|
<a id="YAMAHA_AVR-set-preset" data-pattern="preset.*"></a>
|
|
<li><b>preset</b> 1...40 - wählt ein gespeichertes Preset für den aktuellen Eingang aus.</li>
|
|
<li><b>presetUp</b> - wählt das nächste Preset für den aktuellen Eingang aus.</li>
|
|
<li><b>presetDown</b> - wählt das vorherige Preset für den aktuellen Eingang aus.</li>
|
|
<a id="YAMAHA_AVR-set-direct"></a>
|
|
<li><b>direct</b> on,off - Umgeht alle internen soundverbessernden Maßnahmen (Equalizer, Enhancer, Adaptive DRC,...) und gibt das Signal unverfälscht wieder</li>
|
|
<a id="YAMAHA_AVR-set-input"></a>
|
|
<li><b>input</b> hdmi1,hdmiX,... - Wählt den Eingangskanal (es werden nur die tatsächlich verfügbaren Eingänge angeboten)</li>
|
|
<a id="YAMAHA_AVR-set-hdmiOut" data-pattern="hdmiOut."></a>
|
|
<li><b>hdmiOut1</b> on,off - Aktiviert die Ausgabe via HDMI Ausgang 1</li>
|
|
<li><b>hdmiOut2</b> on,off - Aktiviert die Ausgabe via HDMI Ausgang 2</li>
|
|
<a id="YAMAHA_AVR-set-scene"></a>
|
|
<li><b>scene</b> scene1,sceneX - Wählt eine vorgefertigte Szene aus</li>
|
|
<a id="YAMAHA_AVR-set-surroundDecoder"></a>
|
|
<li><b>surroundDecoder</b> dolbypl,... - Setzt den Surround Decoder, welcher genutzt werden soll sofern der DSP Modus "Surround Decoder" aktiv ist.</li>
|
|
<a id="YAMAHA_AVR-set-volume" data-pattern="volume.*"></a>
|
|
<li><b>volume</b> 0...100 [direct] - Setzt die Lautstärke in Prozent (0 bis 100%). Wenn als zweites Argument "direct" gesetzt ist, wird keine weiche Lautstärkenanpassung durchgeführt (sofern aktiviert). Die Lautstärke wird in diesem Fall sofort gesetzt.</li>
|
|
<li><b>volumeStraight</b> -87...15 [direct] - Setzt die Lautstärke in Dezibel (-80.5 bis 15.5 dB) so wie sie am Receiver auch verwendet wird. Wenn als zweites Argument "direct" gesetzt ist, wird keine weiche Lautstärkenanpassung durchgeführt (sofern aktiviert). Die Lautstärke wird in diesem Fall sofort gesetzt.</li>
|
|
<li><b>volumeUp</b> [0...100] [direct] - Erhöht die Lautstärke um 5% oder entsprechend dem Attribut <a href="#YAMAHA_AVR_volumeSteps">volumeSteps</a> (optional kann der Wert auch als Argument angehangen werden, dieser hat dann Vorang). Wenn als zweites Argument "direct" gesetzt ist, wird keine weiche Lautstärkenanpassung durchgeführt (sofern aktiviert). Die Lautstärke wird in diesem Fall sofort gesetzt.</li>
|
|
<li><b>volumeDown</b> [0...100] [direct] - Veringert die Lautstärke um 5% oder entsprechend dem Attribut <a href="#YAMAHA_AVR_volumeSteps">volumeSteps</a> (optional kann der Wert auch als Argument angehangen werden, dieser hat dann Vorang). Wenn als zweites Argument "direct" gesetzt ist, wird keine weiche Lautstärkenanpassung durchgeführt (sofern aktiviert). Die Lautstärke wird in diesem Fall sofort gesetzt.</li>
|
|
<a id="YAMAHA_AVR-set-mute"></a>
|
|
<li><b>mute</b> on,off,toggle - Schaltet den Receiver stumm</li>
|
|
<a id="YAMAHA_AVR-set-basstreble" data-pattern="bass|treble"></a>
|
|
<li><b>bass</b> [-6...6] Schrittweite 0.5 (main zone), [-10...10] Schrittweite 2 (andere Zonen), [-10...10] Schrittweite 1 (andere Zonen, DSP Modelle) - Stellt die Tiefen in decibel ein</li>
|
|
<li><b>treble</b> [-6...6] Schrittweite 0.5 (main zone), [-10...10] Schrittweite 2 (andere Zonen), [-10...10] Schrittweite 1 (andere Zonen, DSP Modelle) - Stellt die Höhen in decibel ein</li>
|
|
<a id="YAMAHA_AVR-set-straight"></a>
|
|
<li><b>straight</b> on,off - Umgeht die interne Codec-Umwandlung und gibt den Original-Codec wieder.</li>
|
|
<a id="YAMAHA_AVR-set-sleep"></a>
|
|
<li><b>sleep</b> off,30min,60min,...,last - Aktiviert den internen Sleep-Timer zum automatischen Abschalten</li>
|
|
<a id="YAMAHA_AVR-set-shuffle"></a>
|
|
<li><b>shuffle</b> on,off - Aktiviert die Zufallswiedergabe des aktuellen Eingangs (ist nur eingangsabhängig verfügbar)</li>
|
|
<a id="YAMAHA_AVR-set-repeat"></a>
|
|
<li><b>repeat</b> one,all,off - Wiederholt den aktuellen (one) oder alle (all) Titel des aktuellen Eingangs (ist nur eingangsabhängig verfügbar)</li>
|
|
<a id="YAMAHA_AVR-set-pause"></a>
|
|
<li><b>pause</b> - Wiedergabe pausieren (ist nur eingangsabhängig verfügbar)</li>
|
|
<a id="YAMAHA_AVR-set-play"></a>
|
|
<li><b>play</b> - Wiedergabe starten (ist nur eingangsabhängig verfügbar)</li>
|
|
<a id="YAMAHA_AVR-set-stop"></a>
|
|
<li><b>stop</b> - Wiedergabe stoppen (ist nur eingangsabhängig verfügbar)</li>
|
|
<a id="YAMAHA_AVR-set-skip"></a>
|
|
<li><b>skip</b> reverse,forward - Aktuellen Titel überspringen (ist nur eingangsabhängig verfügbar)</li>
|
|
<a id="YAMAHA_AVR-set-statusRequest"></a>
|
|
<li><b>statusRequest</b> - Fragt den aktuell Status des Receivers ab</li>
|
|
<a id="YAMAHA_AVR-set-remoteControl"></a>
|
|
<li><b>remoteControl</b> up,down,... - Sendet Fernbedienungsbefehle wie im nächsten Abschnitt beschrieben</li>
|
|
</ul>
|
|
<br><br>
|
|
</ul>
|
|
<u>Fernbedienung (je nach Modell nicht in allen Zonen verfügbar)</u><br><br>
|
|
<ul>
|
|
<u>Cursor Steuerung:</u><br><br>
|
|
<ul><code>
|
|
remoteControl up<br>
|
|
remoteControl down<br>
|
|
remoteControl left<br>
|
|
remoteControl right<br>
|
|
remoteControl enter<br>
|
|
remoteControl return<br>
|
|
</code></ul><br><br>
|
|
|
|
<u>Menü Auswahl:</u><br><br>
|
|
<ul><code>
|
|
remoteControl setup<br>
|
|
remoteControl option<br>
|
|
remoteControl display<br>
|
|
</code></ul><br><br>
|
|
|
|
<u>Radio Steuerung:</u><br><br>
|
|
<ul><code>
|
|
remoteControl tunerPresetUp<br>
|
|
|
|
|
|
|
|
remoteControl tunerPresetDown<br>
|
|
</code></ul><br>
|
|
</ul>
|
|
<a id="YAMAHA_AVR-MenuNavigation"></a>
|
|
<u>Automatische Menü Navigation (nur für Menü-basierte Eingänge wie z.B. Net Radio, Server, USB, ...)</u><br><br>
|
|
<ul>
|
|
Für Menü-basierte Eingänge muss man einen bestimmten Eintrag aus einer komplexen Struktur auswählen um die Wiedergabe zu starten.
|
|
Ein typischer Fall ist das Abspielen von Internet-Radios (Eingang: Net Radio) oder ähnlichen, netzwerkbasierten Diensten.
|
|
Erst durch das Navigieren durch mehrere Menüs und Untermenüs selektiert man das gewünschte Element und die Wiedergabe beginnt.
|
|
<br><br>
|
|
Um diese Navigation durch verschiedene Menüstrukturen zu automatisieren, gibt es das Set-Kommando "navigateListMenu".
|
|
Als Parameter übergibt man den Pfad (ausgehend vom Beginn) zu dem gewünschtem Menüeintrag
|
|
YAMAHA_AVR wird diese Liste von links nach rechts abarbeiten und sich so durch das Menü hangeln.
|
|
Alle angegebenen Menüelemente sind dabei durch einen Schrägstrich (/) getrennt.
|
|
<br><br>
|
|
Ein paar Beispiele:
|
|
Aktueller Eingang ist "netradio":<br><br>
|
|
<ul>
|
|
<code>
|
|
set <name> navigateListMenu Länder/Ozeanien/Australien/Alle Sender/1Radio.FM<br>
|
|
set <name> navigateListMenu Lesezeichen/Favoriten/1LIVE</code>
|
|
</ul><br>
|
|
Wenn man den Receiver mit einem Befehl anschalten möchte und einen bestimmten Internet-Radio Sender auswählen will:<br><br>
|
|
<ul>
|
|
<code>
|
|
set <name> on ; set <name> volume 20 direct ; set <name> input netradio ; set <name> navigateListMenu Lesezeichen/Favoriten/1LIVE<br><br>
|
|
# für tägliches einschalten eines Internet-Radios via <a href="#at">at-Modul</a><br>
|
|
define 1Radio_am_Morgen at *08:00 set <name> on ; set <name> volume 20 direct ; set <name> input netradio ; set <name> navigateListMenu Länder/Ozeanien/Australien/Alle Sender/1Radio.FM<br><br>
|
|
define 1LIVE_am_Abend at *17:00 set <name> on ; set <name> volume 20 direct ; set <name> input netradio ; set <name> navigateListMenu Lesezeichen/Favoriten/1LIVE</code>
|
|
</ul>
|
|
<br>
|
|
Aktueller Eingang ist "server" (Netzwerk-Freigaben via UPnP/DLNA):<br><br>
|
|
<ul>
|
|
<code>
|
|
set <name> navigateListMenu NAS/Musik/Nach Interpret/Alicia Keys/Songs in A Minor/Fallin
|
|
</code>
|
|
</ul>
|
|
<br>
|
|
Die exakte Menüstruktur hängt von ihrer eigenen Receiver-Konfiguration, sowie den zur Verfügung stehenden Freigaben in ihrem Netzwerk ab.
|
|
Jeder einzelne Menüeintrag muss nicht vollständig als Pfadelement angegeben werden.
|
|
Jedes Pfadelement wird als Stichwort verwendet um den richtigen Menüeintrag aus der aktuellen Listenebene zu finden, z.B:
|
|
<br><br>
|
|
<ul>
|
|
Der tatsächliche Menüpfad (wie im Display des Receiveres erkennbar) sieht beispielhaft folgendermaßen aus: <code> <i><b>Lesezeichen</b></i> => <i><b>Favoriten</b></i> => <i><b>foo:BAR 70'er-90'er [[HITS]]</b></i></code><br><br>
|
|
Der letzte Menüeintrag hat in diesem Fall viele Sonderzeichen die einem in einer FHEM-Konfiguration durchaus Probleme bereiten könen.
|
|
Man muss aber nicht die vollständige Bezeichnung in der Pfadangabe benutzen, sondern kann ein kürzeres Stichwort benutzen, was in der vollständigen Bezeichnung jedoch vorkommen muss.
|
|
So kann man beispielsweise folgendes Set-Kommando benutzen um diesen Eintrag auszuwählen und die Wiedergabe damit zu starten:<br><br>
|
|
<code>
|
|
set <name> navigateListMenu Lesezeichen/Favoriten/foo:BAR
|
|
</code>
|
|
<br><br>
|
|
Dieser Befehl funktioniert, obwohl man nicht die vollständige Bezeichnung angegeben hat (<i><code>foo:BAR 70's-90's [[HITS]]</code></i>).
|
|
</ul>
|
|
<br>
|
|
Auf selbe Weiße kann man somit lange Menüeinträge abkürzen, damit die Befehle nicht so lang werden.
|
|
Solche gekürzten Pfadangaben müssen aber trotzdem soweit eindeutig sein, damit sie nur auf das gewünschte Element passen.
|
|
Das erste Element aus einer Listenebene (von oben nach unten), was auf eine Pfadangabe passt, wird ausgewählt.
|
|
<br><br>
|
|
</ul>
|
|
<a id="YAMAHA_AVR-get"></a>
|
|
<h4>Get-Kommandos</h4>
|
|
<ul>
|
|
<code>get <Name> <Readingname></code>
|
|
<br><br>
|
|
Aktuell stehen via GET lediglich die Werte der Readings zur Verfügung. Eine genaue Auflistung aller möglichen Readings folgen unter "Generierte Readings/Events".
|
|
</ul>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr"></a>
|
|
<h4>Attribute</h4>
|
|
<ul>
|
|
|
|
<li><a href="#do_not_notify">do_not_notify</a></li>
|
|
<li><a href="#disabledForIntervals">disabledForIntervals</a></li>
|
|
<li><a href="#readingFnAttributes">readingFnAttributes</a></li><br>
|
|
<a id="YAMAHA_AVR-attr-requestTimeout"></a><li>requestTimeout<br>
|
|
Optionales Attribut. Maximale Dauer einer Anfrage in Sekunden zum Receiver.
|
|
<br><br>
|
|
Mögliche Werte: 1-5 Sekunden. Standardwert ist 4 Sekunden</li><br><br>
|
|
<a id="YAMAHA_AVR-attr-disable"></a><li>disable<br>
|
|
Optionales Attribut zur Deaktivierung des zyklischen Status-Updates. Ein manuelles Update via statusRequest-Befehl ist dennoch möglich.
|
|
<br><br>
|
|
Mögliche Werte: 0 => zyklische Status-Updates, 1 => keine zyklischen Status-Updates.</li><br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeSmoothChange"></a><li>volumeSmoothChange<br>
|
|
Optionales Attribut, welches einen weichen Lautstärkeübergang aktiviert
|
|
<br><br>
|
|
Mögliche Werte: 0 => deaktiviert , 1 => aktiviert</li><br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeSmoothSteps"></a><li>volumeSmoothSteps<br>
|
|
Optionales Attribut, welches angibt, wieviele Schritte zur weichen Lautstärkeanpassung
|
|
durchgeführt werden sollen. Standardwert ist 5 Anpassungschritte</li><br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeSteps"></a><li>volumeSteps<br>
|
|
Optionales Attribut, welches den Standardwert zur Lautstärkenerhöhung (volumeUp) und Lautstärkenveringerung (volumeDown) konfiguriert. Standardwert ist 5%</li>
|
|
<br><br>
|
|
<a id="YAMAHA_AVR-attr-volumeMax"></a><li>
|
|
volumeMax <br>
|
|
Optionales Attribut, welches eine maximale Obergrenze in Prozent für die Lautstärke festlegt.
|
|
Wird versucht die Lautstärke auf einen höheren Wert zu setzen, so wird die Lautstärke dennoch die konfigurierte Obergrenze nicht überschreiten.
|
|
<br><br>
|
|
Mögliche Werte: 0-100%. Standardwert ist 100% (keine Begrenzung)</li>
|
|
<br><br>
|
|
</ul>
|
|
|
|
<a id="YAMAHA_AVR-readings"></a>
|
|
<h4>Generierte Readings/Events:</h4>
|
|
<ul>
|
|
<li><b>3dCinemaDsp</b> - Der Status des CINEMA DSP 3D-Modus ("auto" => an, "off" => aus)</li>
|
|
<li><b>adaptiveDrc</b> - Der Status des Adaptive DRC ("auto" => an, "off" => aus)</li>
|
|
<li><b>bass</b> Der aktuelle Basspegel, zwischen -6 and 6 dB (main zone) and -10 and 10 dB (andere Zonen)</li>
|
|
<li><b>direct</b> - Zeigt an, ob soundverbessernde Features umgangen werden oder nicht ("on" => soundverbessernde Features werden umgangen, "off" => soundverbessernde Features werden benutzt)</li>
|
|
<li><b>displayBrightness</b> - Status der Helligkeitsreduzierung des Front-Displays (-4 => maximale Reduzierung, 0 => keine Reduzierung)</li>
|
|
<li><b>dsp</b> - Das aktuell aktive DSP Preset</li>
|
|
<li><b>enhancer</b> - Der Status des Enhancers ("on" => an, "off" => aus)</li>
|
|
<li><b>extraBass</b> - Der Status des Extra Bass ("auto" => an, "off" => aus)</li>
|
|
<li><b>input</b> - Der ausgewählte Eingang entsprechend dem FHEM-Kommando</li>
|
|
<li><b>inputName</b> - Die Eingangsbezeichnung, so wie sie am Receiver eingestellt wurde und auf dem Display erscheint</li>
|
|
<li><b>hdmiOut1</b> - Der Status des HDMI Ausgang 1 ("on" => an, "off" => aus)</li>
|
|
<li><b>hdmiOut2</b> - Der Status des HDMI Ausgang 2 ("on" => an, "off" => aus)</li>
|
|
<li><b>mute</b> - Der aktuelle Stumm-Status ("on" => Stumm, "off" => Laut)</li>
|
|
<li><b>newFirmware</b> - Zeigt an, ob eine neue Firmware zum installieren bereit liegt ("available" => neue Firmware verfügbar, "unavailable" => keine neue Firmware verfügbar; Event wird nur generiert für RX-Vx71, RX-Vx73, RX-Ax10 oder RX-Ax20)</li>
|
|
<li><b>power</b> - Der aktuelle Betriebsstatus ("on" => an, "off" => aus)</li>
|
|
<li><b>presence</b> - Die aktuelle Empfangsbereitschaft ("present" => empfangsbereit, "absent" => nicht empfangsbereit, z.B. Stromausfall)</li>
|
|
<li><b>partyMode</b> - Der Status des Party Modus ( "enabled" => aktiviert, "disabled" => deaktiviert). In der Main Zone stellt dies den geräteweiten Zustand des Party Modus dar. In den einzelnen Zonen zeigt es an, ob die jeweilige Zone für den Party Modus verwendet wird.</li>
|
|
<li><b>straight</b> - Zeigt an, ob die interne Codec Umwandlung umgangen wird oder nicht ("on" => Codec Umwandlung wird umgangen, "off" => Codec Umwandlung wird benutzt)</li>
|
|
<li><b>sleep</b> - Zeigt den Status des internen Sleep-Timers an</li>
|
|
<li><b>surroundDecoder</b> - Zeigt den aktuellen Surround Decoder an</li>
|
|
<li><b>state</b> - Der aktuelle Schaltzustand (power-Reading) oder die Abwesenheit des Gerätes (mögliche Werte: "on", "off" oder "absent")</li>
|
|
<li><b>tunerFrequency</b> - Die aktuelle Empfangsfrequenz für Radio-Empfang in kHz (AM-Band) oder MHz (FM-Band)</li>
|
|
<li><b>tunerFrequencyBand</b> - Das aktuell genutzte Radio-Band ("AM", "FM" oder "DAB" sofern unterstüzt)</li>
|
|
<li><b>treble</b> Der aktuelle Höhenpegel, zwischen -6 and 6 dB (main zone) and -10 and 10 dB (andere Zonen)</li>
|
|
<li><b>volume</b> - Der aktuelle Lautstärkepegel in Prozent (zwischen 0 und 100 %)</li>
|
|
<li><b>volumeStraight</b> - Der aktuelle Lautstärkepegel in Dezibel (zwischen -80.0 und +15 dB)</li>
|
|
<li><b>ypaoVolume</b> - Der Status der YPAO Lautstärke ("auto" => an, "off" => aus)</li>
|
|
<br><u>Eingangsabhängige Readings/Events:</u><br><br>
|
|
<li><b>currentChannel</b> - Nummer des Eingangskanals (nur bei SIRIUS)</li>
|
|
<li><b>currentStation</b> - Name des Radiosenders (nur bei TUNER, HD RADIO, NET RADIO oder PANDORA)</li>
|
|
<li><b>currentStationFrequency</b> - Die Sendefrequenz des aktuellen Radiosender (nur bei Tuner oder HD Radio)</li>
|
|
<li><b>currentAlbum</b> - Album es aktuell gespielten Titel</li>
|
|
<li><b>currentArtist</b> - Interpret des aktuell gespielten Titel</li>
|
|
<li><b>currentTitle</b> - Name des aktuell gespielten Titel</li>
|
|
<li><b>playStatus</b> - Wiedergabestatus des Eingangs</li>
|
|
<li><b>shuffle</b> - Status der Zufallswiedergabe des aktuellen Eingangs</li>
|
|
<li><b>repeat</b> - Status der Titelwiederholung des aktuellen Eingangs</li>
|
|
</ul>
|
|
<br>
|
|
<b>Hinweise des Autors</b>
|
|
<ul>
|
|
Dieses Modul ist nur nutzbar, wenn die Option "Network Standby" am Receiver aktiviert ist. Ansonsten ist die Steuerung nur im eingeschalteten Zustand möglich.
|
|
</ul>
|
|
<br>
|
|
</ul>
|
|
=end html_DE
|
|
|
|
=cut
|
|
|
|
=pod
|
|
perlcritic start
|
|
Total lines:
|
|
3274
|
|
Code lines:
|
|
2165
|
|
Comment lines:
|
|
162
|
|
Data lines:
|
|
1
|
|
Blank lines:
|
|
280
|
|
POD lines:
|
|
666
|
|
Total violations:
|
|
281
|
|
Severity 5:
|
|
43
|
|
Severity 4:
|
|
17
|
|
Severity 3:
|
|
221
|
|
Total subroutines:
|
|
28
|
|
Average McCabe:
|
|
26.96
|
|
=cut |