diff --git a/fhem/FHEM/71_YAMAHA_AVR.pm b/fhem/FHEM/71_YAMAHA_AVR.pm new file mode 100755 index 000000000..c903195c9 --- /dev/null +++ b/fhem/FHEM/71_YAMAHA_AVR.pm @@ -0,0 +1,344 @@ +# +# Module: YAMAHA_AVR +# +# 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. +# +# Currently supported are: power (on|off) +# input (hdmi1|hdmi2|...) +# volume (-50 ... 10) +# mute (on|off) +# +# Of course there are more possibilities than these 4 commands. +# But in my oppinion these are the most relevant usecases within FHEM. +# +# For more commands, please email me. +# +# Written by Notausstieg (Notausstieg0309[at]googlemail[dot]com) +# +# 29.10.2012 +# +################################### + +package main; + +use strict; +use warnings; +#use Time::HiRes qw(gettimeofday); + + +sub YAMAHA_AVR_Get($@); +sub YAMAHA_AVR_Define($$); +sub YAMAHA_AVR_GetStatus($); + + + + +################################### +sub +YAMAHA_AVR_Initialize($) +{ + my ($hash) = @_; + + $hash->{GetFn} = "YAMAHA_AVR_Get"; + $hash->{SetFn} = "YAMAHA_AVR_Set"; + $hash->{DefFn} = "YAMAHA_AVR_Define"; + $hash->{UndefFn} = "YAMAHA_AVR_Undefine"; + + $hash->{AttrList} = "loglevel:0,1,2,3,4,5 subType event-on-update-reading event-on-change-reading"; +} + +################################### +sub +YAMAHA_AVR_GetStatus($) +{ + my ($hash) = @_; + my $name = $hash->{NAME}; + my $power; + + return "" if(!defined($hash->{ADDRESS}) or !defined($hash->{INTERVAL})); + + my $device = $hash->{ADDRESS}; + my $return = SendCommand($device,"GetParam"); + + + return "Can't submit command. please see fhem logfile for further information" if(not defined($return) or length($return) == 0); + + readingsBeginUpdate($hash); + + if($return =~ /(.+)<\/Power>/) + { + $power = $1; + readingsUpdate($hash, "power", lc($power)); + if($power eq "Standby") + { + $power = "Off"; + } + + $hash->{STATE} = lc($power); + + } + if($return =~ /(.+)<\/Val>(.+)<\/Exp>.+<\/Unit><\/Lvl>(.+)<\/Mute><\/Volume>/) + { + readingsUpdate($hash, "volume_level", ($1 / 10 ** $2)); + readingsUpdate($hash, "mute", lc($3)); + } + + if($return =~ /(.+)<\/Input_Sel>/) + { + readingsUpdate($hash, "input", lc($1)); + } + + readingsEndUpdate($hash, 1); + + InternalTimer(gettimeofday()+$hash->{INTERVAL}, "YAMAHA_AVR_GetStatus", $hash, 1); + + Log GetLogLevel($name,4), "YAMAHA_AVR $name: $hash->{STATE}"; + + return $hash->{STATE}; +} + +################################### +sub +YAMAHA_AVR_Get($@) +{ + my ($hash, @a) = @_; + my $what; + + return "argument is missing" if(int(@a) != 2); + $what = $a[1]; + + + if($what =~ /^(power|input|volume|mute)$/) + { + YAMAHA_AVR_GetStatus($hash); + if(defined($hash->{READINGS}{$what})) + { + return $a[0]." ".$what." => ".$hash->{READINGS}{$what}{VAL}; + } + else + { + return "no such reading: $what"; + } + } + else + { + return "Unknown argument $what, choose one of param power input volume mute get"; + } +} + + +################################### +sub +YAMAHA_AVR_Set($@) +{ + my ($hash, @a) = @_; + my $name = $hash->{NAME}; + my $address = $hash->{ADDRESS}; + my $result = ""; + my $inputs_piped = $hash->{INPUTS}; + + return "No Argument given" if(!defined($a[1])); + + my $what = $a[1]; + my $usage = "Unknown argument $what, choose one of on off volume:slider,-80,1,16 input:".$hash->{INPUTS}." mute:on,off statusRequest"; + + readingsBeginUpdate($hash); + if($what eq "on") + { + $result = SendCommand($address, "On"); + if($result =~ /RC="0"/ and $result =~ /<\/Power>/) + { + # As the receiver startup takes about 5 seconds, the status will be already set, if the return code of the command is 0. + readingsUpdate($hash, "power", "on"); + $hash->{STATE} = "on"; + return undef; + } + } + elsif($what eq "off") + { + SendCommand($address, "Standby"); + } + elsif($what eq "input") + { + if(defined($a[2])) + { + if($hash->{STATE} eq "on") + { + $inputs_piped =~ s/,/|/g; + + if($a[2] =~ /^($inputs_piped)$/) + { + if($a[2] eq "netradio") + { + $result = SendCommand($address,"NET RADIO"); + } + elsif($a[2] eq "airplay") + { + $result = SendCommand($address,"AirPlay"); + } + else + { + $result = SendCommand($address,"".uc($a[2]).""); + } + + if(not $result =~ /RC="0"/) + { + # if the returncode isn't 0, than the command was not successful + return "Could not set input to ".$a[2].". Please use only available inputs on your specific receiver"; + } + } + else + { + return $usage; + } + } + else + { + return "input can only be used when device is powered on"; + } + } + } + elsif($what eq "mute") + { + if(defined($a[2])) + { + if($hash->{STATE} eq "on") + { + if( $a[2] eq "on") + { + SendCommand($address, "On"); + } + elsif($a[2] eq "off") + { + SendCommand($address, "Off"); + + } + else + { + return $usage; + } + } + else + { + return "mute can only used when device is powered on"; + } + } + } + elsif($what eq "volume") + { + if(defined($a[2]) && $a[2] >= -80 && $a[2] < 16) + { + if($hash->{STATE} eq "on") + { + SendCommand($address,"".($a[2]*10)."1dB"); + } + else + { + return "volume can only be used when device is powered on"; + } + } + } + elsif($what eq "statusRequest") + { + # Will be executed on the end of this function anyway, so no need to call it specificly + } + else + { + return $usage; + } + readingsEndUpdate($hash, 1); + + YAMAHA_AVR_GetStatus($hash); + return undef; + +} + + +############################# +sub +YAMAHA_AVR_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $name = $hash->{NAME}; + my @inputs; + + if(! @a >= 3) + { + my $msg = "wrong syntax: define YAMAHA_AVR []"; + Log 2, $msg; + return $msg; + } + + + my $address = $a[2]; + + my $response = GetFileFromURL("http://".$address."/YamahaRemoteControl/desc.xml"); + if($response =~ //) + { + $hash->{MODEL} = $1; + } + + $hash->{ADDRESS} = $address; + + $response = SendCommand($address, "GetParam"); + $response =~ s/>\n(.+?)<\/Param>/ and not $1 =~ /iPod/) + { + if(defined($hash->{INPUTS}) and length($hash->{INPUTS}) > 0) + { + $hash->{INPUTS} .= ","; + } + if($1 eq "NET RADIO") + { + $hash->{INPUTS} .= "netradio"; + } + else + { + $hash->{INPUTS} .= lc($1); + } + } + } + + + if(defined($a[3]) and $a[3] > 0) + { + $hash->{INTERVAL}=$a[3]; + } + else + { + $hash->{INTERVAL}=30; + } + + InternalTimer(gettimeofday()+2, "YAMAHA_AVR_GetStatus", $hash, 0); + + return undef; +} + +############################# +sub +SendCommand($$) +{ + my($address, $command) = @_; + + # In case any URL changes must be made, this part is separated in this function". + return GetFileFromURL("http://".$address."/YamahaRemoteControl/ctrl", 10, "".$command); +} + +############################# +sub +YAMAHA_AVR_Undefine($$) +{ + my($hash, $name) = @_; + RemoveInternalTimer($hash); + return undef; +} + +1; diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index cd90e109c..5813ac432 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -136,7 +136,7 @@ SISPM   SIS_PMS   SML   - STV   + STV   TCM   TellStick   TRX   @@ -158,6 +158,7 @@ WS3600   X10   xxLG7000   + YAMAHA_AVR   ZWDongle   ZWave   @@ -10100,6 +10101,91 @@ KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.
You need to define an RFXtrx433
+ +

