diff --git a/fhem/CHANGED b/fhem/CHANGED index 0128d2561..3b12d834b 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,6 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - added: 71_YAMAHA_NP.pm: New module for controlling Yamaha network players such as CRX-N560(D) - bugfix: FB_CALLMONITOR: fix not working telnet login, when user based authentication is configured in FritzBox - feature: 02_RSS.pm: improved frontpage for RSS diff --git a/fhem/FHEM/71_YAMAHA_NP.pm b/fhem/FHEM/71_YAMAHA_NP.pm new file mode 100644 index 000000000..ac64c6374 --- /dev/null +++ b/fhem/FHEM/71_YAMAHA_NP.pm @@ -0,0 +1,1729 @@ +############################################################################## +# +# $Id$ +# +# 71_YAMAHA_NP.pm +# +# An FHEM Perl module for controlling the Yamaha CD-Receiver CRX-N560(D) +# (aka MCR-N560D) via Ethernet connection. +# The module should also work with devices controlled by the +# Yamaha Network Player App for *OS and Andr*id +# (e.g. NP-S2000, CD-N500, CD-N301, R-N500, R-N301). +# +# Copyright by Radoslaw Watroba +# (e-mail: ra666ack@googlemail.com) +# +# Inspired by the 71_YAMAHA_AVR module by Markus Bloch +# (e-mail: Notausstieg0309@googlemail.com) +# +# This file is part of fhem. +# +# Fhem is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# Fhem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see . +# +############################################################################## +# +# 2015-01-17 v1.0 Initial Release +# +############################################################################## + +package main; + +use strict; +use warnings; +use Time::HiRes qw(gettimeofday sleep); +use Time::Piece; +use POSIX qw{strftime}; +use HttpUtils; + +sub YAMAHA_NP_Get($@); +sub YAMAHA_NP_Define($$); +sub YAMAHA_NP_GetStatus($;$); +sub YAMAHA_NP_Attr(@); +sub YAMAHA_NP_ResetTimer($;$); +sub YAMAHA_NP_Undefine($$); + +################################### +sub YAMAHA_NP_Initialize($) +{ + my ($hash) = @_; + + $hash->{DefFn} = "YAMAHA_NP_Define"; + $hash->{GetFn} = "YAMAHA_NP_Get"; + $hash->{SetFn} = "YAMAHA_NP_Set"; + $hash->{AttrFn} = "YAMAHA_NP_Attr"; + $hash->{UndefFn} = "YAMAHA_NP_Undefine"; + + $hash->{AttrList} = "do_not_notify:0,1 disable:0,1 request-timeout:1,2,3,4,5 ".$readingFnAttributes; +} + +################################### +sub YAMAHA_NP_GetStatus($;$) +{ + my ($hash, $local) = @_; + my $name = $hash->{NAME}; + my $power; + + $local = 0 unless(defined($local)); + + return "" if(!defined($hash->{helper}{ADDRESS}) or !defined($hash->{helper}{OFF_INTERVAL}) or !defined($hash->{helper}{ON_INTERVAL})); + + my $device = $hash->{helper}{ADDRESS}; + + # Get model and firmware information + if(not defined($hash->{MODEL})) + { + YAMAHA_NP_getModel($hash); + # Get network related information from the NP + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest", "networkInfo"); + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest", "systemConfig"); + YAMAHA_NP_ResetTimer($hash) unless($local == 1); + return; + } + + # Get available inputs if not defined + if((not defined($hash->{helper}{INPUTS}) or length($hash->{helper}{INPUTS}) == 0)) + { + YAMAHA_NP_getInputs($hash); + YAMAHA_NP_ResetTimer($hash) unless($local == 1); + return; + } + + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest", "basicStatus"); + YAMAHA_NP_ResetTimer($hash) unless($local == 1); +} + +################################### +sub YAMAHA_NP_Get($@) +{ + my ($hash, @a) = @_; + my $what; + my $return; + + return "argument is missing" if(int(@a) != 2); + + $what = $a[1]; + + if(exists($hash->{READINGS}{$what})) + { + if(defined($hash->{READINGS}{$what})) + { + return $hash->{READINGS}{$what}{VAL}; + } + else + { + return "no such reading: $what"; + } + } + else + { + $return = "unknown argument $what, choose one of"; + + foreach my $reading (keys %{$hash->{READINGS}}) + { + $return .= " $reading:noArg"; + } + + return $return; + } +} + + +################################### +sub YAMAHA_NP_Set($@) +{ + my ($hash, @a) = @_; + my $name = $hash->{NAME}; + my $address = $hash->{helper}{ADDRESS}; + + # Get model info in case not defined + if(not defined($hash->{MODEL}) or not defined($hash->{FIRMWARE})) + { + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest", "networkInfo"); + YAMAHA_NP_getModel($hash); + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest", "systemConfig"); + } + + if(not defined($hash->{helper}{VOLUMESTRAIGHTMIN}) and not defined($hash->{helper}{VOLUMESTRAIGHTMAX})) + { + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest", "basicStatus"); + } + + # get all available inputs if nothing is available + if(not defined($hash->{helper}{INPUTS}) or length($hash->{helper}{INPUTS}) == 0) + { + YAMAHA_NP_getInputs($hash); + } + + my $inputs_piped = defined($hash->{helper}{INPUTS}) ? YAMAHA_NP_Param2Fhem(lc($hash->{helper}{INPUTS}), 0) : "" ; + my $inputs_comma = defined($hash->{helper}{INPUTS}) ? YAMAHA_NP_Param2Fhem(lc($hash->{helper}{INPUTS}), 1) : "" ; + + # Setting default values. Update from device during existing communication. + my $volumeStraightMin = defined($hash->{helper}{VOLUMESTRAIGHTMIN}) ? $hash->{helper}{VOLUMESTRAIGHTMIN} : "0"; + my $volumeStraightMax = defined($hash->{helper}{VOLUMESTRAIGHTMAX}) ? $hash->{helper}{VOLUMESTRAIGHTMAX} : "60"; + + return "No Argument given" if(!defined($a[1])); + + my $what = $a[1]; + + my $usage = ""; + + # DAB available? Suffix D stands for DAB. + if (defined($hash->{MODEL})) + { + my $model = $hash->{MODEL}; + + if ($model eq "CRX-N560D") + { + $usage = "Unknown argument $what, choose one of ". + "on:noArg ". + "off:noArg ". + "timerRepeat:once,every ". + "sleep:off,30min,60min,90min,120min ". + "volumeStraight:slider,".$volumeStraightMin.",1,".$volumeStraightMax." ". + "volume:slider,0,1,100 ". + "volumeUp:noArg ". + "volumeDown:noArg ". + "timerVolume:slider,".$volumeStraightMin.",1,".$volumeStraightMax." ". + "mute:on,off ". + (exists($hash->{helper}{INPUTS})?"input:".$inputs_comma." ":""). + "statusRequest:basicStatus,networkInfo,playerStatus,systemConfig,timerStatus,tunerPresetDAB,tunerPresetFM,tunerStatus ". + "standbyMode:eco,normal ". + "cdTray:noArg ". + "timer:on,off ". + "tuner:bandDAB,bandFM,presetUp,presetDown,tuneDown,tuneUp ". + "player:play,stop,pause,next,prev,shuffleToggle,repeatToggle ". + "clockUpdate:noArg ". + "tunerPresetDAB: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 ". + "tunerPresetFM: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 ". + "timerHour:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ". + "timerMinute:0,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,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59 "; + } + else + { + $usage = "Unknown argument $what, choose one of ". + "on:noArg ". + "off:noArg ". + "timerRepeat:once,every ". + "sleep:off,30min,60min,90min,120min ". + "volumeStraight:slider,".$volumeStraightMin.",1,".$volumeStraightMax." ". + "volume:slider,0,1,100 ". + "volumeUp:noArg ". + "volumeDown:noArg ". + "timerVolume:slider,".$volumeStraightMin.",1,".$volumeStraightMax." ". + "mute:on,off ". + (exists($hash->{helper}{INPUTS})?"input:".$inputs_comma." ":""). + "statusRequest:basicStatus,networkInfo,playerStatus,systemConfig,timerStatus,tunerPresetFM,tunerStatus ". + "standbyMode:eco,normal ". + "cdTray:noArg ". + "timer:on,off ". + "tuner:bandFM,presetUp,presetDown,tuneDown,tuneUp ". + "player:play,stop,pause,next,prev,shuffleToggle,repeatToggle ". + "clockUpdate:noArg ". + "tunerPresetFM: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 ". + "timerHour:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 ". + "timerMinute:0,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,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59 "; + } + Log3 $name, 5, "Model: $model."; + } + + Log3 $name, 5, "YAMAHA_NP ($name) - set ".join(" ", @a); + + if($what eq "on") + { + YAMAHA_NP_SendCommand($hash, "On" ,$what, undef); + } + elsif($what eq "off") + { + YAMAHA_NP_SendCommand($hash, "Standby", $what, undef); + } + elsif($what eq "input") + { + if(defined($a[2])) + { + if($hash->{READINGS}{power}{VAL} eq "on") + { + if(not $inputs_piped eq "") + { + if($a[2] =~ /^($inputs_piped)$/) + { + my $command = YAMAHA_NP_getParamName($hash, $a[2], $hash->{helper}{INPUTS}); + if(defined($command) and length($command) > 0) + { + YAMAHA_NP_SendCommand($hash, "".$command."", $what, $a[2]); + } + else + { + return "invalid input: ".$a[2]; + } + } + else + { + return $usage; + } + } + else + { + return "No inputs are avaible. Please try an statusUpdate."; + } + } + else + { + return "input can only be used when device is powered on"; + } + } + else + { + return $inputs_piped eq "" ? "No inputs are available. Please try an statusUpdate." : "No input parameter was given"; + } + } + elsif($what eq "mute") + { + if(defined($a[2])) + { + if($hash->{READINGS}{power}{VAL} eq "on") + { + if($a[2] eq "on") + { + YAMAHA_NP_SendCommand($hash, "On", $what, "on"); + } + elsif($a[2] eq "off") + { + YAMAHA_NP_SendCommand($hash, "Off", $what, "off"); + } + else + { + return $usage; + } + } + else + { + return "mute can only used when device is powered on"; + } + } + } + elsif($what =~ /^(volumeStraight|volume|volumeUp|volumeDown)$/) + { + my $target_volume; + + if($what eq "volume" and $a[2] >= 0 && $a[2] <= 100) + { + $target_volume = YAMAHA_NP_volume_rel2abs($hash, $a[2]); + } + elsif($what eq "volumeDown") + { + $target_volume = $hash->{READINGS}{volumeStraight}{VAL} - 1; + } + elsif($what eq "volumeUp") + { + $target_volume = $hash->{READINGS}{volumeStraight}{VAL} + 1; + } + else + { + # volumeStraight + $target_volume = $a[2]; + } + + # if lower than minimum VOLUMESTRAIGHTMIN or higher than max VOLUMESTRAIGHTMAX set target volume to the corresponding limts + $target_volume = $hash->{helper}{VOLUMESTRAIGHTMIN} if(defined($target_volume) and $target_volume < $hash->{helper}{VOLUMESTRAIGHTMIN}); + $target_volume = $hash->{helper}{VOLUMESTRAIGHTMAX} if(defined($target_volume) and $target_volume > $hash->{helper}{VOLUMESTRAIGHTMAX}); + + Log3 $name, 4, "YAMAHA_NP ($name) - new target volume: $target_volume"; + + if(defined($target_volume) ) + { + if($hash->{READINGS}{power}{VAL} eq "on") + { + $hash->{helper}{targetVolume} = $target_volume; + YAMAHA_NP_SendCommand($hash, "".($target_volume)."<\/System>", "volume", undef); + } + else + { + return "Volume can only be changed when device is powered on"; + } + } + } + elsif($what eq "sleep") + { + if($a[2] eq "off") + { + YAMAHA_NP_SendCommand($hash, "Off", $what, $a[2]); + } + elsif($a[2] eq "30min") + { + YAMAHA_NP_SendCommand($hash, "30 min", $what, $a[2]); + } + elsif($a[2] eq "60min") + { + YAMAHA_NP_SendCommand($hash, "60 min", $what, $a[2]); + } + elsif($a[2] eq "90min") + { + YAMAHA_NP_SendCommand($hash, "90 min", $what, $a[2]); + } + elsif($a[2] eq "120min") + { + YAMAHA_NP_SendCommand($hash, "120 min", $what, $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "tuner") + { + if($a[2] eq "presetUp") + { + YAMAHA_NP_SendCommand($hash,"Next", $what, $a[2]); + } + elsif($a[2] eq "presetDown") + { + YAMAHA_NP_SendCommand($hash,"Prev", $what, $a[2]); + } + elsif($a[2] eq "tuneUp") + { + YAMAHA_NP_SendCommand($hash, "Next", $what, $a[2]); + } + elsif($a[2] eq "tuneDown") + { + YAMAHA_NP_SendCommand($hash, "Prev", $what, $a[2]); + } + elsif($a[2] eq "bandDAB") + { + YAMAHA_NP_SendCommand($hash, "DAB", $what, $a[2]); + } + elsif($a[2] eq "bandFM") + { + YAMAHA_NP_SendCommand($hash, "FM", $what, $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "player") + { + if($a[2] eq "play") + { + YAMAHA_NP_SendCommand($hash, "Play", $what, $a[2]); + } + elsif($a[2] eq "pause") + { + YAMAHA_NP_SendCommand($hash, "Pause", $what, $a[2]); + } + elsif($a[2] eq "stop") + { + YAMAHA_NP_SendCommand($hash, "Stop", $what, $a[2]); + } + elsif($a[2] eq "next") + { + YAMAHA_NP_SendCommand($hash, "Next", $what, $a[2]); + } + elsif($a[2] eq "prev") + { + YAMAHA_NP_SendCommand($hash, "Prev", $what, $a[2]); + } + elsif($a[2] eq "shuffle") + { + YAMAHA_NP_SendCommand($hash, "Toggle", $what, $a[2]); + } + elsif($a[2] eq "repeat") + { + YAMAHA_NP_SendCommand($hash, "Toggle", $what, $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "standbyMode") + { + if($a[2] eq "eco") + { + YAMAHA_NP_SendCommand($hash, "Eco", $what, $a[2]); + } + elsif($a[2] eq "normal") + { + YAMAHA_NP_SendCommand($hash, "Normal", $what, $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "cdTray") + { + YAMAHA_NP_SendCommand($hash, "Open/Close", $what, undef); + } + elsif($what eq "clockUpdate") + { + my $clockUpdateCurrentTime = Time::Piece->new(); + YAMAHA_NP_SendCommand($hash, "".($clockUpdateCurrentTime->strftime('%Y:%m:%d:%H:%M:%S'))."", $what, undef); + } + elsif($what eq "statusRequest") + { + if($a[2] eq "systemConfig") + { + YAMAHA_NP_SendCommand($hash, "GetParam", $what, $a[2]); + } + elsif($a[2] eq "playerStatus") + { + YAMAHA_NP_SendCommand($hash, "GetParam<\/Play_Info><\/Player><\/YAMAHA_AV>", $what, $a[2]); + } + elsif($a[2] eq "tunerStatus") + { + YAMAHA_NP_SendCommand($hash, "GetParam<\/Play_Info><\/Tuner><\/YAMAHA_AV>", $what, $a[2]); + } + elsif($a[2] eq "basicStatus") + { + YAMAHA_NP_SendCommand($hash, "GetParam", $what, $a[2]); + } + elsif($a[2] eq "timerStatus") + { + YAMAHA_NP_SendCommand($hash, "GetParam", $what, "getTimer"); + YAMAHA_NP_SendCommand($hash, "GetParam", $what, $a[2]); + } + elsif($a[2] eq "networkInfo") + { + YAMAHA_NP_SendCommand($hash, "GetParam", $what, $a[2]); + } + elsif($a[2] eq "tunerPresetFM") + { + YAMAHA_NP_SendCommand($hash, "GetParam", $what, $a[2]); + } + elsif($a[2] eq "tunerPresetDAB") + { + YAMAHA_NP_SendCommand($hash, "GetParam", $what, $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "timer") + { + if($a[2] eq "on") + { + if(defined($hash->{helper}{timerHour}) and defined($hash->{helper}{timerMinute}) and defined($hash->{helper}{timerRepeat}) and defined($hash->{helper}{timerVolume})) + { + # Configure Timer according to provided parameters + YAMAHA_NP_SendCommand($hash, "".sprintf("%02d", $hash->{helper}{timerHour}).":".sprintf("%02d", $hash->{helper}{timerMinute})."".$hash->{helper}{timerVolume}."".$hash->{helper}{timerRepeat}."", $what, $a[2]); + # Switch on timer + YAMAHA_NP_SendCommand($hash, "".ucfirst($a[2])."", $what, $a[2]); + } + else + { + return "Please, define timerHour, timerMinute, timerRepeat and timerVolume first." + } + } + elsif($a[2] eq "off") + { + YAMAHA_NP_SendCommand($hash, "".ucfirst($a[2])."", $what, $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "timerHour") + { + if((int($a[2]) >= 0) and (int($a[2]) <= 23)) + { + $hash->{helper}{timerHour} = $a[2]; + } + else + { + return $usage; + } + } + elsif($what eq "timerMinute") + { + if((int($a[2]) >= 0) and (int($a[2]) <= 59)) + { + $hash->{helper}{timerMinute} = $a[2]; + } + else + { + return $usage; + } + } + elsif($what eq "timerRepeat") + { + if($a[2] eq "once" or $a[2] eq "every") + { + $hash->{helper}{timerRepeat} = ucfirst($a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "timerVolume") + { + # if lower than minimum VOLUMESTRAIGHTMIN or higher than max VOLUMESTRAIGHTMAX set target volume to the corresponding limts + if($a[2] >= $hash->{helper}{VOLUMESTRAIGHTMIN} and $a[2] <= $hash->{helper}{VOLUMESTRAIGHTMAX}) + { + $hash->{helper}{timerVolume} = $a[2]; + } + else + { + return "Please use straight device volume range :".$hash->{helper}{VOLUMESTRAIGHTMIN}."...".$hash->{helper}{VOLUMESTRAIGHTMAX}."."; + } + } + elsif($what eq "tunerPresetDAB") + { + if($a[2] >= 1 and $a[2] <= 30 and $hash->{MODEL} eq "CRX-N560D") + { + YAMAHA_NP_SendCommand($hash, "".$a[2]."<\/Preset_Sel><\/DAB><\/Preset><\/Play_Control><\/Tuner>", "tunerPresetDAB", $a[2]); + } + else + { + return $usage; + } + } + elsif($what eq "tunerPresetFM") + { + if($a[2] >= 1 and $a[2] <= 30) + { + YAMAHA_NP_SendCommand($hash, "".$a[2]."<\/Preset_Sel><\/FM><\/Preset><\/Play_Control><\/Tuner>", "tunerPresetFM", $a[2]); + } + else + { + return $usage; + } + } + else + { + return $usage; + } +} + +############################# +sub YAMAHA_NP_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $name = $hash->{NAME}; + + if(! @a >= 3) + { + my $msg = "Wrong syntax: define YAMAHA_NP [] [] "; + Log3 $name, 2, $msg; + return $msg; + } + + my $address = $a[2]; + + $hash->{helper}{ADDRESS} = $address; + + # if an update interval was given which is greater than zero, use it. + if(defined($a[3]) and $a[3] > 0) + { + $hash->{helper}{OFF_INTERVAL} = $a[3]; + } + else + { + $hash->{helper}{OFF_INTERVAL} = 30; + } + + if(defined($a[4]) and $a[4] > 0) + { + $hash->{helper}{ON_INTERVAL} = $a[4]; + } + else + { + $hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL}; + } + + YAMAHA_NP_getInputs($hash); + + # set the volume-smooth-change attribute only if it is not defined, so no user values will be overwritten + # + # own attribute values will be overwritten anyway when all attr-commands are executed from fhem.cfg + + unless(exists($hash->{helper}{AVAILABLE}) and ($hash->{helper}{AVAILABLE} == 0)) + { + $hash->{helper}{AVAILABLE} = 1; + readingsSingleUpdate($hash, "presence", "present", 1); + } + + + # start the status update timer + $hash->{helper}{DISABLED} = 0 unless(exists($hash->{helper}{DISABLED})); + YAMAHA_NP_ResetTimer($hash,0); + + return undef; +} + + +########################## +sub YAMAHA_NP_Attr(@) +{ + my @a = @_; + my $hash = $defs{$a[1]}; + + if($a[0] eq "set" && $a[2] eq "disable") + { + if($a[3] eq "0") + { + $hash->{helper}{DISABLED} = 0; + YAMAHA_NP_GetStatus($hash, 1); + } + elsif($a[3] eq "1") + { + $hash->{helper}{DISABLED} = 1; + } + } + elsif($a[0] eq "del" && $a[2] eq "disable") + { + $hash->{helper}{DISABLED} = 0; + YAMAHA_NP_GetStatus($hash, 1); + } + + # Start/Stop Timer according to new disabled-Value + YAMAHA_NP_ResetTimer($hash); + + return undef; +} + +############################# +sub +YAMAHA_NP_Undefine($$) +{ + my($hash, $name) = @_; + + # Stop the internal GetStatus-Loop and exit + RemoveInternalTimer($hash); + return undef; +} + + +############################################################################################################ +# +# Begin of helper functions +# +############################################################################################################ + + + +############################# +# sends a command to the receiver via HTTP +sub YAMAHA_NP_SendCommand($@) +{ + my ($hash, $data,$cmd,$arg,$blocking) = @_; + my $name = $hash->{NAME}; + my $address = $hash->{helper}{ADDRESS}; + + # "Blocking" delivers most reliable results for updating the READINGS. + # However, should the NP suddenly disappear FHEM would be blocked until a timeout. + # Trade-off between sending command and getting status... + + # Always use non-blocking http communication + if(not defined($blocking) and $cmd ne "statusRequest" and $hash->{helper}{AVAILABLE} == 1) + { + #1 for testing + $blocking = 0; + } + else + { + #0 for testing + $blocking = 0; + } + + # In case any URL changes must be made, this part is separated in this function". + + if($blocking == 1) + { + Log3 $name, 5, "YAMAHA_NP ($name) - execute blocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data"; + + my $param = + { + url => "http://".$address."/YamahaRemoteControl/ctrl", + timeout => AttrVal($name, "request-timeout", 4), + noshutdown => 1, + data => "".$data, + loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5), + hash => $hash, + cmd => $cmd, + arg => $arg + }; + + my ($err, $data) = HttpUtils_BlockingGet($param); + YAMAHA_NP_ParseResponse($param, $err, $data); + } + else + { + Log3 $name, 5, "YAMAHA_NP ($name) - execute nonblocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data"; + + HttpUtils_NonblockingGet + ({ + url => "http://".$address."/YamahaRemoteControl/ctrl", + timeout => AttrVal($name, "request-timeout", 4), + noshutdown => 1, + data => "".$data, + loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5), + hash => $hash, + cmd => $cmd, + arg => $arg, + callback => \&YAMAHA_NP_ParseResponse + + }); + } +} + +############################# +# parses the receiver response +sub YAMAHA_NP_ParseResponse ($$$) +{ + my ( $param, $err, $data ) = @_; + + my $hash = $param->{hash}; + my $name = $hash->{NAME}; + my $cmd = $param->{cmd}; + my $arg = $param->{arg}; + + if(exists($param->{code})) + { + Log3 $name, 5, "YAMAHA_NP ($name) - received HTTP code ".$param->{code}." for command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\""; + } + + if($err ne "") + { + Log3 $name, 5, "YAMAHA_NP ($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_NP ($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; + } + elsif($data ne "") + { + Log3 $name, 5, "YAMAHA_NP ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data"; + + if (defined($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 0) + { + Log3 $name, 3, "YAMAHA_NP ($name) - device $name reappeared"; + readingsSingleUpdate($hash, "presence", "present", 1); + } + + $hash->{helper}{AVAILABLE} = 1; + + if(not $data =~ /RC="0"/) + { + # if the returncode isn't 0, than the command was not successful + Log3 $name, 3, "YAMAHA_NP ($name) - Could not execute \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\""; + } + + readingsBeginUpdate($hash); + + if($cmd eq "statusRequest") + { + if($arg eq "systemConfig") + { + if($data =~ /(.+?)<\/Model_Name>.*(.+?)<\/System_ID>.*(.+?)<\/Version>.*(.+?)<\/Min>.*(.+?)<\/Max>.*(.+?)<\/Step><\/Volume>/) + { + delete($hash->{MODEL}) if(defined($hash->{MODEL})); + delete($hash->{helper}{VOLUMESTRAIGHTMIN}) if(defined($hash->{helper}{VOLUMESTRAIGHTMIN})); + delete($hash->{helper}{VOLUMESTRAIGHTMAX}) if(defined($hash->{helper}{VOLUMESTRAIGHTMAX})); + delete($hash->{helper}{VOLUMESTRAIGHTSTEP}) if(defined($hash->{helper}{VOLUMESTRAIGHTSTEP})); + + $hash->{MODEL} = $1; + $hash->{SYSTEM_ID} = $2; + $hash->{FIRMWARE} = $3; + $hash->{helper}{VOLUMESTRAIGHTMIN} = $4; + $hash->{helper}{VOLUMESTRAIGHTMAX} = $5; + $hash->{helper}{VOLUMESTRAIGHTSTEP} = $6; + } + + #$attr{$name}{"model"} = $hash->{MODEL}; + } + elsif($arg eq "getInputs") + { + delete($hash->{helper}{INPUTS}) if(defined($hash->{helper}{INPUTS})); + + while($data =~ /(.+?)<\/Feature_Existence>/gc) + { + if(defined($hash->{helper}{INPUTS}) and length($hash->{helper}{INPUTS}) > 0) + { + $hash->{helper}{INPUTS} .= ","; + } + $hash->{helper}{INPUTS} .= $1; + } + $hash->{helper}{INPUTS} = join("|", sort split("\\,", $hash->{helper}{INPUTS})); + } + elsif($arg eq "basicStatus") + { + if($data =~ /(.+?)<\/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 =~ /(.+?)<\/Lvl>(.+?)<\/Mute><\/Volume>/) + { + readingsBulkUpdate($hash, "volumeStraight", ($1)); + readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $1)); + readingsBulkUpdate($hash, "mute", lc($2)); + } + # current input same as the corresponding set command name + if($data =~ /(.+?)<\/Input_Sel>/) + { + readingsBulkUpdate($hash, "input", YAMAHA_NP_Param2Fhem(lc($1), 0)); + } + + if($data =~ /(.+?)<\/Sleep>/) + { + readingsBulkUpdate($hash, "sleep", YAMAHA_NP_Param2Fhem($1, 0)); + } + } + elsif($arg eq "playerStatus") + { + if($data =~ /(.+)<\/Playback_Info>/) + { + readingsBulkUpdate($hash, "playerPlaybackInfo", lc($1)); + } + if($data =~ /(.+)<\/Device_Type>/) + { + readingsBulkUpdate($hash, "playerDeviceType", lc($1)); + } + if($data =~ /(.+)<\/iPod_Mode>/) + { + readingsBulkUpdate($hash, "playerIpodMode", lc($1)); + } + if($data =~ /(.+)<\/Repeat>/) + { + readingsBulkUpdate($hash, "playerRepeat", lc($1)); + } + if($data =~ /(.+)<\/Shuffle>/) + { + readingsBulkUpdate($hash, "playerShuffle", lc($1)); + } + if($data =~ /(.+)<\/Play_Time>/) + { + readingsBulkUpdate($hash, "playerPlayTime", strftime("\%H:\%M:\%S", gmtime($1))); + } + if($data =~ /(.+)<\/Track_Number>/) + { + readingsBulkUpdate($hash, "playerTrackNumber", lc($1)); + } + if($data =~ /(.+)<\/Total_Tracks>/) + { + readingsBulkUpdate($hash, "playerTotalTracks", lc($1)); + } + if($data =~ /(.+)<\/Artist>/) + { + readingsBulkUpdate($hash, "playerArtist", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Album>/) + { + readingsBulkUpdate($hash, "playerAlbum", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Song>/) + { + readingsBulkUpdate($hash, "playerSong", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/URL>(.+)<\/ID>(.+)<\/Format><\/Album_ART>/) + { + readingsBulkUpdate($hash, "playerAlbumArtURL", YAMAHA_NP_html2txt($1)); + readingsBulkUpdate($hash, "playerAlbumArtID", YAMAHA_NP_html2txt($2)); + readingsBulkUpdate($hash, "playerAlbumArtFormat", YAMAHA_NP_html2txt($3)); + } + } + elsif($arg eq "tunerStatus") + { + if($data =~ /(.+)<\/Band>/) + { + readingsBulkUpdate($hash, "tunerBand", ($1)); + } + if($data =~ /(.+)<\/Preset_Sel><\/Preset>(.*)<\/FM/) + { + readingsBulkUpdate($hash, "tunerPresetFM", ($1)); + } + if($data =~ /(.+)<\/Freq><\/Tuning>/) + { + my $frequency = $1; + $frequency =~ s/(\d{2})$/.$1/; # Insert '.' to frequency + readingsBulkUpdate($hash, "tunerFrequencyFM", $frequency." MHz"); + } + if($data =~ /(.+)<\/Program_Service>/) + { + readingsBulkUpdate($hash, "tunerProgramServiceFM", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Radio_Text_A>/) + { + readingsBulkUpdate($hash, "tunerRadioTextAFM", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Radio_Text_B>/) + { + readingsBulkUpdate($hash, "tunerRadioTextBFM", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Preset_Sel><\/Preset>(.*)<\/DAB>/) + { + readingsBulkUpdate($hash, "tunerPresetDAB", ($1)); + } + if($data =~ /(.+)<\/Service_Label>/) + { + readingsBulkUpdate($hash, "tunerServiceLabelDAB", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Ch_Label>/) + { + readingsBulkUpdate($hash, "tunerChannelLabelDAB", ($1)); + } + if($data =~ /(.+)<\/DLS>/) + { + readingsBulkUpdate($hash, "tunerDLSDAB", YAMAHA_NP_html2txt($1)); + } + if($data =~ /(.+)<\/Ensemble_Label>/) + { + readingsBulkUpdate($hash, "tunerEnsembleLabelDAB", YAMAHA_NP_html2txt($1)); + } + } + elsif($arg eq "timerStatus") + { + if($data =~ /(.+)<\/Lvl><\/Volume>/) + { + readingsBulkUpdate($hash, "timerVolume", $1); + } + if($data =~ /(.+)<\/Start_Time>/) + { + readingsBulkUpdate($hash, "timerStartTime", $1); + } + if($data =~ /(.+)<\/Repeat>/) + { + readingsBulkUpdate($hash, "timerRepeat", lc($1)); + } + } + elsif($arg eq "getTimer") + { + if($data =~ /(.+)<\/Mode>/) + { + readingsBulkUpdate($hash, "timer", lc($1)); + } + } + elsif($arg eq "networkInfo") + { + if($data =~ /(.+)<\/IP_Address>/) + { + $hash->{IP_ADDRESS} = $1; + } + if($data =~ /(.+)<\/Subnet_Mask>/) + { + $hash->{SUBNET_MASK} = $1; + } + if($data =~ /(.+)<\/Default_Gateway>/) + { + $hash->{DEFAULT_GATEWAY} = $1; + } + if($data =~ /(.+)<\/DNS_Server_1>/) + { + $hash->{DNS_SERVER_1} = $1; + } + if($data =~ /(.+)<\/DNS_Server_2>/) + { + $hash->{DNS_SERVER_2} = $1; + } + if($data =~ /(.+)<\/MAC_Address>/) + { + $hash->{MAC_ADDRESS} = $1; + # Add ':' after every two chars + $hash->{MAC_ADDRESS} =~ s/\w{2}\B/$&:/g; + } + } + elsif($arg eq "tunerPresetFM") + { + { + # May be also an empty string + for (my $i = 1; $i < 31; $i++) + { + if ($data =~ /<\/Item_$i>/) + { + readingsBulkUpdate($hash, sprintf("tunerPresetFMItem_%02d", $i), "No Preset"); + } + elsif($data =~ /(.+?)<\/Item_$i>/) + { + readingsBulkUpdate($hash, sprintf("tunerPresetFMItem_%02d", $i), $1); + } + } + } + } + elsif($arg eq "tunerPresetDAB") + { + # May be also an empty string + for (my $i = 1; $i < 31; $i++) + { + if ($data =~ /<\/Item_$i>/) + { + readingsBulkUpdate($hash, sprintf("tunerPresetDABItem_%02d", $i), "No Preset"); + } + elsif($data =~ /(.+?)<\/Item_$i>/) + { + readingsBulkUpdate($hash, sprintf("tunerPresetDABItem_%02d", $i), $1); + } + } + } + } + elsif($cmd eq "on") + { + if($data =~ /RC="0"/ and $data =~ /<\/Power>/) + { + # As the NP startup takes about 5 seconds, the status will be already set, if the return code of the command is 0. + readingsBulkUpdate($hash, "power", "on"); + readingsBulkUpdate($hash, "state","on"); + + readingsEndUpdate($hash, 1); + + YAMAHA_NP_ResetTimer($hash, 5); + + return undef; + } + } + elsif($cmd eq "off") + { + if($data =~ /RC="0"/ and $data =~ /<\/Power>/) + { + readingsBulkUpdate($hash, "power", "off"); + readingsBulkUpdate($hash, "state","off"); + + readingsEndUpdate($hash, 1); + + YAMAHA_NP_ResetTimer($hash, 3); + + return undef; + } + } + elsif($cmd eq "mute") + { + if($data =~ /RC="0"/) + { + readingsBulkUpdate($hash, "mute", $arg); + } + } + elsif($cmd eq "volume" or $cmd eq "volumeStraight" or $cmd eq "volumeUp" or $cmd eq "volumeDown") + { + + if($data =~ /RC="0"/) + { + readingsBulkUpdate($hash, "volumeStraight", $hash->{helper}{targetVolume}); + readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $hash->{helper}{targetVolume})); + # New "volume"value: The CRX-N560D cannot provide the current volume in time after a volume change. + # Therefore updated locally. + # Volume will be updated during the next timer loop. + } + } + + readingsEndUpdate($hash, 1); + + YAMAHA_NP_ResetTimer($hash, 0) if($cmd ne "statusRequest" and $cmd ne "on" and $cmd ne "volume"); + } +} + +############################# +# Converts all Values to FHEM usable command lists +sub YAMAHA_NP_Param2Fhem($$) +{ + my ($param, $replace_pipes) = @_; + + $param =~ s/\s+//g; + $param =~ s/,//g; + $param =~ s/_//g; + $param =~ s/\(/_/g; + $param =~ s/\)//g; + $param =~ s/\|/,/g if($replace_pipes == 1); + + return lc $param; +} + +############################# +# Returns the Yamaha Parameter Name for the FHEM like equivalent +sub YAMAHA_NP_getParamName($$$) +{ + my ($hash, $name, $list) = @_; + my $item; + + return undef if(not defined($list)); + + my @commands = split("\\|", $list); + + foreach $item (@commands) + { + if(YAMAHA_NP_Param2Fhem($item, 0) eq $name) + { + return $item; + } + } + return undef; +} + +############################# +# queries the receiver model, system-id, version and all available zones +sub YAMAHA_NP_getModel($) +{ + my ($hash) = @_; + + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest","systemConfig"); +} + +############################# +# converts straight volume in percentage volume (volumestraightmin .. volumestraightmax => 0 .. 100%) +sub YAMAHA_NP_volume_rel2abs($$) +{ + my ($hash, $percentage) = @_; + + return int(($percentage * $hash->{helper}{VOLUMESTRAIGHTMAX} / 100 )); +} + +############################# +# converts percentage volume in decibel volume (0 .. 100% => volumestraightmin .. volumestraightmax) +sub YAMAHA_NP_volume_abs2rel($$) +{ + my ($hash, $absolute) = @_; + + # Prevent division by 0 + if (defined($hash->{helper}{VOLUMESTRAIGHTMAX}) and $hash->{helper}{VOLUMESTRAIGHTMAX} ne "0") + { + return int($absolute * 100 / int($hash->{helper}{VOLUMESTRAIGHTMAX})); + } + else + { + return int(0) + } +} + +############################# +# queries all available inputs and scenes +sub YAMAHA_NP_getInputs($) +{ + my ($hash) = @_; + my $name = $hash->{NAME}; + my $address = $hash->{helper}{ADDRESS}; + + # query all inputs + YAMAHA_NP_SendCommand($hash, "GetParam", "statusRequest","getInputs"); +} + +############################# +# Restarts the internal status request timer according to the given interval or current receiver state +sub YAMAHA_NP_ResetTimer($;$) +{ + my ($hash, $interval) = @_; + + RemoveInternalTimer($hash); + + if($hash->{helper}{DISABLED} == 0) + { + if(defined($interval)) + { + InternalTimer(gettimeofday()+$interval, "YAMAHA_NP_GetStatus", $hash, 0); + } + elsif((exists($hash->{READINGS}{presence}{VAL}) and $hash->{READINGS}{presence}{VAL} eq "present") and (exists($hash->{READINGS}{power}{VAL}) and $hash->{READINGS}{power}{VAL} eq "on")) + { + InternalTimer(gettimeofday() + $hash->{helper}{ON_INTERVAL}, "YAMAHA_NP_GetStatus", $hash, 0); + } + else + { + InternalTimer(gettimeofday() + $hash->{helper}{OFF_INTERVAL}, "YAMAHA_NP_GetStatus", $hash, 0); + } + } + return undef; +} + +############################# +# convert all HTML entities into UTF-8 equivalent +sub YAMAHA_NP_html2txt($) +{ + my ($string) = @_; + + $string =~ s/"/\"/g; + $string =~ s/&/&/g; + $string =~ s/&/&/g; + $string =~ s/ / /g; + $string =~ s/'/'/g; + $string =~ s/(\xe4|ä)/ä/g; + $string =~ s/(\xc4|Ä)/Ä/g; + $string =~ s/(\xf6|ö)/ö/g; + $string =~ s/(\xd6|Ö)/Ö/g; + $string =~ s/(\xfc|ü)/ü/g; + $string =~ s/(\xdc|Ü)/Ü/g; + $string =~ s/(\xdf|ß)/ß/g; + + $string =~ s/<.+?>//g; + $string =~ s/(^\s+|\s+$)//g; + + return $string; +} + +1; + +=pod +=begin html + + +

