mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-07 23:09:26 +00:00
33fa579656
71_PIONEERAVRZONE.pm: Volume fix (was off by 1) - code cleanup: foreach -> for git-svn-id: https://svn.fhem.de/fhem/trunk@22807 2b470e98-0d58-463d-a4d8-8e2adae1ed80
869 lines
30 KiB
Perl
869 lines
30 KiB
Perl
# $Id$
|
|
##############################################################################
|
|
#
|
|
# 71_PIONEERAVRZONE.pm
|
|
#
|
|
# This file is part of Fhem.
|
|
#
|
|
# Fhem is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# Fhem is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Fhem. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
##############################################################################
|
|
|
|
package main;
|
|
|
|
use strict;
|
|
use warnings;
|
|
use Time::HiRes qw(gettimeofday);
|
|
use SetExtensions qw/ :all /;
|
|
|
|
sub PIONEERAVRZONE_Get;
|
|
sub PIONEERAVRZONE_Set;
|
|
sub PIONEERAVRZONE_Attr;
|
|
sub PIONEERAVRZONE_Define;
|
|
|
|
no if $] >= 5.017011, warnings => 'experimental::smartmatch';
|
|
|
|
###################################
|
|
sub PIONEERAVRZONE_Initialize {
|
|
my ($hash) = @_;
|
|
|
|
$hash->{Match} = ".+";
|
|
|
|
$hash->{GetFn} = "PIONEERAVRZONE_Get";
|
|
$hash->{SetFn} = "PIONEERAVRZONE_Set";
|
|
$hash->{DefFn} = "PIONEERAVRZONE_Define";
|
|
$hash->{ParseFn} = "PIONEERAVRZONE_Parse";
|
|
|
|
$hash->{AttrFn} = "PIONEERAVRZONE_Attr";
|
|
$hash->{AttrList} = "IODev " . $readingFnAttributes;
|
|
return;
|
|
}
|
|
|
|
###################################
|
|
sub PIONEERAVRZONE_Changed {
|
|
my ( $hash, $cmd, $value ) = @_;
|
|
|
|
readingsBeginUpdate($hash);
|
|
my $state = $cmd;
|
|
|
|
if ( defined($value) && $value ne "" ) {
|
|
readingsBulkUpdate( $hash, $cmd, $value );
|
|
$state .= " $value";
|
|
}
|
|
readingsBulkUpdate( $hash, "state", $state );
|
|
readingsEndUpdate( $hash, 1 );
|
|
my $name = $hash->{NAME};
|
|
Log3 $hash, 4, "PIONEERAVRZONE $name $state";
|
|
return $state;
|
|
}
|
|
|
|
###################################
|
|
|
|
sub PIONEERAVRZONE_Get {
|
|
my ( $hash, @a ) = @_;
|
|
|
|
my $name = $hash->{NAME};
|
|
my $zone = $hash->{helper}{ZONE};
|
|
my $expect = ".*";
|
|
return "get $name needs at least one argument" if ( int(@a) < 2 );
|
|
my $cmdName = $a[1];
|
|
|
|
my $IOhash = $hash->{IODev};
|
|
if ( $cmdName eq "input" ) {
|
|
}
|
|
elsif ( !defined( $IOhash->{helper}{GETS}{$zone}{$cmdName} ) ) {
|
|
my $gets = $IOhash->{helper}{GETS}{$zone};
|
|
return "$name error: unknown argument $cmdName, choose one of "
|
|
. ( join " ", sort keys %$gets );
|
|
}
|
|
|
|
my $cmd = $IOhash->{helper}{GETS}{$zone}{$cmdName};
|
|
|
|
my $v = IOWrite( $hash, $cmd );
|
|
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
sub PIONEERAVRZONE_Set {
|
|
my ( $hash, @a ) = @_;
|
|
my @args = @a;
|
|
shift @args;
|
|
shift @args;
|
|
my $name = $hash->{NAME};
|
|
my $type = $hash->{TYPE};
|
|
return "set $name needs at least one argument" if ( int(@a) < 2 );
|
|
my $cmd = $a[1];
|
|
|
|
my $IOhash = $hash->{IODev};
|
|
my $zone = $hash->{helper}{ZONE};
|
|
my $vmax = 0;
|
|
my $zahl = 0;
|
|
my $muteStr = "";
|
|
|
|
my @setsWithoutArg = (
|
|
"off", "toggle", "volumeUp", "volumeDown",
|
|
"muteOn", "muteOff", "muteToggle", "inputUp",
|
|
"inputDown"
|
|
);
|
|
|
|
Log3 $name, 5, "PIONEERAVRZONE $name: called function PIONEERAVR_Set($cmd)";
|
|
|
|
return "No Argument given" if ( !defined($cmd) );
|
|
|
|
my $inputNames = $IOhash->{helper}{INPUTNAMES};
|
|
|
|
# get all input names (preferable the aliasName) of the enabled inputs for the drop down list of "set <device> input xxx"
|
|
my @listInputNames = ();
|
|
for my $key ( keys %{ $IOhash->{helper}{INPUTNAMES} } ) {
|
|
if ( defined( $IOhash->{helper}{INPUTNAMES}->{$key}{enabled} ) ) {
|
|
if ( $IOhash->{helper}{INPUTNAMES}->{$key}{enabled} eq "1" ) {
|
|
if ( $IOhash->{helper}{INPUTNAMES}{$key}{aliasName} ) {
|
|
push( @listInputNames,
|
|
$IOhash->{helper}{INPUTNAMES}{$key}{aliasName} );
|
|
}
|
|
elsif ( $IOhash->{helper}{INPUTNAMES}{$key}{name} ) {
|
|
push( @listInputNames,
|
|
$IOhash->{helper}{INPUTNAMES}{$key}{name} );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( ( $zone eq "zone2" ) || ( $zone eq "zone3" ) ) {
|
|
$muteStr = " mute:on,off,toggle";
|
|
}
|
|
my $list =
|
|
"on:noArg off:noArg toggle:noArg input:"
|
|
. join( ',', sort @listInputNames )
|
|
. " inputUp:noArg inputDown:noArg"
|
|
. " volumeUp:noArg volumeDown:noArg"
|
|
. $muteStr
|
|
. " statusRequest:noArg volume:slider,0,1,100"
|
|
. " volumeStraight:slider,-80,1,"
|
|
. $vmax;
|
|
|
|
if ( $cmd eq "?" ) {
|
|
Log3 $name, 5, "PIONEERAVRZONE set $name " . $cmd;
|
|
return SetExtensions( $hash, $list, $name, $cmd, @args );
|
|
}
|
|
|
|
if ( @a == 2 ) {
|
|
Log3 $name, 5, "PIONEERAVRZONE $name: Set $cmd";
|
|
|
|
#### simple set commands without attributes
|
|
#### we just "translate" the human readable command to the PioneerAvr command
|
|
#### lookup in $IOhash->{helper}{SETS}{$zone} if the command exists and what to write to PioneerAvr
|
|
if ( $cmd ~~ @setsWithoutArg ) {
|
|
Log3 $name, 5, "PIONEERAVR $name: Set $cmd (setsWithoutArg)";
|
|
my $setCmd = $IOhash->{helper}{SETS}{$zone}{$cmd};
|
|
my $v = IOWrite( $hash, $setCmd );
|
|
Log3 $hash, 5,
|
|
"PIONEERAVR $name: Set_IOwrite($zone ... $cmd ): $setCmd";
|
|
return;
|
|
|
|
### Power on
|
|
### Command: PO
|
|
### according to "Elite & Pioneer FY14AVR IP & RS-232 7-31-13.xlsx" (notice) we need to send <cr> and
|
|
### wait 100ms before the first command is accepted by the Pioneer AVR
|
|
}
|
|
elsif ( $cmd eq "on" ) {
|
|
Log3 $name, 5, "PIONEERAVR $name: Set $cmd ";
|
|
my $setCmd = "";
|
|
IOWrite( $hash, $setCmd );
|
|
sleep(0.1);
|
|
|
|
if ( $zone eq "zone2" ) {
|
|
$setCmd = "APO";
|
|
}
|
|
elsif ( $zone eq "zone3" ) {
|
|
$setCmd = "BPO";
|
|
}
|
|
elsif ( $zone eq "hdZone" ) {
|
|
$setCmd = "ZEO";
|
|
}
|
|
IOWrite( $hash, $setCmd );
|
|
sleep(0.1);
|
|
Log3 $hash, 5, "PIONEERAVR $name: Set_IOwrite: $setCmd";
|
|
return;
|
|
|
|
# statusRequest: execute all "get" commands to update the readings
|
|
}
|
|
elsif ( $cmd eq "statusRequest" ) {
|
|
Log3 $name, 5, "PIONEERAVR $name: Set $cmd ";
|
|
for my $key ( keys %{ $IOhash->{helper}{GETS}{$zone} } ) {
|
|
IOWrite( $hash, $IOhash->{helper}{GETS}->{$zone}->{$key} );
|
|
}
|
|
return;
|
|
}
|
|
#### commands with argument(s)
|
|
}
|
|
elsif ( @a > 2 ) {
|
|
my $arg = $a[2];
|
|
####Input (all available Inputs of the Pioneer Avr -> see 'get $name loadInputNames')
|
|
####according to http://www.fhemwiki.de/wiki/DevelopmentGuidelinesAV
|
|
if ( $cmd eq "input" ) {
|
|
|
|
Log3 $name, 5, "PIONEERAVRZONE $name: set $cmd " . dq($arg);
|
|
for my $key ( keys %{ $IOhash->{helper}{INPUTNAMES} } ) {
|
|
if ( $IOhash->{helper}{INPUTNAMES}->{$key}{aliasName} eq $arg )
|
|
{
|
|
if ( $zone eq "zone2" ) {
|
|
IOWrite( $hash, sprintf "%02dZS", $key );
|
|
}
|
|
elsif ( $zone eq "zone3" ) {
|
|
IOWrite( $hash, sprintf "%02dZT", $key );
|
|
}
|
|
elsif ( $zone eq "hdZone" ) {
|
|
IOWrite( $hash, sprintf "%02dZEA", $key );
|
|
}
|
|
}
|
|
elsif ( $IOhash->{helper}{INPUTNAMES}->{$key}{name} eq $arg ) {
|
|
if ( $zone eq "zone2" ) {
|
|
IOWrite( $hash, sprintf "%02dZS", $key );
|
|
}
|
|
elsif ( $zone eq "zone3" ) {
|
|
IOWrite( $hash, sprintf "%02dZT", $key );
|
|
}
|
|
elsif ( $zone eq "hdZone" ) {
|
|
IOWrite( $hash, sprintf "%02dZEA", $key );
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
#####VolumeStraight (-80.5 - 12) in dB
|
|
####according to http://www.fhemwiki.de/wiki/DevelopmentGuidelinesAV
|
|
}
|
|
elsif ( $cmd eq "volumeStraight" ) {
|
|
$zahl = 80.5 + $arg;
|
|
if ( $zone eq "zone2" ) {
|
|
IOWrite( $hash, sprintf "%02dZV", $zahl );
|
|
}
|
|
elsif ( $zone eq "zone3" ) {
|
|
IOWrite( $hash, sprintf "%02dYV", $zahl );
|
|
}
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate( $hash, "volumeStraight", $arg );
|
|
readingsBulkUpdate( $hash, "volume", sprintf "%.0f",
|
|
( $a[2] + 80 ) / 0.81 );
|
|
readingsEndUpdate( $hash, 1 );
|
|
return;
|
|
####Volume (0 - 100) in %
|
|
####according to http://www.fhemwiki.de/wiki/DevelopmentGuidelinesAV
|
|
}
|
|
elsif ( $cmd eq "volume" ) {
|
|
$zahl = sprintf "%.0f", $arg * 0.81;
|
|
if ( $zone eq "zone2" ) {
|
|
IOWrite( $hash, sprintf "%02dZV", $zahl );
|
|
}
|
|
elsif ( $zone eq "zone3" ) {
|
|
IOWrite( $hash, sprintf "%02dYV", $zahl );
|
|
}
|
|
readingsBeginUpdate($hash);
|
|
readingsBulkUpdate( $hash, "volumeStraight", $zahl - 80 );
|
|
readingsBulkUpdate( $hash, "volume", sprintf "%.0f", $a[2] );
|
|
readingsEndUpdate( $hash, 1 );
|
|
return;
|
|
####Mute (on|off|toggle)
|
|
####according to http://www.fhemwiki.de/wiki/DevelopmentGuidelinesAV
|
|
}
|
|
elsif ( $cmd eq "mute" ) {
|
|
if ( $arg eq "on" ) {
|
|
IOWrite( $hash, $IOhash->{helper}{SETS}{$zone}{muteOn} );
|
|
readingsSingleUpdate( $hash, "mute", "on", 1 );
|
|
}
|
|
elsif ( $arg eq "off" ) {
|
|
IOWrite( $hash, $IOhash->{helper}{SETS}{$zone}{muteOff} );
|
|
readingsSingleUpdate( $hash, "mute", "off", 1 );
|
|
}
|
|
elsif ( $arg eq "toggle" ) {
|
|
IOWrite( $hash, $IOhash->{helper}{SETS}{$zone}{muteToggle} );
|
|
}
|
|
return;
|
|
}
|
|
else {
|
|
return SetExtensions( $hash, $list, $name, $cmd, @args );
|
|
}
|
|
}
|
|
else {
|
|
return SetExtensions( $hash, $list, $name, $cmd, @args );
|
|
}
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
sub PIONEERAVRZONE_Parse {
|
|
|
|
# we are called from dispatch() from the PIONEERAVR device
|
|
# we never come here if $msg does not match $hash->{MATCH} in the first place
|
|
# NOTE: we will update all matching readings for all (logical) devices, not just the first!
|
|
|
|
my ( $IOhash, $msg ) =
|
|
@_; # IOhash points to the PIONEERAVR, not to the PIONEERAVRZONE
|
|
|
|
my @matches;
|
|
my $name = $IOhash->{NAME};
|
|
my $state = '';
|
|
|
|
#Debug "Trying to find a match for \"" . escapeLogLine($msg) ."\"";
|
|
# walk over all clients
|
|
for my $d ( keys %defs ) {
|
|
my $hash = $defs{$d};
|
|
if ( $hash->{TYPE} eq "PIONEERAVRZONE" && $hash->{IODev} eq $IOhash ) {
|
|
my $zone = $hash->{helper}{ZONE};
|
|
readingsBeginUpdate($hash);
|
|
|
|
# zone2
|
|
if ( $zone eq "zone2" ) {
|
|
|
|
# volume zone2
|
|
# ZVXX
|
|
# XX 00 ... 81 -> -81dB ... 0dB
|
|
if ( $msg =~ m/^ZV(\d\d)$/ ) {
|
|
Log3 $name, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone2 - New volume = "
|
|
. $1
|
|
. " (raw volume data).";
|
|
readingsBulkUpdate( $hash, "volumeStraight", $1 - 81 );
|
|
readingsBulkUpdate( $hash, "volume", sprintf "%.0f",
|
|
$1 / 0.81 );
|
|
push @matches, $d;
|
|
|
|
# Mute zone2
|
|
# Z2MUTX
|
|
# X = 0: Mute on; X = 1: Mute off
|
|
}
|
|
elsif ( $msg =~ m/^Z2MUT(\d)$/ ) {
|
|
if ($1) {
|
|
readingsBulkUpdate( $hash, "mute", "off" );
|
|
Log3 $name, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone2 - Mute off.";
|
|
}
|
|
else {
|
|
readingsBulkUpdate( $hash, "mute", "on" );
|
|
Log3 $name, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone2 - Mute on.";
|
|
}
|
|
push @matches, $d;
|
|
|
|
# Input zone2
|
|
# Z2FXX
|
|
# XX -> input number 00 ... 49
|
|
}
|
|
elsif ( $msg =~ m/^Z2F(\d\d)$/ ) {
|
|
my $inputNr = $1;
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone2 - Input is set to inputNr: $inputNr ";
|
|
|
|
if ( $IOhash->{helper}{INPUTNAMES}->{$inputNr}{aliasName} ne
|
|
"" )
|
|
{
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone2 - Input aliasName for input $inputNr is "
|
|
. $IOhash->{helper}{INPUTNAMES}{$inputNr}{aliasName};
|
|
readingsBulkUpdate( $hash, "input",
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{aliasName}
|
|
);
|
|
}
|
|
elsif (
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{name} ne "" )
|
|
{
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone2 - Input Name for input $inputNr is "
|
|
. $IOhash->{helper}{INPUTNAMES}{$inputNr}{name};
|
|
readingsBulkUpdate( $hash, "input",
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{name} );
|
|
}
|
|
else {
|
|
readingsBulkUpdate( $hash, "input", $msg );
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone2 - InputName: can't find Name for input $inputNr";
|
|
}
|
|
push @matches, $d;
|
|
|
|
# Power zone2
|
|
# APRX
|
|
# X = 0: Power on; X = 1: Power off
|
|
}
|
|
elsif ( $msg =~ m/^APR(0|1)$/ ) {
|
|
if ( $1 eq '0' ) {
|
|
readingsBulkUpdate( $hash, "power", "on" );
|
|
$state = "on";
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone2 - Power: on";
|
|
}
|
|
elsif ( $1 eq '1' ) {
|
|
readingsBulkUpdate( $hash, "power", "off" );
|
|
$state = "off";
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone2 - Power: off";
|
|
}
|
|
|
|
# Set reading for state
|
|
#
|
|
if ( !defined( $hash->{READINGS}{state}{VAL} )
|
|
|| $hash->{READINGS}{state}{VAL} ne $state )
|
|
{
|
|
readingsBulkUpdate( $hash, "state", $state );
|
|
}
|
|
}
|
|
push @matches, $d;
|
|
|
|
# zone3
|
|
}
|
|
elsif ( $zone eq "zone3" ) {
|
|
|
|
# volume zone3
|
|
# YVXX
|
|
# XX 00 ... 81 -> -81dB ... 0dB
|
|
if ( $msg =~ m/^YV(\d\d)$/ ) {
|
|
Log3 $name, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone3 - New volume = "
|
|
. $1
|
|
. " (raw volume data).";
|
|
readingsBulkUpdate( $hash, "volumeStraight", $1 - 81 );
|
|
readingsBulkUpdate( $hash, "volume", sprintf "%.0f",
|
|
$1 / 0.81 );
|
|
push @matches, $d;
|
|
|
|
# Mute zone3
|
|
# Z3MUTX
|
|
# X = 0: Mute on; X = 1: Mute off
|
|
}
|
|
elsif ( $msg =~ m/^Z3MUT(\d)$/ ) {
|
|
if ($1) {
|
|
readingsBulkUpdate( $hash, "mute", "off" );
|
|
Log3 $name, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone3 - Mute off.";
|
|
}
|
|
else {
|
|
readingsBulkUpdate( $hash, "mute", "on" );
|
|
Log3 $name, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone3 - Mute on.";
|
|
}
|
|
push @matches, $d;
|
|
|
|
# Input zone3
|
|
# Z3FXX
|
|
# XX -> input number 00 ... 49
|
|
}
|
|
elsif ( $msg =~ m/^Z3F(\d\d)$/ ) {
|
|
my $inputNr = $1;
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone3 - Input is set to inputNr: $inputNr ";
|
|
if (
|
|
defined(
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{aliasName}
|
|
)
|
|
)
|
|
{
|
|
readingsBulkUpdate( $hash, "input",
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{aliasName}
|
|
);
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone3 - Input aliasName for input $inputNr is "
|
|
. $hash->{helper}{INPUTNAMES}{$inputNr}{aliasName};
|
|
}
|
|
elsif (
|
|
defined(
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{name}
|
|
)
|
|
)
|
|
{
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone3 - Input Name for input $inputNr is "
|
|
. $hash->{helper}{INPUTNAMES}{$inputNr}{name};
|
|
readingsBulkUpdate( $hash, "input",
|
|
$IOhash->{helper}{INPUTNAMES}->{$inputNr}{name} );
|
|
}
|
|
else {
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone3 - InputName: can't find Name for input $inputNr";
|
|
readingsBulkUpdate( $hash, "input", $msg );
|
|
}
|
|
push @matches, $d;
|
|
|
|
# Power zone3
|
|
# BPRX
|
|
# X = 0: Power on; X = 1: Power off
|
|
}
|
|
elsif ( $msg =~ m/^BPR(0|1)$/ ) {
|
|
if ( $1 eq '0' ) {
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone3 - Power: on";
|
|
readingsBulkUpdate( $hash, "power", "on" );
|
|
$state = "on";
|
|
}
|
|
elsif ( $1 eq '1' ) {
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: Zone3 - Power: off";
|
|
readingsBulkUpdate( $hash, "power", "off" );
|
|
$state = "off";
|
|
}
|
|
|
|
# Set reading for state
|
|
#
|
|
if ( !defined( $hash->{READINGS}{state}{VAL} )
|
|
|| $hash->{READINGS}{state}{VAL} ne $state )
|
|
{
|
|
readingsBulkUpdate( $hash, "state", $state );
|
|
}
|
|
push @matches, $d;
|
|
}
|
|
|
|
# hdZone
|
|
}
|
|
elsif ( $zone eq "hdZone" ) {
|
|
|
|
# Input hdZone
|
|
# ZEAXX
|
|
# XX -> input number 00 ... 49
|
|
if ( $msg =~ m/^ZEA(\d\d)$/ ) {
|
|
my $inputNr = $1;
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: hdZone - Input is set to inputNr: $inputNr ";
|
|
if (
|
|
defined(
|
|
$IOhash->{helper}{INPUTNAMES}->{$1}{aliasName}
|
|
)
|
|
)
|
|
{
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: hdZone - Input aliasName for input $inputNr is "
|
|
. $IOhash->{helper}{INPUTNAMES}{$inputNr}{aliasName};
|
|
readingsBulkUpdate( $hash, "input",
|
|
$IOhash->{helper}{INPUTNAMES}->{$1}{aliasName} );
|
|
}
|
|
elsif (
|
|
defined( $IOhash->{helper}{INPUTNAMES}->{$1}{name} ) )
|
|
{
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: hdZone - Input Name for input $inputNr is "
|
|
. $IOhash->{helper}{INPUTNAMES}{$inputNr}{name};
|
|
readingsBulkUpdate( $hash, "input",
|
|
$IOhash->{helper}{INPUTNAMES}->{$1}{name} );
|
|
}
|
|
else {
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: Zone3 - InputName: can't find Name for input $inputNr";
|
|
readingsBulkUpdate( $hash, "input", $msg );
|
|
}
|
|
push @matches, $d;
|
|
|
|
# Power hdZone
|
|
# ZEPX
|
|
# X = 0: Power on; X = 1: Power off
|
|
}
|
|
elsif ( $msg =~ m/^ZEP(0|1)$/ ) {
|
|
if ( $1 eq '0' ) {
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: hdZone - Power: on";
|
|
readingsBulkUpdate( $hash, "power", "on" );
|
|
$state = "on";
|
|
}
|
|
elsif ( $1 eq '1' ) {
|
|
Log3 $hash, 5,
|
|
"PIONEERAVRZONE $name: "
|
|
. dq($msg)
|
|
. " interpreted as: hdZone - Power: off";
|
|
readingsBulkUpdate( $hash, "power", "off" );
|
|
$state = "off";
|
|
}
|
|
|
|
# Set reading for state
|
|
#
|
|
if ( !defined( $hash->{READINGS}{state}{VAL} )
|
|
|| $hash->{READINGS}{state}{VAL} ne $state )
|
|
{
|
|
readingsBulkUpdate( $hash, "state", $state );
|
|
}
|
|
push @matches, $d;
|
|
}
|
|
}
|
|
readingsEndUpdate( $hash, 1 );
|
|
|
|
}
|
|
}
|
|
return @matches if (@matches);
|
|
return "UNDEFINED PIONEERAVRZONE message1 $msg";
|
|
}
|
|
|
|
#####################################
|
|
sub PIONEERAVRZONE_Attr {
|
|
|
|
my @a = @_;
|
|
my $hash = $defs{ $a[1] };
|
|
|
|
return;
|
|
}
|
|
|
|
#############################
|
|
sub PIONEERAVRZONE_Define {
|
|
my ( $hash, $def ) = @_;
|
|
my @a = split( "[ \t]+", $def );
|
|
|
|
return
|
|
"Usage: define <name> PIONEERAVRZONE <zone> ... wrong paramter count: "
|
|
. int(@a)
|
|
if ( int(@a) != 3 );
|
|
my $name = $a[0];
|
|
|
|
AssignIoPort($hash);
|
|
|
|
my $IOhash = $hash->{IODev};
|
|
if ( !defined($IOhash) ) {
|
|
my $err = "PIONEERAVRZONE $name error: no I/O device.";
|
|
Log3 $hash, 1, $err;
|
|
return $err;
|
|
}
|
|
|
|
#Parameter (Zone)
|
|
my $zone = "";
|
|
if ( $a[2] =~ m/^(zone\d|hdZone)$/ ) {
|
|
$zone = $a[2];
|
|
}
|
|
else {
|
|
my $err =
|
|
"PIONEERAVRZONE define $name error: unknown Zone "
|
|
. dq( $a[2] )
|
|
. " -> must be one of [zone2|zone3|hdZone] (I/O device is "
|
|
. $IOhash->{NAME}
|
|
. "). Usage: define <name> PIONEERAVRZONE <zone>";
|
|
Log3 $hash, 1, $err;
|
|
return $err;
|
|
}
|
|
|
|
# for autocreate: we store here a pointer of defined devices
|
|
# so we can check if the device exists
|
|
$modules{PIONEERAVRZONE}{defptr}{$zone} = $hash;
|
|
|
|
if ( !defined( $IOhash->{helper}{SETS}{$zone} ) ) {
|
|
my $err =
|
|
"PIONEERAVRZONE define $name error: unknown Zone $zone (I/O device is "
|
|
. $IOhash->{NAME} . ").";
|
|
Log3 $hash, 1, $err;
|
|
return $err;
|
|
}
|
|
|
|
$hash->{helper}{ZONE} = $zone;
|
|
|
|
# set default attributes
|
|
unless ( exists( $attr{$name}{webCmd} ) ) {
|
|
$attr{$name}{webCmd} = 'volume:mute:input';
|
|
}
|
|
unless ( exists( $attr{$name}{devStateIcon} ) ) {
|
|
$attr{$name}{devStateIcon} =
|
|
'on:rc_GREEN:off off:rc_STOP:on absent:rc_RED';
|
|
}
|
|
return;
|
|
}
|
|
#####################################
|
|
#Function to show special chars (e.g. \n\r) in logs
|
|
#sub
|
|
#dq($)
|
|
#{
|
|
# my ($s)= @_;
|
|
# $s= "<nothing>" unless(defined($s));
|
|
# return "\"" . escapeLogLine($s) . "\"";
|
|
#}
|
|
|
|
1;
|
|
|
|
=pod
|
|
=item device
|
|
=item summary control for the zones of a PIONEER AV receivers via network or serial connection
|
|
=item summary_DE Steuerung der Zonen eines PIONEER AV Receiver per Netzwerk oder seriell
|
|
=begin html
|
|
|
|
<a name="PIONEERAVRZONE"></a>
|
|
<h3>PIONEERAVRZONE</h3>
|
|
<ul>
|
|
<br>
|
|
<a name="PIONEERAVRZONEdefine"></a>
|
|
<b>Define</b>
|
|
<ul>
|
|
<code>define <name> PIONEERAVRZONE <zone> </code>
|
|
<br><br>
|
|
|
|
Defines a Zone (zone2, zone3 or hdZone) of a PioneerAVR device.<br>
|
|
Note: devices to control zone2, zone3 and/or HD-zone are autocreated on reception of the first message for those zones.<br><br>
|
|
|
|
Normally, the PIONEERAVRZONE device is attached to the latest previously defined PIONEERAVR device
|
|
for I/O. Use the <code>IODev</code> attribute of the PIONEERAVRZONE device to attach to any
|
|
PIONEERAVR device, e.g. <code>attr myPioneerAvrZone2 IODev myPioneerAvr</code>.
|
|
<br><br>
|
|
|
|
Examples:
|
|
<ul>
|
|
<code>define myPioneerAvrZone2 PIONEERAVRZONE zone2</code><br>
|
|
<code>attr myPioneerAvrZone2 IODev myPIONEERAVR</code>
|
|
</ul>
|
|
<br>
|
|
</ul>
|
|
|
|
<a name="PIONEERAVRZONEset"></a>
|
|
<b>Set</b>
|
|
<ul>
|
|
<code>set <name> <what> [<value>]</code>
|
|
<br><br>
|
|
where <what> is one of
|
|
<li>reopen</li>
|
|
<li>off <br>put zone into standby</li>
|
|
<li>on <br>turn zone on from standby</li>
|
|
<li>toggle <br>toggles zone power</li>
|
|
<li>volume <0 ... 100><br>zone volume in % of the maximum volume</li>
|
|
<li>volumeUp<br>increases the zone volume by 0.5dB</li>
|
|
<li>volumeDown<br>decreases the zone volume by 0.5dB</li>
|
|
<li>volumeStraight<-80.5 ... 12><br>same values for zone volume as shown on the display of the Pioneer AV receiver</li>
|
|
<li>mute <on|off|toggle></li>
|
|
<li>input <not on the Pioneer hardware deactivated input><br>the list of possible (i.e. not deactivated)
|
|
inputs is read in during Fhem start and with <code>get <name> statusRequest</code></li>
|
|
<li>inputUp<br>change zone input to next input</li>
|
|
<li>inputDown<br>change zone input to previous input</li>
|
|
<li><a href="#setExtensions">set extensions</a> are supported (except <code><name></code>)</li>
|
|
<br><br>
|
|
Example:
|
|
<ul>
|
|
<code>set VSX923Zone2 on</code><br>
|
|
</ul>
|
|
<br><br>
|
|
</ul>
|
|
<a name="PIONEERAVRZONEget"></a>
|
|
<b>Get</b>
|
|
<ul>
|
|
<li><code>get <name> input</code>
|
|
<br><br>
|
|
Update the reading for the zone input
|
|
</li>
|
|
</ul>
|
|
<br><br>
|
|
|
|
<a name="PIONEERAVRattr"></a>
|
|
<b>Attributes</b>
|
|
<br><br>
|
|
<ul>
|
|
<li>IOdev Name of the device which communicates with the phisical Pioneer AV receiver via ethernet or rs232</li>
|
|
<li><a href="#verbose">verbose</a></li>
|
|
</ul>
|
|
<br><br>
|
|
</ul>
|
|
|
|
=end html
|
|
=begin html_DE
|
|
|
|
<a name="PIONEERAVRZONE"></a>
|
|
<h3>PIONEERAVRZONE</h3>
|
|
<ul>
|
|
<br>
|
|
<a name="PIONEERAVRZONEdefine"></a>
|
|
<b>Define</b>
|
|
<ul>
|
|
<code>define <name> PIONEERAVRZONE <zone> </code>
|
|
<br><br>
|
|
|
|
Definiert ein PioneerAVR device für eine Zone Zone (zone2, zone3 or hdZone).<p>
|
|
|
|
Im Allgemeinen verwendet das logische device PIONEERAVRZONE das zuletzt definierte PIONEERAVR device für die Kommunikation mit dem Pioneer AV Receiver.
|
|
Mit dem Atribut <code>IODev</code> kann das PIONEERAVRZONE device jedes PIONEERAVR device zur Kommunikation verwenden,
|
|
z.B. <code>attr myPioneerAvrZone2 IODev myPioneerAvr</code>.
|
|
<br><br>
|
|
|
|
Examples:
|
|
<ul>
|
|
<code>define myPioneerAvrZone2 PIONEERAVRZONE zone2</code><br>
|
|
<code>attr myPioneerAvrZone2 IODev myPIONEERAVR</code>
|
|
</ul>
|
|
<br>
|
|
</ul>
|
|
|
|
<a name="PIONEERAVRZONEset"></a>
|
|
<b>Set</b>
|
|
<ul>
|
|
<code>set <name> <was> [<value>]</code>
|
|
<br><br>
|
|
wobei <was> eines der folgenden Befehle sein kann:
|
|
<li>reopen</li>
|
|
<li>off <br>Zone in den Standby-Modus schalten</li>
|
|
<li>on <br>Zone aus dem Standby-Modus Einschalten</li>
|
|
<li>toggle <br>Zone Ein/Ausschalten</li>
|
|
<li>volume <0 ... 100><br>Zonenlautstärke in % der maximalen Lautstärke</li>
|
|
<li>volumeUp<br>Zonenlautstärke um 0.5dB erhöhen</li>
|
|
<li>volumeDown<br>Zonenlautstärke um 0.5dB verringern</li>
|
|
<li>volumeStraight<-80.5 ... 12><br>Einstellen der Zonenlautstärke mit einem Wert, wie er am Display des Pioneer AV Receiver angezeigt wird</li>
|
|
<li>mute <on|off|toggle></li>
|
|
<li>input <nicht am Pioneer AV Receiver deaktivierte Eingangsquelle><br> Die Liste der verfügbaren (also der nicht deaktivierten)
|
|
Eingangsquellen wird beim Start von Fhem und auch mit <code>get <name> statusRequest</code> eingelesen</li>
|
|
<li>inputUp<br>nächste Eingangsquelle für die Zone auswählen</li>
|
|
<li>inputDown<br>vorherige Eingangsquelle für die Zone auswählen</li>
|
|
<li><a href="#setExtensions">set extensions</a> (ausser <code><name></code>) werden unterstützt</li>
|
|
|
|
|
|
<br><br>
|
|
Beispiel:
|
|
<ul>
|
|
<code>set VSX923Zone2 on</code><br>
|
|
</ul>
|
|
<br><br>
|
|
</ul>
|
|
<a name="PIONEERAVRZONEget"></a>
|
|
<b>Get</b>
|
|
<ul>
|
|
<li><code>get <name> input</code>
|
|
<br><br>
|
|
reading für die Eingangsquelle aktualisieren
|
|
</li>
|
|
</ul>
|
|
<br><br>
|
|
|
|
<a name="PIONEERAVRattr"></a>
|
|
<b>Attributes</b>
|
|
<br><br>
|
|
<ul>
|
|
<li>IOdev Name des device welches die Kommunikation mit dem Pioneer AV Receiver zur Verfügung stellt</li>
|
|
<li><a href="#verbose">verbose</a></li>
|
|
</ul>
|
|
<br><br>
|
|
</ul>
|
|
|
|
=end html_DE
|
|
=cut
|