YAMAHA_AVR

+
    + + + Define +
      + define <name> YAMAHA_AVR <ip-address> [<status_interval>] +

      + + 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.

      + 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 60 seconds), which periodically reads + the status of the AV receiver (power state, selected input, volume and mute status) + and triggers notify/filelog commands.

      + + Example: +
        + define AV_Receiver YAMAHA_AVR 192.168.0.10
        +
      + + Set +
        + set <name> <command> [<parameter>] +

        + Currently, the following commands are defined; the available inputs are depending on the used receiver. + The module only offers the real available inputs. The following input commands are just an example and can differ. + +
        on
        +off
        +input hdmi1
        +input hdmi2
        +input hdmi3
        +input hdmi4
        +input av1
        +input av2
        +input av3
        +input av3
        +input av4
        +input av5
        +input av6
        +input usb
        +input airplay
        +input tuner
        +input v-aux
        +input audio
        +input server
        +volume -80..16	(volume between -80 and +16 dB)
        +mute on
        +mute off
        +
      + + + Get +
        + get <name> <what> +

        + Currently, the following commands are defined and return the current state of the receiver. +
        power
        +input 
        +mute 
        +volume
        +
      + + Attributes + +
      + Implementator's note +
        + The module is only usable if you activate "Network Standby" on your receiver.

        + Technically there are many more commands and readings possible, but I think + these are the main usecases within FHEM. +
      +
      +
    +

    ZWDongle