YAMAHA_NP

+
    + + Define +

    +
      + + define <name> YAMAHA_NP <ip-address> [<status_interval>]

      + define <name> YAMAHA_NP <ip-address> [<off_status_interval>] [<on_status_interval>] +
      +

      + This module controls a Yamaha Network Player (such as CRX-N560, CRX-N560D, CD-N500 or NP-S2000) via Ethernet. + Theoretically, any device understanding the communication protocol of the Yamaha Network Player App should work. +

      + Currently implemented features: +

      +
        +
      • Power on/off
      • +
      • Timer on/off
      • +
      • Input selection
      • +
      • Timer on/off
      • +
      • Volume +/-
      • +
      • Mute on/off
      • +
      • System Clock Update
      • +
      • Tuner: tune +/-, preset +/-, Station information (FM/DAB)
      • +
      • Stand-by mode: eco/normal
      • +
      • Player (play, stop, next, prev, shuffle, repeat)
      • +
      • ...
      • +
      +
      + Defining a YAMAHA_NP device will schedule an internal task (interval can be set + with optional parameters <off_status_interval> and <on_status_interval> in seconds.
      + <off_status_interval> is a parameter used in case the device is powered off or not available.
      + <on_status_interval> is a parameter used in case the device is powered on.
      + If both parameters are unset, a default value 30 (seconds) for both is used.
      + If <off_status_interval> is set only the same value is used for both parameters. +
      + The internal task periodically reads the status of the Network Player (power state, selected + input, volume and mute status etc.) and triggers notify/filelog commands. +

      + Example:

      +

        + Add the following code into the fhem.cfg configuration file and restart fhem:

        + + define NP_Player YAMAHA_NP 192.168.0.15
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp

        + # With custom status interval of 60 seconds
        + define NP_Player YAMAHA_NP 192.168.0.15 60
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp

        + # With custom "off"-interval of 60 seconds and "on"-interval of 10 seconds
        + define NP_Player YAMAHA_NP 192.168.0.15 60 10
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp +
        +
      +
    +

    + + Set +
      + + set <name> <command> [<parameter>] +

      + Currently, the following commands are defined.
      + The available inputs are depending on the used network player. + The module offers only available inputs.

      + Note: Commands and parameters are case sensitive.
      +


        + Available commands:

        +
      • cdTray  -   open/close the CD tray.
      • +
      • clockUpdate  -   updates the system clock with current time. The time information is taken from the FHEM server.
      • +
      • input [<parameter>]   -   selects the input channel. The inputs are read dynamically from the device. Available inputs can be set (e.g. cd, tuner, aux1, aux2, ...).
      • +
      • mute [on|off]   -   activates/deactivates muting
      • +
      • off   -   shuts down the device
      • +
      • on   -   powers on the device
      • +
      • player [<parameter>]   -   sets player related commands.
      • +
          +
        • play  -   play.
        • +
        • stop  -   stop.
        • +
        • pause  -   pause.
        • +
        • next  -   next item.
        • +
        • prev  -   previous item.
        • +
        • shuffleToggle  -   Toggles the shuffle mode.
        • +
        • repeatToggle  -   Toggles the repeat modes.
        • +
        +
      • sleep [off|30min|60min|90min|120min]   -   activates the internal sleep timer
      • +
      • standbyMode [eco|normal]   -   set the standby mode.
      • +
      • statusRequest [<parameter>]   -   requests the current status of the device
      • +
          +
        • systemConfig  -   requests the system configuration
        • +
        • basicStatus  -   requests the basic status such as volume input etc.
        • +
        • playerStatus  -   requests the player status such as play status, song info, artist info etc.
        • +
        • tunerStatus  -   requests the tuner status such as FM frequency, preset number, DAB information etc.
        • +
        • timerStatus  -   requests device's internal wake-up timer status
        • +
        • networkInfo  -   requests device's network related information such as IP, Gateway, MAC address etc.
        • +
        +
      • timerHour [0...23]   -   sets hour of device's internal wake-up timer
      • +
      • timerMinute [0...59]   -   sets minutes of device's internal wake-up timer
      • +
      • timerRepeat [once|every]   -   sets repetition mode of device's internal wake-up timer
      • +
      • timerVolume [<VOL_MIN>...<VOL_MAX>]   -   sets volume of device's internal wake-up timer
      • +
      • timer [on|off]   -   sets device's internal wake-up timer. (Note: before timer activation timerHour, timerMinute, timerRepeat and timerVolume must be set.)
      • +
      • tuner [<parameter>]   -   sets tuner related commands.
      • +
          +
        • bandDAB  -   sets the tuner band to DAB (if available).
        • +
        • bandFM  -   sets the tuner band to FM.
        • +
        • tuneUp  -   tuner tune up.
        • +
        • tuneDown  -   tuner tune down.
        • +
        • presetUp  -   tuner preset up.
        • +
        • presetDown  -   tuner preset down.
        • +
        +
      • tunerPresetDAB [1...30]   -   Sets the DAB preset.
      • +
      • tunerPresetFM [1...30]   -   Sets the FM preset.
      • +
      • volume [0...100]   -   set the volume level in %
      • +
      • volumeStraight [<VOL_MIN>...<VOL_MAX>]   -   set the volume as used and displayed in the device. <VOL_MIN> and <VOL_MAX> are read and set from the device automatically.
      • +
      • volumeUp [<VOL_MIN>...<VOL_MAX>]   -   increases the volume by one device's absolute step. <VOL_MIN> and <VOL_MAX> are read and set from the device automatically.
      • +
      • volumeDown [<VOL_MIN>...<VOL_MAX>]   -   increases the volume by one device's absolute step. <VOL_MIN> and <VOL_MAX> are read and set from the device automatically.
      • +


      + + A typical example is powering the device remotely and tuning the favourite radio station:

      + Add the following code into the fhem.cfg configuration file:


      +
        + + define NP_player YAMAHA_NP 192.168.0.15 30 5
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp +
        +


      + Add the following code into the 99_MyUtils.pm file:

      +
        + + sub startMyFavouriteRadioStation()
        + {
        +   fhem "set NP_player on";
        +   sleep 1;
        +   fhem "set NP_player input tuner";
        +   sleep 1;
        +   fhem "set NP_player tunerPresetDAB 1";
        +   sleep 1;
        +   fhem "set NP_player volume 30";
        + } +
        +
      +

      + It's a good idea to insert a 'sleep' instruction between each fhem commands due to internal processing time of the network player. During that time the following commands might be ignored...

      + + Now the function can be called by typing the following line in the FHEM command line or by the notify-definitions:

      +
        + + {startMyFavouriteRadioStation()}

        +
        +
      +
    + + Get +
      + + get <name> <reading> + +

      + Currently, the 'get' command returns reading values only. For a specific list of possible values, see section "Generated Readings".

      +
    + + Attributes

    +
      +
        +
      • do_not_notify
      • +
      • readingFnAttributes
      • +
      • request-timeout
      • +
        Optional attribute change the response timeout in seconds for all queries to the receiver. +
        Possible values: 1...5 seconds. Default value is 4 seconds.

        +
      • disable
      • +
        Optional attribute to disable the internal cyclic status update of the receiver. Manual status updates via statusRequest command is still possible. +
        Possible values: 0 → perform cyclic status update, 1 → don't perform cyclic status updates.


        +
      +
    + Readings
    +
      +
        +

        Basic readings:

        +
      • input - The selected input source according to the FHEM input commands
      • +
      • mute - Reports the mute status of the receiver (on|off)
      • +
      • power - Reports the power status of the receiver (on|off)
      • +
      • presence - Reports the presence status of the receiver or zone (absent|present). Note: In case of "absent", the device cannot be controlled by FHEM. Check standbyMode.
      • +
      • volume - Reports the current volume level of the receiver in % (0...100%)
      • +
      • volumeStraight - Reports the current volume level of the receiver as used and displayed in the device (values device specific)
      • +
      • sleep - Reports the current sleep timer status (30min|60min|90min|120min|off).
      • +
      • state - Reports the current power state and an absence of the device (on|off|absent)
      • +

        Player related readings:

        +
      • playerPlaybackInfo - Reports current player state (play|stop|pause).
      • +
      • playerDeviceType - Reports the device type (ipod|msc).
      • +
      • playerIpodMode - Reports the Ipod Mode (normal|off)
      • +
      • playerRepeat - Reports the Repeat Mode (one|off)
      • +
      • playerShuffle - Reports the Shuffle Mode (on|off)
      • +
      • playerPlayTime - Reports the play time of the currently played audio (HH:MM:SS).
      • +
      • playerTrackNumber - Reports the track number of the currently played audio.
      • +
      • playerTotalTracks - Reports the total number of tracks for playing.
      • +
      • playerArtist - Reports the artist (if available) of the currently played audio.
      • +
      • playerAlbum - Reports the album (if available) of the currently played audio.
      • +
      • playerSong - Reports the song name (if available) of the currently played audio.
      • +
      • playerAlbumArtURL - Reports the album art url (if available) of the currently played audio. The URL points to the network player.
      • +
      • playerAlbumArtID - Reports the album art ID (if available) of the currently played audio.
      • +
      • playerAlbumArtFormat - Reports the album art format (if available) of the currently played audio.
      • +

        Tuner related readings:

        +
      • tunerBand - Reports the currently selected tuner band (FM|DAB). DAB if available.
      • +
      • tunerPresetFM - Reports the currently selected FM preset. If stored as such (1...30).
      • +
      • tunerFrequencyFM - Reports the currently tuned FM frequency. (xxx.xx MHz)
      • +
      • tunerProgramServiceFM - Reports the FM service name.
      • +
      • tunerRadioTextAFM - Reports the Radio Text A of the selected FM service.
      • +
      • tunerRadioTextBFM - Reports the Radio Text B of the selected FM service.
      • +
      • tunerPresetDAB - Reports the currently selected DAB preset. If stored as such (1...30).
      • +
      • tunerServiceLabelDAB - Reports the service label of the selected DAB service.
      • +
      • tunerChannelLabelDAB - Reports the channel label of the selected DAB service.
      • +
      • tunerDLSDAB - Reports the dynamic label segment of the selected DAB service.
      • +
      • tunerEnsembleLabelDAB - Reports the ensemble label of the selected DAB service.
      • +

        Timer related readings:

        +
      • timer - Reports the time mode (on|off).
      • +
      • timerRepeat - Reports the timer repeat mode (once|every).
      • +
      • timerStartTime - Reports the timer start time (HH:MM).
      • +
      • timerVolumeLevel - Reports the timer volume level.
      • +
      +

    + Implementer's note

    +
      + Trivial: In order to use that module the network player must be connected to the Ethernet.
      + The device must be in standbyMode "Normal" in order to power on.
      + However, even if the standbyMode is set to "Eco" the device can be powered off. In that case it has to be switched on manually.
      +

    +
+=end html +=begin html_DE + + +

YAMAHA_NP

+
    + + Define

    +
      + + define <name> YAMAHA_NP <ip-address> [<status_interval>]

      + define <name> YAMAHA_NP <ip-address> [<off_status_interval>] [<on_status_interval>] +
      +

      + Mit Hilfe dieses Moduls lassen sich Yamaha Network Player (z.B. CRX-N560, CRX-N560D, CD-N500 or NP-S2000) via Ethernet steuern.
      + Theoretisch sollten alle Geräte, die mit der Yamaha Network Player App kompatibel sind, bedient werden können.

      + Die aktuelle Implementierung ermöglicht u.a. den folgenden Funktionsumfang:

      +
        +
      • Power on/off
      • +
      • Timer on/off
      • +
      • Input selection
      • +
      • Timer on/off
      • +
      • Volume +/-
      • +
      • Mute on/off
      • +
      • System Clock Update
      • +
      • Tuner: tune +/-, preset +/-, Senderinformation (FM/DAB)
      • +
      • Stand-by mode: eco/normal
      • +
      • Player (play, stop, next, prev, shuffle, repeat)
      • +
      • ...
      • +
      +
      + Eine YAMAHA_NP Definition initiiert einen internen Task, der von FHEM zyklisch abgearbeitet wird.
      + Das Intervall (in Sekunden) kann für die Zustände <on_status_interval> und <off_status_interval> optional gesetzt werden.
      + <off_status_interval> steht für das Intervall, wenn das Gerät ausgeschaltet/abwesend ist.
      + <on_status_interval> steht für das Intervall, wenn das Gerät eingeschaltet/verfügbar ist.
      + Wenn keine Parametere angegeben wurden, wird ein Default-Wert von 30 Sekunden für beide gesetzt.
      + Wenn nur <off_status_interval> gesetzt wird, gilt dieser Wert für beide Zustände (eingeschaltet/ausgeschaltet).
      + Der Task liest zyklisch grundlegende Parameter vom Network Player wie z.B. (Power-Status , gewählter Eingang, Lautstärke etc.) und triggert notify/filelog Befehle.

      + Beispiel:

      +

        + Definition in der fhem.cfg Konfigurationsdatei:

        + + define NP_Player YAMAHA_NP 192.168.0.15
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp

        + # 60 Sekunden Intervall
        + define NP_Player YAMAHA_NP 192.168.0.15 60
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp

        + # 60 Sekunden Intervall für "off" und 10 Sekunden für "on"
        + define NP_Player YAMAHA_NP 192.168.0.15 60 10
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp +
        +
      +


    + + Set +
      + + set <name> <command> [<parameter>] + +

      + Aktuell sind folgende Befehle implementiert:
      + Die verfügbaren Eingänge des Network Players werden vom diesem gelesen und dynamisch in FHEM angepasst.

      + Bemerkung: Bitte bei den Befehlen und Parametern die Groß- und Kleinschreibung beachten.

      +


        + Verfügbare Befehle:

        +
      • cdTray  -   Öffnen und Schließen des CD-Fachs.
      • +
      • clockUpdate  -   Aktualisierung der Systemzeit des Network Players. Die Zeitinformation wird von dem FHEM Server bezogen, auf dem das Modul ausgeführt wird.
      • +
      • input [<parameter>]   -   Auswahl des Eingangs des NP. Der aktive Eingang wird vom Gerät gelesen und in FHEM dynamisch dargestellt (z.B. cd, tuner, aux1, aux2, ...).
      • +
      • mute [on|off]   -   Aktiviert/Deaktiviert die Stummschaltung.
      • +
      • off   -   Network Player ausschalten.
      • +
      • on   -   Network Player einschalten.
      • +
      • player [<parameter>]   -   Setzt Player relevante Befehle.
      • +
          +
        • play  -   play.
        • +
        • stop  -   stop.
        • +
        • pause  -   pause.
        • +
        • next  -   nächstes Audiostück.
        • +
        • prev  -   vorheriges Audiostück.
        • +
        • shuffleToggle  -   Umschaltung des Zufallswiedergabe.
        • +
        • repeatToggle  -   Umschaltung des Wiederholungsmodes.
        • +
        +
      • sleep [off|30min|60min|90min|120min]   -   Aktiviert/Deaktiviert den internen Sleep-Timer
      • +
      • standbyMode [eco|normal]   -   Umschaltung des Standby Modus.
      • +
      • statusRequest [<parameter>]   -   Abfrage des aktuellen Status des Network Players.
      • +
          +
        • systemConfig  -   Abfrage der Systemkonfiguration.
        • +
        • basicStatus  -   Abfrage der Elementarparameter (z.B. Lautstärke, Eingang, etc.)
        • +
        • playerStatus  -   Abfrage des Player-Status.
        • +
        • tunerStatus  -   Abfrage des Tuner-Status (z.B. FM Frequenz, Preset-Nummer, DAB Information etc.)
        • +
        • timerStatus  -   Abfrage des internen Wake-up timers.
        • +
        • networkInfo  -   Abfrage von Netzwerk-relevanten Informationen (z.B: IP-Adresse, Gateway-Adresse, MAC-address etc.)
        • +
        +
      • timerHour [0...23]   -   Setzt die Stunde des internen Wake-up Timers
      • +
      • timerMinute [0...59]   -   Setzt die Minute des internen Wake-up Timers
      • +
      • timerRepeat [once|every]   -   Setzt den Wiederholungsmodus des internen Wake-up Timers
      • +
      • timerVolume [<VOL_MIN>...<VOL_MAX>]   -   Setzt die Lautstärke des internen Wake-up Timers
      • +
      • timer [on|off]   -   Schaltet ein/aus den internen Wake-up Timer. (Bemerkung: Bevor der Wake-Up Timer gesetzt werden kann, müssen timerHour, timerMinute, timerRepeat and timerVolume zuvor gesetzt werden.)
      • +
      • tuner [<parameter>]   -   Tuner-relevante Befehle.
      • +
          +
        • bandDAB  -   Setzt das Tuner-Band auf DAB (falls verfügbar).
        • +
        • bandFM  -   Setzt das Tuner-Band auf FM.
        • +
        • tuneUp  -   Tuner Frequenz +.
        • +
        • tuneDown  -   Tuner Frquenz -.
        • +
        • presetUp  -   Tuner Voreinstellung hoch.
        • +
        • presetDown  -   Tuner Voreinstellung runter.
        • +
        +
      • tunerPresetDAB [1...30]   -   Setzt die DAB Voreinstellung.
      • +
      • tunerPresetFM [1...30]   -   Setzt die FM Voreinstellung.
      • +
      • volume [0...100]   -   Setzt den Lautstärkepegel in %
      • +
      • volumeStraight [<VOL_MIN>...<VOL_MAX>]   -   Setzt die absolute Lautstärke wie vom Gerät benutzt und angezeigt. Die Parameter <VOL_MIN> and <VOL_MAX> werden automatisch ermittelt.
      • +
      • volumeUp [<VOL_MIN>...<VOL_MAX>]   -   Erhöht die Lautstärke um einen absoluten Schritt. Die Parameter <VOL_MIN> and <VOL_MAX> werden automatisch ermittelt.
      • +
      • volumeDown [<VOL_MIN>...<VOL_MAX>]   -   Reduziert die Lautstärke um einen absoluten Schritt. Die Parameter <VOL_MIN> and <VOL_MAX> werden automatisch ermittelt.
      • +


      + Ein typisches Beispiel ist das Einschalten des Gerätes und das Umschalten auf den Lieblingsradiosender:

      + Beispieldefinition in der fhem.cfg Konfigurationsdatei:


      +
        + + define NP_player YAMAHA_NP 192.168.0.15 30 5
        + attr NP_player webCmd input:volume:mute:volumeDown:volumeUp +
        +


      + Folgender Code kann anschließend in die Datei 99_MyUtils.pm eingebunden werden:

      +
        + + sub startMyFavouriteRadioStation()
        + {
        +   fhem "set NP_player on";
        +   sleep 1;
        +   fhem "set NP_player input tuner";
        +   sleep 1;
        +   fhem "set NP_player tunerPresetDAB 1";
        +   sleep 1;
        +   fhem "set NP_player volume 30";
        + } +
        +


      + Bemerkung: Aufgrund der relativ langsamen Befehlsverarbeitung im Network Player im Vergleich zur asynchronen Ethernet-Kommunikation, kann es vorkommen, dass veraltete Statusinformationen zurückgesendet werden.
      + Aus diesem Grund wird empfohlen, während der Automatisierung zwischen den 'set' und 'get' Befehlen ein Delay einzubauen. Speziell beim Hochfahren des Network Players sollte dies beachtet werden.


      + Die Funktion kann jetzt in der FHEM Befehlszeile eingegeben oder in die Notify-Definitionen eingebunden werden.

      +
        + + {startMyFavouriteRadioStation()}

        +
        +
      +
    + + Get + + get <name> <reading> +

    + Aktuell liefert der Befehl 'get' ausschließlich Reading-Werte (s. Abschnitt "Readings").

    +
+ +
    + Attribute

    +
      +
        +
      • do_not_notify
      • +
      • readingFnAttributes

      • +
      • request-timeout

      • + Optionales Attribut, um das HTTP response timeout zu beeinflußen.
        + Mögliche Werte: 1...5 Sekunden. Default Wert ist 4 Sekunden.

        +
      • disable

      • + Optionales Attribut zum Deaktivieren des internen zyklischen Timers zum Aktualisieren des NP-Status. Manuelles Update ist nach wie vor möglich.
        + Mögliche Werte: 0 → Zyklisches Update aktiv., 1 → Zyklisches Update inaktiv.


        +
      +
    + Readings
    +
      +
        +

        Elementar-Readings:

        +
      • input - Aktivierter Eingang.
      • +
      • mute - Abfrage des Mute Status (on|off)
      • +
      • power - Abfrage des Power-Status (on|off)
      • +
      • presence - Abfrage der Geräteanwesenheit im Netzwerk (absent|present). Bemerkung: Falls abwesend ("absent"), lässt sich das Gerät nicht fernbedienen.
      • +
      • volume - Abfrage der aktuell eingestellten Lautstärke in % (0...100%)
      • +
      • volumeStraight - Abfrage der aktuellen absoluten Gerätelautstärke im Gerät (gerätespezifisch)
      • +
      • sleep - Abfrage des Sleep-Timer Status (30min|60min|90min|120min|off).
      • +
      • state - Abfrage des aktuellen Power Zustands und Anwesenheit (on|off|absent).
      • +

        Player Readings:

        +
      • playerPlaybackInfo - Abfrage des aktuellen Player Status (play|stop|pause).
      • +
      • playerDeviceType - Abfrage des Device Typs (ipod|msc).
      • +
      • playerIpodMode - Abfrage des *Pod/*Pad/*Phone Modus (normal|off)
      • +
      • playerRepeat - Abfrage des Wiederholungsmodus (one|all)
      • +
      • playerShuffle - Abfrage des Zufallswiedergabemodus (on|off)
      • +
      • playerPlayTime - Abfrage der aktuellen Spielzeit (HH:MM:SS).
      • +
      • playerTrackNumber - Abfrage der Audiotracknummer.
      • +
      • playerTotalTracks - Abfrage der Gesamtzahl der zu wiedergebenden Tracks.
      • +
      • playerArtist - Abfrage des Künstler (Artist) (falls verfügbar) der aktuellen Wiedergabe.
      • +
      • playerAlbum - Abfrage des Albumnamens (falls verfügbar) der aktuellen Wiedergabe.
      • +
      • playerSong - Abfrage des Tracknamens (falls verfügbar) der aktuellen Wiedergabe.
      • +
      • playerAlbumArtURL - Abfrage der Album URL (falls verfügbar) der aktuellen Wiedergabe.
      • +
      • playerAlbumArtID - Abfrage der AlbumArtID (falls verfügbar) der aktuellen Wiedergabe.
      • +
      • playerAlbumArtFormat - Abfrage des AlbumArt Formats (falls verfügbar) der aktuellen Wiedergabe.
      • +

        Tuner Readings:

        +
      • tunerBand - Abfrage des aktuellen Radio-Bandes (FM|DAB). DAB falls verfügbar.
      • +
      • tunerPresetFM - Abfrage der aktuellen FM Voreinstellung. Falls gespeichtert (1...30).
      • +
      • tunerFrequencyFM - Abfrage der aktuellen FM Frequenz. (xxx.xx MHz)
      • +
      • tunerProgramServiceFM - Abfrage des FM Sendernamen.
      • +
      • tunerRadioTextAFM - Abfrage des Radio Text A des FM Senders.
      • +
      • tunerRadioTextBFM - Abfrage des Radio Text B des FM Senders.
      • +
      • tunerPresetDAB - Abfrage der aktuellen DAB Voreinstellung. Falls gespeichtert (1...30).
      • +
      • tunerServiceLabelDAB - Abfrage des DAB Sendernamen.
      • +
      • tunerChannelLabelDAB - Abfrage des Channel Labels des gewählten DAB Senders.
      • +
      • tunerDLSDAB - Abfrage des 'Dynamic Label Segment' des gewählten DAB Senders.
      • +
      • tunerEnsembleLabelDAB - Abfrage des 'Ensemble Label' des gewählten DAB Senders.
      • +

        Timer Readings:

        +
      • timer - Abfrage des Time Modus (Wecker) (on|off).
      • +
      • timerRepeat - Abfrage des Timer Wiederholungs Modus (once|every).
      • +
      • timerStartTime - Abfrage der Timer Startzeit (HH:MM).
      • +
      • timerVolumeLevel - Abfrage der Timer-Lautstärke.
      • +
      +

    + Bemerkung des Entwicklers

    +
      + Trivial: Um das Gerät fernbedienen zu können, muss es an das Ethernet-Netzwerk angeschlossen und erreichbar sein.
      + Das Gerät muss sich im standbyMode "Normal" befinden, um es fergesteuert einzuschalten.
      + Das Abschalten funktioniert auch standbyMode "Normal" Modus.
      +

    +
+=end html_DE +=cut diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt index 1cd75b254..f0cc5b9b8 100644 --- a/fhem/MAINTAINER.txt +++ b/fhem/MAINTAINER.txt @@ -1,3 +1,4 @@ + maintainer of the file to do the change. The third column specifies, where/how the maintainer should be contacted. If @@ -202,6 +203,7 @@ FHEM/70_Pushover.pm Johannes_B http://forum.fhem.de Unterstue FHEM/70_PushNotifier.pm xusader http://forum.fhem.de Unterstuetzende Dienste FHEM/71_YAMAHA_AVR.pm markusbloch http://forum.fhem.de Multimedia FHEM/71_YAMAHA_BD.pm markusbloch http://forum.fhem.de Multimedia +FHEM/71_YAMAHA_NP.pm ra666ack http://forum.fhem.de Multimedia FHEM/72_FB_CALLMONITOR.pm markusbloch http://forum.fhem.de Unterstuetzende Dienste FHEM/72_FRITZBOX.pm tupol http://forum.fhem.de FRITZBOX (Link senden: http://forum.fhem.de/index.php?action=pm;sa=send;u=5432) FHEM/73_km200.pm sailor http://forum.fhem.de Heizungssteuerung/Raumklima