71_YAMAHA_NP.pm 100 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372
  1. ##############################################################################
  2. #
  3. # $Id: 71_YAMAHA_NP.pm 11114 2016-03-23 06:41:10Z ra666ack $
  4. #
  5. # 71_YAMAHA_NP.pm
  6. #
  7. # Fhem Perl module for controlling the Yamaha PianoCraft(TM) HiFi
  8. # Network Audiosystem MCR-N560(D) over Ethernet.
  9. # The system is also marketed as CRX-N560(D).
  10. #
  11. # The module might also work with other devices such as
  12. # NP-S2000, CD-N500, CD-N301, R-N500, R-N301 or any other device
  13. # implementing the Yamaha Network Player Controller(TM) protocol:
  14. #
  15. # i*S:
  16. # https://itunes.apple.com/us/app/network-player-controller-us/id467502483?mt=8
  17. #
  18. # Andr*id:
  19. # https://play.google.com/store/apps/details?id=com.yamaha.npcontroller
  20. #
  21. # Since the used communication protocol is undisclosed the module bases on
  22. # entirely reverse engineered implementation.
  23. # Some features may be unavailable.
  24. # (Online check for new firmware was excluded intentionally.)
  25. #
  26. # Copyright by Radoslaw Watroba (ra666ack a t 9 m a 1 l d 0 t c 0 m)
  27. #
  28. # This file is part of fhem.
  29. #
  30. # Fhem is free software: you can redistribute it and/or modify
  31. # it under the terms of the GNU General Public License as published by
  32. # the Free Software Foundation, either version 2 of the License, or
  33. # (at your option) any later version.
  34. #
  35. # Fhem is distributed in the hope that it will be useful,
  36. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  38. # GNU General Public License for more details.
  39. #
  40. # You should have received a copy of the GNU General Public License
  41. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  42. #
  43. ##############################################################################
  44. package main;
  45. use strict;
  46. use warnings;
  47. use Time::HiRes qw(gettimeofday sleep);
  48. use Time::Piece;
  49. use POSIX qw{strftime};
  50. use HttpUtils;
  51. use List::Util qw(first);
  52. ###################################
  53. sub YAMAHA_NP_Initialize
  54. {
  55. my ($hash) = @_;
  56. $hash->{DefFn} = "YAMAHA_NP_Define";
  57. $hash->{GetFn} = "YAMAHA_NP_Get";
  58. $hash->{SetFn} = "YAMAHA_NP_Set";
  59. $hash->{AttrFn} = "YAMAHA_NP_Attr";
  60. $hash->{UndefFn} = "YAMAHA_NP_Undefine";
  61. $hash->{AttrList} = "do_not_notify:0,1 disable:0,1 request-timeout:1,2,3,4,5 model auto-update-player-readings:1,0 auto-update-tuner-readings:1,0 smooth-volume-change:1,0 ".$readingFnAttributes;
  62. return;
  63. }
  64. ###################################
  65. sub YAMAHA_NP_GetStatus
  66. {
  67. my ($hash, $local) = @_;
  68. my $name = $hash->{NAME};
  69. my $power;
  70. # Local means a timer reset by the module itself
  71. $local = 0 unless(defined($local));
  72. return "" if((!defined($hash->{helper}{ADDRESS})) or (!defined($hash->{helper}{OFF_INTERVAL})) or (!defined($hash->{helper}{ON_INTERVAL})));
  73. my $device = $hash->{helper}{ADDRESS};
  74. # Get model and firmware information
  75. if(not defined($hash->{MODEL}))
  76. {
  77. YAMAHA_NP_getModel($hash);
  78. # Get network related information from the NP
  79. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Info>GetParam</Info></Network></Misc></System></YAMAHA_AV>", "statusRequest", "networkInfo", 0);
  80. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Info>GetParam</Info></Network></Misc></System></YAMAHA_AV>", "statusRequest", "systemConfig", 0);
  81. YAMAHA_NP_ResetTimer($hash, 1);
  82. return;
  83. }
  84. # Get available inputs if not defined
  85. if((not defined($hash->{helper}{INPUTS}) or length($hash->{helper}{INPUTS}) == 0))
  86. {
  87. YAMAHA_NP_getInputs($hash);
  88. YAMAHA_NP_ResetTimer($hash, 1);
  89. return;
  90. }
  91. # Timer readings available?
  92. if(not defined($hash->{READINGS}{timerVolume}))
  93. {
  94. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Timer><Mode>GetParam</Mode></Timer></Misc></System></YAMAHA_AV>", "statusRequest", "getTimer", 0);
  95. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Timer><Param>GetParam</Param></Timer></Misc></System></YAMAHA_AV>", "statusRequest", "timerStatus", 0);
  96. }
  97. # Standby mode readings available?
  98. if(not defined($hash->{READINGS}{standbyMode}))
  99. {
  100. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Power_Control><Saving>GetParam</Saving></Power_Control></System></YAMAHA_AV>", "statusRequest", "standbyMode", 0);
  101. }
  102. # DAB preset readings available? Only for the DAB model.
  103. if (defined $hash->{MODEL})
  104. {
  105. my $model = $hash->{MODEL};
  106. if ($model eq "CRX-N560D")
  107. {
  108. if(not defined($hash->{READINGS}{tunerPresetDABItem_01}))
  109. {
  110. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Control><Preset><DAB><Preset_Sel_Item>GetParam</Preset_Sel_Item></DAB></Preset></Play_Control></Tuner></YAMAHA_AV>", "statusRequest", "tunerPresetDAB", 0);
  111. }
  112. }
  113. }
  114. # FM preset readings available?
  115. if(not defined($hash->{READINGS}{tunerPresetFMItem_01}))
  116. {
  117. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Control><Preset><FM><Preset_Sel_Item>GetParam</Preset_Sel_Item></FM></Preset></Play_Control></Tuner></YAMAHA_AV>", "statusRequest", "tunerPresetFM", 0);
  118. }
  119. # Basic status request
  120. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Basic_Status>GetParam</Basic_Status></System></YAMAHA_AV>", "statusRequest", "basicStatus", 0);
  121. if(defined($hash->{READINGS}{input}))
  122. {
  123. # Get dynamic tuner readings
  124. if((AttrVal($name, "auto-update-tuner-readings","1") eq "1") and ($hash->{READINGS}{input}{VAL} eq "tuner") and ($hash->{READINGS}{power}{VAL} eq "on"))
  125. {
  126. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Info>GetParam<\/Play_Info><\/Tuner><\/YAMAHA_AV>", "statusRequest", "tunerStatus", 0);
  127. if($hash->{READINGS}{tunerBand}{VAL} eq "FM")
  128. {
  129. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Control><Preset><FM><Preset_Sel_Item>GetParam</Preset_Sel_Item></FM></Preset></Play_Control></Tuner></YAMAHA_AV>", "statusRequest", "tunerPresetFM", 0);
  130. blankTunerDABReadings($hash);
  131. }
  132. elsif($hash->{READINGS}{tunerBand}{VAL} eq "DAB")
  133. {
  134. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Control><Preset><DAB><Preset_Sel_Item>GetParam</Preset_Sel_Item></DAB></Preset></Play_Control></Tuner></YAMAHA_AV>", "statusRequest", "tunerPresetDAB", 0);
  135. blankTunerFMReadings($hash);
  136. }
  137. # Reset player readings
  138. blankPlayerReadings($hash);
  139. }
  140. elsif(AttrVal($name, "auto-update-player-readings", "1") eq "1" and ($hash->{READINGS}{input}{VAL} ne "tuner") and ($hash->{READINGS}{power}{VAL} eq "on"))
  141. {
  142. # Inputs don't use any player readings. Blank them.
  143. if($hash->{READINGS}{input}{VAL} eq "aux1" or
  144. $hash->{READINGS}{input}{VAL} eq "aux2" or
  145. $hash->{READINGS}{input}{VAL} eq "digital1" or
  146. $hash->{READINGS}{input}{VAL} eq "digital2" or
  147. $hash->{READINGS}{input}{VAL} eq "airplay")
  148. {
  149. blankPlayerReadings($hash);
  150. }
  151. else
  152. {
  153. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Player><Play_Info>GetParam<\/Play_Info><\/Player><\/YAMAHA_AV>", "statusRequest", "playerStatus", 0);
  154. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Player><List_Info>GetParam</List_Info></Player></YAMAHA_AV>", "playerListGetList", "playerListGetList", 0);
  155. }
  156. # Reset tuner readings
  157. readingsSingleUpdate($hash, "tunerBand", "", 1);
  158. blankTunerDABReadings($hash);
  159. blankTunerFMReadings($hash);
  160. }
  161. }
  162. # Reset Timer for the next loop.
  163. YAMAHA_NP_ResetTimer($hash) unless($local == 1);
  164. return;
  165. }
  166. ###################################
  167. sub YAMAHA_NP_Get
  168. {
  169. my ($hash, @a) = @_;
  170. my $what;
  171. my $return;
  172. return "Argument missing." if(int(@a) != 2);
  173. $what = $a[1];
  174. if(exists($hash->{READINGS}{$what}))
  175. {
  176. if(defined($hash->{READINGS}{$what}))
  177. {
  178. return $hash->{READINGS}{$what}{VAL};
  179. }
  180. else
  181. {
  182. return "no such reading: $what";
  183. }
  184. }
  185. else
  186. {
  187. $return = "Unknown argument $what, choose one of";
  188. foreach my $reading (keys %{$hash->{READINGS}})
  189. {
  190. $return .= " $reading:noArg";
  191. }
  192. return $return;
  193. }
  194. }
  195. ###################################
  196. sub YAMAHA_NP_Set
  197. {
  198. my ($hash, @a) = @_;
  199. my $name = $hash->{NAME};
  200. my $address = $hash->{helper}{ADDRESS};
  201. # Get model info in case not defined
  202. if(not defined($hash->{MODEL}) or not defined($hash->{FIRMWARE}))
  203. {
  204. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Info>GetParam</Info></Network></Misc></System></YAMAHA_AV>", "statusRequest", "networkInfo",0);
  205. YAMAHA_NP_getModel($hash);
  206. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Info>GetParam</Info></Network></Misc></System></YAMAHA_AV>", "statusRequest", "systemConfig", 0);
  207. }
  208. if(not defined($hash->{helper}{VOLUMESTRAIGHTMIN}) and not defined($hash->{helper}{VOLUMESTRAIGHTMAX}))
  209. {
  210. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Info>GetParam</Info></Network></Misc></System></YAMAHA_AV>", "statusRequest", "systemConfig", 0);
  211. }
  212. # Get available inputs in case of empty list
  213. if(not defined($hash->{helper}{INPUTS}) or length($hash->{helper}{INPUTS}) == 0)
  214. {
  215. YAMAHA_NP_getInputs($hash);
  216. }
  217. my $inputs_piped = defined($hash->{helper}{INPUTS}) ? YAMAHA_NP_Param2Fhem(lc($hash->{helper}{INPUTS}), 0) : "" ;
  218. my $inputs_comma = defined($hash->{helper}{INPUTS}) ? YAMAHA_NP_Param2Fhem(lc($hash->{helper}{INPUTS}), 1) : "" ;
  219. # Setting default values. Update from device during existing communication.
  220. my $volumeStraightMin = defined($hash->{helper}{VOLUMESTRAIGHTMIN}) ? $hash->{helper}{VOLUMESTRAIGHTMIN} : "0";
  221. my $volumeStraightMax = defined($hash->{helper}{VOLUMESTRAIGHTMAX}) ? $hash->{helper}{VOLUMESTRAIGHTMAX} : "60";
  222. return "No Argument given" if(!defined($a[1]));
  223. my $what = $a[1];
  224. my $usage = "";
  225. # DAB available? Suffix D stands for DAB. "CRX-N560D"
  226. if (defined($hash->{MODEL}))
  227. {
  228. my $model = $hash->{MODEL};
  229. $usage = "Unknown argument $what, choose one of ".
  230. "on:noArg ".
  231. "off:noArg ".
  232. "timerRepeat:once,every ".
  233. "timerSet:noArg ".
  234. "sleep:off,30min,60min,90min,120min ".
  235. "volumeStraight:slider,".$volumeStraightMin.",1,".$volumeStraightMax." ".
  236. "volume:slider,0,1,100 ".
  237. "volumeUp:noArg ".
  238. "volumeDown:noArg ".
  239. "timerVolume:slider,".$volumeStraightMin.",1,".$volumeStraightMax." ".
  240. "mute:on,off ".
  241. (exists($hash->{helper}{INPUTS})?"input:".$inputs_comma." ":"").
  242. "standbyMode:eco,normal ".
  243. "cdTray:noArg ".
  244. "timer:on,off ".
  245. (($model eq "CRX-N560D") ? "statusRequest:basicStatus,mediaRendererDesc,playerStatus,standbyMode,systemConfig,timerStatus,tunerPresetDAB,tunerPresetFM,tunerStatus ":
  246. "statusRequest:basicStatus,mediaRendererDesc,playerStatus,standbyMode,systemConfig,timerStatus,tunerPresetFM,tunerStatus ").
  247. (($model eq "CRX-N560D") ? "tuner:bandDAB,bandFM,presetUp,presetDown,tuneDown,tuneUp " : "tuner:bandFM,presetUp,presetDown,tuneDown,tuneUp ").
  248. (($model eq "CRX-N560D") ? "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 " : "").
  249. "player:play,stop,pause,next,prev,shuffleToggle,repeatToggle ".
  250. "clockUpdate:noArg ".
  251. "dimmer:1,2,3 ".
  252. "playerListGetList:noArg ".
  253. "playerListJumpLine ".
  254. "playerListSelectLine ".
  255. "playerListCursorReturn:noArg ".
  256. "playerListCursorDown:noArg ".
  257. "playerListCursorUp:noArg ".
  258. "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 ".
  259. "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 ".
  260. "tunerFMFrequency ".
  261. "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 ";
  262. Log3 $name, 5, "Model: $model.";
  263. }
  264. Log3 $name, 5, "YAMAHA_NP ($name) - set ".join(" ", @a);
  265. # Processing of SET commands.
  266. # Device Power ON/OFF
  267. #
  268. if($what eq "on")
  269. {
  270. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Power_Control><Power>On</Power></Power_Control></System></YAMAHA_AV>" ,$what, "On", 0);
  271. }
  272. elsif($what eq "off")
  273. {
  274. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Power_Control><Power>Standby</Power></Power_Control></System></YAMAHA_AV>", $what, "Standby", 0);
  275. }
  276. elsif($what eq "input")
  277. {
  278. if(defined($a[2]))
  279. {
  280. if($hash->{READINGS}{power}{VAL} eq "on")
  281. {
  282. if(not $inputs_piped eq "")
  283. {
  284. if($a[2] =~ /^($inputs_piped)$/)
  285. {
  286. my $command = YAMAHA_NP_getParamName($hash, $a[2], $hash->{helper}{INPUTS});
  287. if(defined($command) and length($command) > 0)
  288. {
  289. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Input><Input_Sel>".$command."</Input_Sel></Input></System></YAMAHA_AV>", $what, $a[2], 0);
  290. }
  291. else
  292. {
  293. return "invalid input: ".$a[2];
  294. }
  295. }
  296. else
  297. {
  298. return $usage;
  299. }
  300. }
  301. else
  302. {
  303. return "No inputs avaible. Please try an statusRequest.";
  304. }
  305. }
  306. else
  307. {
  308. return "Switch device on first.";
  309. }
  310. }
  311. else
  312. {
  313. return $inputs_piped eq "" ? "No inputs available. Please try an statusRequest first." : "No input parameter given.";
  314. }
  315. }
  316. #
  317. # MUTE
  318. #
  319. elsif($what eq "mute")
  320. {
  321. if($hash->{READINGS}{power}{VAL} ne "on")
  322. {
  323. return "Power on the device first.";
  324. }
  325. if(defined($a[2]))
  326. {
  327. if($a[2] =~ /^(on|off)$/)
  328. {
  329. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Mute>".ucfirst($a[2])."</Mute></Volume></System></YAMAHA_AV>", $what, ucfirst($a[2]), 0);
  330. }
  331. else
  332. {
  333. return $usage;
  334. }
  335. }
  336. }
  337. #
  338. # DISPLAY DIMMER
  339. #
  340. elsif($what eq "dimmer")
  341. {
  342. if($a[2] >= 1 and $a[2] <= 3)
  343. {
  344. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Misc><Display><FL_Dimmer>".$a[2]."</FL_Dimmer></Display></Misc></System></YAMAHA_AV>", $what, $a[2], 0);
  345. }
  346. else
  347. {
  348. return "Dimmer value must be 1 .. 3";
  349. }
  350. }
  351. #
  352. # VOLUME
  353. #
  354. # VolumeStraight is device specific e.g. 0...60, Volume 0...100, VolumeUp/Down one step
  355. #
  356. elsif($what =~ /^(volumeStraight|volume|volumeUp|volumeDown)$/)
  357. {
  358. my $target_volume;
  359. my $minVolume = $hash->{helper}{VOLUMESTRAIGHTMIN};
  360. my $maxVolume = $hash->{helper}{VOLUMESTRAIGHTMAX};
  361. if($hash->{READINGS}{power}{VAL} ne "on")
  362. {
  363. return "Power on the device first.";
  364. }
  365. if($what eq "volumeDown")
  366. {
  367. $hash->{helper}{volumeChangeDir} = "DOWN";
  368. $target_volume = $hash->{READINGS}{volumeStraight}{VAL} - 1;
  369. $hash->{helper}{targetVolume} = $target_volume;
  370. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".$target_volume."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", $target_volume, 0);
  371. }
  372. elsif($what eq "volumeUp")
  373. {
  374. $hash->{helper}{volumeChangeDir} = "UP";
  375. $target_volume = $hash->{READINGS}{volumeStraight}{VAL} + 1;
  376. $hash->{helper}{targetVolume} = $target_volume;
  377. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".$target_volume."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", $target_volume, 0);
  378. }
  379. else
  380. {
  381. if($what eq "volume")
  382. {
  383. if($a[2] >= 0 and $a[2] <= 100)
  384. {
  385. $target_volume = YAMAHA_NP_volume_rel2abs($hash, $a[2]);
  386. }
  387. else
  388. {
  389. return "Volume must be in the range 1...100.";
  390. }
  391. }
  392. elsif($what eq "volumeStraight")
  393. {
  394. if($a[2] >= $minVolume and $a[2] <= $maxVolume)
  395. {
  396. $target_volume = $a[2];
  397. }
  398. else
  399. {
  400. return "Volume must be in the range $minVolume...$maxVolume.";
  401. }
  402. }
  403. $hash->{helper}{targetVolume} = $target_volume;
  404. if(AttrVal($name, "smooth-volume-change", "1") eq "1" )
  405. {
  406. if($target_volume < $hash->{READINGS}{volumeStraight}{VAL})
  407. {
  408. $hash->{helper}{volumeChangeDir} = "DOWN";
  409. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".($hash->{READINGS}{volumeStraight}{VAL} - 1)."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", ($hash->{READINGS}{volumeStraight}{VAL} - 1), 0);
  410. }
  411. elsif($target_volume > $hash->{READINGS}{volumeStraight}{VAL})
  412. {
  413. $hash->{helper}{volumeChangeDir} = "UP";
  414. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".($hash->{READINGS}{volumeStraight}{VAL} + 1)."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", ($hash->{READINGS}{volumeStraight}{VAL} + 1), 0);
  415. }
  416. elsif($target_volume eq $hash->{READINGS}{volumeStraight}{VAL})
  417. {
  418. $hash->{helper}{volumeChangeDir} = "EQUAL";
  419. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".($hash->{READINGS}{volumeStraight}{VAL})."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", ($hash->{READINGS}{volumeStraight}{VAL}), 0);
  420. }
  421. }
  422. else
  423. {
  424. $hash->{helper}{volumeChangeDir} = "EQUAL";
  425. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".$target_volume."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", $a[2], 0);
  426. }
  427. }
  428. Log3 $name, 4, "YAMAHA_NP ($name) - new target volume: $target_volume";
  429. }
  430. #
  431. # SLEEP
  432. #
  433. elsif($what eq "sleep")
  434. {
  435. if($a[2] eq "off")
  436. {
  437. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Power_Control><Sleep>Off</Sleep></Power_Control></System></YAMAHA_AV>", $what, $a[2], 0);
  438. }
  439. elsif($a[2] =~ /^(30min|60min|90min|120min)$/)
  440. {
  441. if($a[2] =~ /(.+)min/)
  442. {
  443. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Power_Control><Sleep>".$1." min</Sleep></Power_Control></System></YAMAHA_AV>", $what, $a[2], 0);
  444. }
  445. }
  446. else
  447. {
  448. return $usage;
  449. }
  450. }
  451. #
  452. # TUNER
  453. #
  454. elsif($what eq "tuner")
  455. {
  456. if($a[2] eq "presetUp")
  457. {
  458. YAMAHA_NP_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Preset><Preset_Sel>Next</Preset_Sel></Preset></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  459. }
  460. elsif($a[2] eq "presetDown")
  461. {
  462. YAMAHA_NP_SendCommand($hash,"<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Preset><Preset_Sel>Prev</Preset_Sel></Preset></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  463. }
  464. elsif($a[2] eq "tuneUp")
  465. {
  466. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Service>Next</Service></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  467. }
  468. elsif($a[2] eq "tuneDown")
  469. {
  470. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Service>Prev</Service></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  471. }
  472. elsif($a[2] eq "bandDAB")
  473. {
  474. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Band>DAB</Band></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  475. }
  476. elsif($a[2] eq "bandFM")
  477. {
  478. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Band>FM</Band></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  479. }
  480. else
  481. {
  482. return $usage;
  483. }
  484. }
  485. #
  486. # Player
  487. #
  488. elsif($what eq "player")
  489. {
  490. if($a[2] =~ /^(play|pause|stop|next|prev)$/)
  491. {
  492. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><Play_Control><Playback>".ucfirst($a[2])."</Playback></Play_Control></Player></YAMAHA_AV>", $what, $a[2], 0);
  493. }
  494. elsif($a[2] eq "shuffleToggle")
  495. {
  496. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><Play_Control><Play_Mode><Shuffle>Toggle</Shuffle></Play_Mode></Play_Control></Player></YAMAHA_AV>", $what, $a[2], 0);
  497. }
  498. elsif($a[2] eq "repeatToggle")
  499. {
  500. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><Play_Control><Play_Mode><Repeat>Toggle</Repeat></Play_Mode></Play_Control></Player></YAMAHA_AV>", $what, $a[2], 0);
  501. }
  502. else
  503. {
  504. return $usage;
  505. }
  506. }
  507. #
  508. # PlayerGetList
  509. #
  510. elsif($what eq "playerListGetList")
  511. {
  512. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Player><List_Info>GetParam</List_Info></Player></YAMAHA_AV>", $what, "playerListGetList", 0);
  513. }
  514. elsif($what eq "playerListCursorReturn")
  515. {
  516. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><List_Control><Cursor>Return</Cursor></List_Control></Player></YAMAHA_AV>", $what, "playerListCursorReturn", 0);
  517. }
  518. elsif($what eq "playerListCursorDown")
  519. {
  520. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><List_Control><Cursor>Down</Cursor></List_Control></Player></YAMAHA_AV>", $what, "playerListCursorDown", 0);
  521. }
  522. elsif($what eq "playerListCursorUp")
  523. {
  524. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><List_Control><Cursor>Up</Cursor></List_Control></Player></YAMAHA_AV>", $what, "playerListCursorUp", 0);
  525. }
  526. elsif($what eq "playerListJumpLine")
  527. {
  528. if($a[2] ne "")
  529. {
  530. if($a[2] =~ /^\d+$/ and $a[2] >= 1)
  531. {
  532. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><List_Control><Jump_Line>".$a[2]."</Jump_Line></List_Control></Player></YAMAHA_AV>", $what, $a[2], 0);
  533. }
  534. else
  535. {
  536. return "Argument must be numeric and >= 1.";
  537. }
  538. }
  539. else
  540. {
  541. return "No argument given.";
  542. }
  543. }
  544. #
  545. # PlayerListSelectLine
  546. #
  547. elsif($what eq "playerListSelectLine")
  548. {
  549. if($a[2] ne "")
  550. {
  551. if($a[2] =~ /^\d+$/ and $a[2] >= 1)
  552. {
  553. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Player><List_Control><Direct_Sel>Line_".$a[2]."</Direct_Sel></List_Control></Player></YAMAHA_AV>", $what, $a[2], 0);
  554. }
  555. else
  556. {
  557. return "Argument must be numeric and >= 1.";
  558. }
  559. }
  560. else
  561. {
  562. return "No argument given.";
  563. }
  564. }
  565. #
  566. # Standby Mode
  567. #
  568. elsif($what eq "standbyMode")
  569. {
  570. if(($a[2] eq "eco") or ($a[2] eq "normal"))
  571. {
  572. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Power_Control><Saving>".ucfirst($a[2])."</Saving></Power_Control></System></YAMAHA_AV>", $what, $a[2], 0);
  573. }
  574. else
  575. {
  576. return $usage;
  577. }
  578. }
  579. #
  580. # CD Tray
  581. #
  582. elsif($what eq "cdTray")
  583. {
  584. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Misc><Tray>Open/Close</Tray></Misc></System></YAMAHA_AV>", $what, "Open/Close", 0);
  585. }
  586. #
  587. # Clock Update
  588. #
  589. elsif($what eq "clockUpdate")
  590. {
  591. my $clockUpdateCurrentTime = Time::Piece->new();
  592. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Misc><Clock><Param>".($clockUpdateCurrentTime->strftime('%Y:%m:%d:%H:%M:%S'))."</Param></Clock></Misc></System></YAMAHA_AV>", $what, ($clockUpdateCurrentTime->strftime('%Y:%m:%d:%H:%M:%S')), 0);
  593. }
  594. #
  595. # Status Request
  596. #
  597. elsif($what eq "statusRequest")
  598. {
  599. if($a[2] eq "systemConfig")
  600. {
  601. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Config>GetParam</Config></System></YAMAHA_AV>", $what, $a[2], 0);
  602. }
  603. elsif($a[2] eq "playerStatus")
  604. {
  605. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Player><Play_Info>GetParam<\/Play_Info><\/Player><\/YAMAHA_AV>", $what, $a[2], 0);
  606. }
  607. elsif($a[2] eq "tunerStatus")
  608. {
  609. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Info>GetParam<\/Play_Info><\/Tuner><\/YAMAHA_AV>", $what, $a[2], 0);
  610. }
  611. elsif($a[2] eq "basicStatus")
  612. {
  613. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Basic_Status>GetParam</Basic_Status></System></YAMAHA_AV>", $what, $a[2], 0);
  614. }
  615. elsif($a[2] eq "timerStatus")
  616. {
  617. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Timer><Mode>GetParam</Mode></Timer></Misc></System></YAMAHA_AV>", $what, "getTimer", 0);
  618. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Timer><Param>GetParam</Param></Timer></Misc></System></YAMAHA_AV>", $what, $a[2], 0);
  619. }
  620. elsif($a[2] eq "networkInfo")
  621. {
  622. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Misc><Network><Info>GetParam</Info></Network></Misc></System></YAMAHA_AV>", $what, $a[2], 0);
  623. }
  624. elsif($a[2] eq "tunerPresetFM")
  625. {
  626. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Control><Preset><FM><Preset_Sel_Item>GetParam</Preset_Sel_Item></FM></Preset></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  627. }
  628. elsif($a[2] eq "tunerPresetDAB")
  629. {
  630. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><Tuner><Play_Control><Preset><DAB><Preset_Sel_Item>GetParam</Preset_Sel_Item></DAB></Preset></Play_Control></Tuner></YAMAHA_AV>", $what, $a[2], 0);
  631. }
  632. elsif($a[2] eq "standbyMode")
  633. {
  634. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Power_Control><Saving>GetParam</Saving></Power_Control></System></YAMAHA_AV>", $what, $a[2], 0);
  635. }
  636. elsif($a[2] eq "mediaRendererDesc")
  637. {
  638. YAMAHA_NP_getMediaRendererDesc($hash);
  639. }
  640. else
  641. {
  642. return $usage;
  643. }
  644. }
  645. #
  646. # Timer
  647. #
  648. elsif($what eq "timer")
  649. {
  650. if($a[2] eq "on")
  651. {
  652. # Check if standbyMode == 'Normal'
  653. if($hash->{READINGS}{standbyMode}{VAL} eq "normal")
  654. {
  655. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Misc><Timer><Mode>".ucfirst($a[2])."</Mode></Timer></Misc></System></YAMAHA_AV>", $what, $a[2], 0);
  656. }
  657. else
  658. {
  659. return "Set 'standbyMode normal' first.";
  660. }
  661. }
  662. elsif($a[2] eq "off")
  663. {
  664. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Misc><Timer><Mode>".ucfirst($a[2])."</Mode></Timer></Misc></System></YAMAHA_AV>", $what, $a[2], 0);
  665. }
  666. else
  667. {
  668. return $usage;
  669. }
  670. }
  671. #
  672. # Timer Hour
  673. #
  674. elsif($what eq "timerHour")
  675. {
  676. if((int($a[2]) >= 0) and (int($a[2]) <= 23))
  677. {
  678. $hash->{helper}{timerHour} = $a[2];
  679. }
  680. else
  681. {
  682. return $usage;
  683. }
  684. }
  685. #
  686. # Timer Minute
  687. #
  688. elsif($what eq "timerMinute")
  689. {
  690. if((int($a[2]) >= 0) and (int($a[2]) <= 59))
  691. {
  692. $hash->{helper}{timerMinute} = $a[2];
  693. }
  694. else
  695. {
  696. return $usage;
  697. }
  698. }
  699. #
  700. # Timer Repeat
  701. #
  702. elsif($what eq "timerRepeat")
  703. {
  704. if($a[2] eq "once" or $a[2] eq "every")
  705. {
  706. $hash->{helper}{timerRepeat} = ucfirst($a[2]);
  707. }
  708. else
  709. {
  710. return $usage;
  711. }
  712. }
  713. #
  714. # TimerVolume
  715. #
  716. elsif($what eq "timerVolume")
  717. {
  718. # if lower than minimum VOLUMESTRAIGHTMIN or higher than max VOLUMESTRAIGHTMAX set target volume to the corresponding limits
  719. if($a[2] >= $hash->{helper}{VOLUMESTRAIGHTMIN} and $a[2] <= $hash->{helper}{VOLUMESTRAIGHTMAX})
  720. {
  721. $hash->{helper}{timerVolume} = $a[2];
  722. }
  723. else
  724. {
  725. return "Please use straight device volume range :".$hash->{helper}{VOLUMESTRAIGHTMIN}."...".$hash->{helper}{VOLUMESTRAIGHTMAX}.".";
  726. }
  727. }
  728. #
  729. # TimerSet
  730. #
  731. elsif($what eq "timerSet")
  732. {
  733. if(defined($hash->{helper}{timerHour}) and defined($hash->{helper}{timerMinute}) and defined($hash->{helper}{timerRepeat}) and defined($hash->{helper}{timerVolume}))
  734. {
  735. # Configure Timer according to provided parameters
  736. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Misc><Timer><Param><Start_Time>".sprintf("%02d", $hash->{helper}{timerHour}).":".sprintf("%02d", $hash->{helper}{timerMinute})."</Start_Time><Volume>".$hash->{helper}{timerVolume}."</Volume><Repeat>".$hash->{helper}{timerRepeat}."</Repeat></Param></Timer></Misc></System></YAMAHA_AV>", $what, $a[2], 0);
  737. }
  738. else
  739. {
  740. return "Please, define timerHour, timerMinute, timerRepeat and timerVolume first.";
  741. }
  742. }
  743. #
  744. # Tuner Preset DAB
  745. #
  746. elsif($what eq "tunerPresetDAB")
  747. {
  748. if($a[2] >= 1 and $a[2] <= 30 and $hash->{MODEL} eq "CRX-N560D")
  749. {
  750. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Preset><DAB><Preset_Sel>".$a[2]."<\/Preset_Sel><\/DAB><\/Preset><\/Play_Control><\/Tuner></YAMAHA_AV>", "tunerPresetDAB", $a[2], 0);
  751. }
  752. else
  753. {
  754. return $usage;
  755. }
  756. }
  757. #
  758. # Tuner Preset FM
  759. #
  760. elsif($what eq "tunerPresetFM")
  761. {
  762. if($a[2] >= 1 and $a[2] <= 30)
  763. {
  764. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Preset><FM><Preset_Sel>".$a[2]."<\/Preset_Sel><\/FM><\/Preset><\/Play_Control><\/Tuner></YAMAHA_AV>", "tunerPresetFM", $a[2], 0);
  765. }
  766. else
  767. {
  768. return $usage;
  769. }
  770. }
  771. #
  772. # Tuner FM Frequency
  773. #
  774. elsif($what eq "tunerFMFrequency")
  775. {
  776. if(length($a[2]) <= 6 and length($a[2]) >= 5) # Check the string length (x)xx.xx
  777. {
  778. if ( $a[2] =~ /^[0-9,.E]+$/ ) # Check if value is numeric
  779. {
  780. if(substr($a[2], -3, 1) eq '.') # Check for decimal point
  781. {
  782. if( $a[2] >= 87.50 and $a[2] <= 108.00) # Check if within the value range
  783. {
  784. my $lastDigit = substr($a[2], -1, 1);
  785. if(($lastDigit eq "0") or ($lastDigit eq "5"))
  786. {
  787. my $frequency = $a[2];
  788. $frequency =~ s/\.//; # Remove decimal point
  789. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><Tuner><Play_Control><Tuning><FM><Freq>".$frequency."<\/Freq><\/FM><\/Tuning><\/Play_Control><\/Tuner></YAMAHA_AV>", "tunerFMFrequency", $a[2], 0);
  790. }
  791. else
  792. {
  793. return "Last digit must be '0' or '5'";
  794. }
  795. }
  796. else
  797. {
  798. return "Frequency value must be in the range 87.50 ... 108.00 of the format (x)xx.xx";
  799. }
  800. }
  801. else
  802. {
  803. return "Missing decimal point. Accepted format (x)xx.xx";
  804. }
  805. }
  806. else
  807. {
  808. return "Frequency value must be numeric in the range 87.50 ... 108.00 of the format (x)xx.xx";
  809. }
  810. }
  811. else
  812. {
  813. return "Frequency length must be 5 or 6 characters e.g. 89.50 or 108.00";
  814. }
  815. }
  816. else
  817. {
  818. return $usage;
  819. }
  820. return;
  821. }
  822. #############################
  823. sub YAMAHA_NP_Define
  824. {
  825. my ($hash, $def) = @_;
  826. my @a = split("[ \t][ \t]*", $def);
  827. my $name = $hash->{NAME};
  828. if(! @a >= 3)
  829. {
  830. my $msg = "Wrong syntax: define <name> YAMAHA_NP <ip-or-hostname> [<ON-statusinterval>] [<OFF-statusinterval>] ";
  831. Log3 $name, 2, $msg;
  832. return $msg;
  833. }
  834. my $address = $a[2];
  835. $hash->{helper}{ADDRESS} = $address;
  836. # if an update interval was given which is greater than zero, use it.
  837. if(defined($a[3]) and $a[3] > 0)
  838. {
  839. $hash->{helper}{OFF_INTERVAL} = $a[3];
  840. }
  841. else
  842. {
  843. $hash->{helper}{OFF_INTERVAL} = 30;
  844. }
  845. if(defined($a[4]) and $a[4] > 0)
  846. {
  847. $hash->{helper}{ON_INTERVAL} = $a[4];
  848. }
  849. else
  850. {
  851. $hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL};
  852. }
  853. YAMAHA_NP_getInputs($hash);
  854. unless(exists($hash->{helper}{AVAILABLE}) and ($hash->{helper}{AVAILABLE} == 0))
  855. {
  856. $hash->{helper}{AVAILABLE} = 1;
  857. readingsSingleUpdate($hash, "presence", "present", 1);
  858. }
  859. # start the status update timer
  860. $hash->{helper}{DISABLED} = 0 unless(exists($hash->{helper}{DISABLED}));
  861. YAMAHA_NP_ResetTimer($hash,0);
  862. return;
  863. }
  864. ##########################
  865. sub YAMAHA_NP_Attr
  866. {
  867. my @a = @_;
  868. my $hash = $defs{$a[1]};
  869. if($a[0] eq "set" && $a[2] eq "disable")
  870. {
  871. if($a[3] eq "0")
  872. {
  873. $hash->{helper}{DISABLED} = 0;
  874. YAMAHA_NP_GetStatus($hash, 1);
  875. }
  876. elsif($a[3] eq "1")
  877. {
  878. $hash->{helper}{DISABLED} = 1;
  879. }
  880. }
  881. elsif($a[0] eq "del" && $a[2] eq "disable")
  882. {
  883. $hash->{helper}{DISABLED} = 0;
  884. YAMAHA_NP_GetStatus($hash, 1);
  885. }
  886. # Start/Stop Timer according to new disabled-Value
  887. YAMAHA_NP_ResetTimer($hash);
  888. return;
  889. }
  890. #############################
  891. #
  892. #
  893. sub YAMAHA_NP_Undefine
  894. {
  895. my($hash, $name) = @_;
  896. # Stop the internal GetStatus-Loop and exit
  897. RemoveInternalTimer($hash);
  898. return;
  899. }
  900. #############################
  901. # sends a command to the receiver via HTTP
  902. #
  903. sub YAMAHA_NP_SendCommand
  904. {
  905. my ($hash,$data,$cmd,$arg,$blocking) = @_;
  906. my $name = $hash->{NAME};
  907. my $address = $hash->{helper}{ADDRESS};
  908. # Always use non-blocking http communication in case not specified
  909. if(not defined($blocking))
  910. {
  911. $blocking = 0;
  912. }
  913. if($blocking == 1)
  914. {
  915. Log3 $name, 5, "YAMAHA_NP ($name) - execute blocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data";
  916. my $param =
  917. {
  918. url => "http://".$address."/YamahaRemoteControl/ctrl",
  919. timeout => AttrVal($name, "request-timeout", 4),
  920. noshutdown => 1,
  921. data => "<?xml version=\"1.0\" encoding=\"utf-8\"?>".$data,
  922. loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
  923. hash => $hash,
  924. cmd => $cmd,
  925. arg => $arg
  926. };
  927. my ($err, $data) = HttpUtils_BlockingGet($param);
  928. YAMAHA_NP_ParseResponse($param, $err, $data);
  929. }
  930. else
  931. {
  932. Log3 $name, 5, "YAMAHA_NP ($name) - execute nonblocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data";
  933. HttpUtils_NonblockingGet
  934. ({
  935. url => "http://".$address."/YamahaRemoteControl/ctrl",
  936. timeout => AttrVal($name, "request-timeout", 4),
  937. noshutdown => 1,
  938. data => "<?xml version=\"1.0\" encoding=\"utf-8\"?>".$data,
  939. loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
  940. hash => $hash,
  941. cmd => $cmd,
  942. arg => $arg,
  943. callback => \&YAMAHA_NP_ParseResponse
  944. });
  945. }
  946. return;
  947. }
  948. #############################
  949. # parses HTTP response
  950. # (HttpUtils_NonblockingGet) callback
  951. #
  952. sub YAMAHA_NP_ParseResponse
  953. {
  954. my ($param, $err, $data ) = @_;
  955. my $hash = $param->{hash};
  956. my $name = $hash->{NAME};
  957. my $cmd = $param->{cmd};
  958. my $arg = $param->{arg};
  959. if(exists($param->{code}))
  960. {
  961. Log3 $name, 5, "YAMAHA_NP ($name) - received HTTP code ".$param->{code}." for command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\"";
  962. }
  963. if($err ne "")
  964. {
  965. Log3 $name, 5, "YAMAHA_NP ($name) - could not execute command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $err";
  966. if((not exists($hash->{helper}{AVAILABLE})) or (exists($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} == 1))
  967. {
  968. 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.";
  969. readingsSingleUpdate($hash, "presence", "absent", 1);
  970. readingsSingleUpdate($hash, "state", "absent", 1);
  971. }
  972. $hash->{helper}{AVAILABLE} = 0;
  973. }
  974. elsif($data ne "")
  975. {
  976. Log3 $name, 5, "YAMAHA_NP ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data";
  977. if (defined($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 0)
  978. {
  979. Log3 $name, 3, "YAMAHA_NP ($name) - device $name reappeared";
  980. readingsSingleUpdate($hash, "presence", "present", 1);
  981. }
  982. $hash->{helper}{AVAILABLE} = 1;
  983. if (($cmd ne "statusRequest") and ($arg ne "systemConfig")) # RC="0" is not delivered by that status Request
  984. {
  985. if(not $data =~ /RC="0"/)
  986. {
  987. # if the returncode != 0 -> HTTP command unsuccessful
  988. Log3 $name, 3, "YAMAHA_NP ($name) - Could not execute \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\"";
  989. }
  990. }
  991. readingsBeginUpdate($hash);
  992. if($cmd eq "statusRequest")
  993. {
  994. if($arg eq "systemConfig")
  995. {
  996. if($data =~ /<Model_Name>(.+?)<\/Model_Name>.*<System_ID>(.+?)<\/System_ID>.*<Version>(.+?)<\/Version>.*<Volume><Min>(.+?)<\/Min>.*<Max>(.+?)<\/Max>.*<Step>(.+?)<\/Step><\/Volume>/)
  997. {
  998. delete($hash->{MODEL}) if(defined($hash->{MODEL}));
  999. delete($hash->{helper}{VOLUMESTRAIGHTMIN}) if(defined($hash->{helper}{VOLUMESTRAIGHTMIN}));
  1000. delete($hash->{helper}{VOLUMESTRAIGHTMAX}) if(defined($hash->{helper}{VOLUMESTRAIGHTMAX}));
  1001. delete($hash->{helper}{VOLUMESTRAIGHTSTEP}) if(defined($hash->{helper}{VOLUMESTRAIGHTSTEP}));
  1002. $hash->{MODEL} = $1;
  1003. $hash->{SYSTEM_ID} = $2;
  1004. $hash->{FIRMWARE} = $3;
  1005. $hash->{helper}{VOLUMESTRAIGHTMIN} = $4;
  1006. $hash->{helper}{VOLUMESTRAIGHTMAX} = $5;
  1007. $hash->{helper}{VOLUMESTRAIGHTSTEP} = $6;
  1008. # Used by 'fheminfo' command for statistics
  1009. $attr{$name}{"model"} = $hash->{MODEL};
  1010. }
  1011. }
  1012. elsif($arg eq "getInputs")
  1013. {
  1014. delete($hash->{helper}{INPUTS}) if(defined($hash->{helper}{INPUTS}));
  1015. while($data =~ /<Feature_Existence>(.+?)<\/Feature_Existence>/gc)
  1016. {
  1017. if(defined($hash->{helper}{INPUTS}) and length($hash->{helper}{INPUTS}) > 0)
  1018. {
  1019. $hash->{helper}{INPUTS} .= ",";
  1020. }
  1021. $hash->{helper}{INPUTS} .= $1;
  1022. }
  1023. $hash->{helper}{INPUTS} = join("|", sort split("\\,", $hash->{helper}{INPUTS}));
  1024. }
  1025. elsif($arg eq "basicStatus")
  1026. {
  1027. if($data =~ /<Power>(.+?)<\/Power>/)
  1028. {
  1029. my $power = $1;
  1030. if($power eq "Standby")
  1031. {
  1032. $power = "off";
  1033. }
  1034. readingsBulkUpdate($hash, "power", lc($power));
  1035. readingsBulkUpdate($hash, "state", lc($power));
  1036. }
  1037. # current volume and mute status
  1038. if($data =~ /<Volume><Lvl>(.+?)<\/Lvl><Mute>(.+?)<\/Mute><\/Volume>/)
  1039. {
  1040. readingsBulkUpdate($hash, "volumeStraight", ($1));
  1041. readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $1));
  1042. readingsBulkUpdate($hash, "mute", lc($2));
  1043. }
  1044. # current input same as the corresponding set command name
  1045. if($data =~ /<Input_Sel>(.+?)<\/Input_Sel>/)
  1046. {
  1047. readingsBulkUpdate($hash, "input", YAMAHA_NP_Param2Fhem(lc($1), 0));
  1048. }
  1049. if($data =~ /<Sleep>(.+?)<\/Sleep>/)
  1050. {
  1051. readingsBulkUpdate($hash, "sleep", YAMAHA_NP_Param2Fhem($1, 0));
  1052. }
  1053. }
  1054. elsif($arg eq "playerStatus")
  1055. {
  1056. if($data =~ /<Playback_Info>(.+)<\/Playback_Info>/)
  1057. {
  1058. readingsBulkUpdate($hash, "playerPlaybackInfo", lc($1));
  1059. }
  1060. else
  1061. {
  1062. readingsBulkUpdate($hash, "playerPlaybackInfo", "");
  1063. }
  1064. if($data =~ /<Device_Type>(.+)<\/Device_Type>/)
  1065. {
  1066. readingsBulkUpdate($hash, "playerDeviceType", lc($1));
  1067. }
  1068. else
  1069. {
  1070. readingsBulkUpdate($hash, "playerDeviceType", "");
  1071. }
  1072. if($data =~ /<iPod_Mode>(.+)<\/iPod_Mode>/)
  1073. {
  1074. readingsBulkUpdate($hash, "playerIpodMode", lc($1));
  1075. }
  1076. else
  1077. {
  1078. readingsBulkUpdate($hash, "playerIpodMode", "");
  1079. }
  1080. if($data =~ /<Repeat>(.+)<\/Repeat>/)
  1081. {
  1082. readingsBulkUpdate($hash, "playerRepeat", lc($1));
  1083. }
  1084. else
  1085. {
  1086. readingsBulkUpdate($hash, "playerRepeat", "");
  1087. }
  1088. if($data =~ /<Shuffle>(.+)<\/Shuffle>/)
  1089. {
  1090. readingsBulkUpdate($hash, "playerShuffle", lc($1));
  1091. }
  1092. else
  1093. {
  1094. readingsBulkUpdate($hash, "playerShuffle", "");
  1095. }
  1096. if($data =~ /<Play_Time>(.+)<\/Play_Time>/)
  1097. {
  1098. readingsBulkUpdate($hash, "playerPlayTime", strftime("\%H:\%M:\%S", gmtime($1)));
  1099. }
  1100. else
  1101. {
  1102. readingsBulkUpdate($hash, "playerPlayTime", "");
  1103. }
  1104. if($data =~ /<Track_Number>(.+)<\/Track_Number>/)
  1105. {
  1106. readingsBulkUpdate($hash, "playerTrackNumber", lc($1));
  1107. }
  1108. else
  1109. {
  1110. readingsBulkUpdate($hash, "playerTrackNumber", "");
  1111. }
  1112. if($data =~ /<Total_Tracks>(.+)<\/Total_Tracks>/)
  1113. {
  1114. readingsBulkUpdate($hash, "playerTotalTracks", lc($1));
  1115. }
  1116. else
  1117. {
  1118. readingsBulkUpdate($hash, "playerTotalTracks", "");
  1119. }
  1120. if($data =~ /<Artist>(.+)<\/Artist>/)
  1121. {
  1122. readingsBulkUpdate($hash, "playerArtist", YAMAHA_NP_html2txt($1));
  1123. }
  1124. else
  1125. {
  1126. readingsBulkUpdate($hash, "playerArtist", "");
  1127. }
  1128. if($data =~ /<Album>(.+)<\/Album>/)
  1129. {
  1130. readingsBulkUpdate($hash, "playerAlbum", YAMAHA_NP_html2txt($1));
  1131. }
  1132. else
  1133. {
  1134. readingsBulkUpdate($hash, "playerAlbum", "");
  1135. }
  1136. if($data =~ /<Song>(.+)<\/Song>/)
  1137. {
  1138. readingsBulkUpdate($hash, "playerSong", YAMAHA_NP_html2txt($1));
  1139. }
  1140. else
  1141. {
  1142. readingsBulkUpdate($hash, "playerSong", "");
  1143. }
  1144. if($data =~ /<Album_ART><URL>(.+)<\/URL><ID>(.+)<\/ID><Format>(.+)<\/Format><\/Album_ART>/)
  1145. {
  1146. my $address = $hash->{helper}{ADDRESS};
  1147. readingsBulkUpdate($hash, "playerAlbumArtURL", "http://".$address."".YAMAHA_NP_html2txt($1));
  1148. readingsBulkUpdate($hash, "playerAlbumArtID", YAMAHA_NP_html2txt($2));
  1149. readingsBulkUpdate($hash, "playerAlbumArtFormat", YAMAHA_NP_html2txt($3));
  1150. }
  1151. else
  1152. {
  1153. readingsBulkUpdate($hash, "playerAlbumArtURL", "");
  1154. readingsBulkUpdate($hash, "playerAlbumArtID", "");
  1155. readingsBulkUpdate($hash, "playerAlbumArtFormat", "");
  1156. }
  1157. }
  1158. elsif($arg eq "tunerStatus")
  1159. {
  1160. if($data =~ /<Band>(.+)<\/Band>/)
  1161. {
  1162. readingsBulkUpdate($hash, "tunerBand", ($1));
  1163. }
  1164. if($hash->{READINGS}{tunerBand}{VAL} eq "FM")
  1165. {
  1166. if($data =~ /<FM><Preset><Preset_Sel>(.+)<\/Preset_Sel><\/Preset>(.*)<\/FM/)
  1167. {
  1168. readingsBulkUpdate($hash, "tunerPresetFM", ($1));
  1169. }
  1170. if($data =~ /<Tuning><Freq>(.+)<\/Freq><\/Tuning>/)
  1171. {
  1172. my $frequency = $1;
  1173. $frequency =~ s/(\d{2})$/.$1/; # Insert '.' to frequency
  1174. readingsBulkUpdate($hash, "tunerFrequencyFM", $frequency." MHz");
  1175. }
  1176. if($data =~ /<Program_Service>(.+)<\/Program_Service>/)
  1177. {
  1178. readingsBulkUpdate($hash, "tunerProgramServiceFM", YAMAHA_NP_html2txt($1));
  1179. }
  1180. if($data =~ /<Radio_Text_A>(.+)<\/Radio_Text_A>/)
  1181. {
  1182. readingsBulkUpdate($hash, "tunerRadioTextAFM", YAMAHA_NP_html2txt($1));
  1183. }
  1184. if($data =~ /<Radio_Text_B>(.+)<\/Radio_Text_B>/)
  1185. {
  1186. readingsBulkUpdate($hash, "tunerRadioTextBFM", YAMAHA_NP_html2txt($1));
  1187. }
  1188. }
  1189. if($hash->{READINGS}{tunerBand}{VAL} eq "DAB")
  1190. {
  1191. if($data =~ /<DAB><Preset><Preset_Sel>(.+)<\/Preset_Sel><\/Preset>(.*)<\/DAB>/)
  1192. {
  1193. readingsBulkUpdate($hash, "tunerPresetDAB", ($1));
  1194. }
  1195. if($data =~ /<Service_Label>(.+)<\/Service_Label>/)
  1196. {
  1197. readingsBulkUpdate($hash, "tunerServiceLabelDAB", YAMAHA_NP_html2txt($1));
  1198. }
  1199. if($data =~ /<Ch_Label>(.+)<\/Ch_Label>/)
  1200. {
  1201. readingsBulkUpdate($hash, "tunerChannelLabelDAB", ($1));
  1202. }
  1203. if($data =~ /<DLS>(.+)<\/DLS>/)
  1204. {
  1205. readingsBulkUpdate($hash, "tunerDLSDAB", YAMAHA_NP_html2txt($1));
  1206. }
  1207. if($data =~ /<Ensemble_Label>(.+)<\/Ensemble_Label>/)
  1208. {
  1209. readingsBulkUpdate($hash, "tunerEnsembleLabelDAB", YAMAHA_NP_html2txt($1));
  1210. }
  1211. if($data =~ /<Bit_Rate>(.+)<\/Bit_Rate>/)
  1212. {
  1213. readingsBulkUpdate($hash, "tunerBitRateDAB", $1." kbit\/s");
  1214. }
  1215. if($data =~ /<Audio_Mode>(.+)<\/Audio_Mode>/)
  1216. {
  1217. readingsBulkUpdate($hash, "tunerAudioModeDAB", $1);
  1218. }
  1219. if($data =~ /<DAB_PLUS>(.+)<\/DAB_PLUS>/)
  1220. {
  1221. if($1 eq "Negate")
  1222. {
  1223. readingsBulkUpdate($hash, "tunerModeDAB", "DAB");
  1224. }
  1225. elsif($1 eq "Assert")
  1226. {
  1227. readingsBulkUpdate($hash, "tunerModeDAB", "DAB+");
  1228. }
  1229. }
  1230. if($data =~ /<Signal_Info><Freq>(.+)<\/Freq>/)
  1231. {
  1232. my $frequency = $1;
  1233. $frequency =~ s/(\d{3})$/.$1/; # Insert '.' to frequency
  1234. readingsBulkUpdate($hash, "tunerFrequencyDAB", $frequency." MHz");
  1235. }
  1236. }
  1237. }
  1238. elsif($arg eq "timerStatus")
  1239. {
  1240. if($data =~ /<Volume><Lvl>(.+)<\/Lvl><\/Volume>/)
  1241. {
  1242. readingsBulkUpdate($hash, "timerVolume", $1);
  1243. }
  1244. if($data =~ /<Start_Time>(.+)<\/Start_Time>/)
  1245. {
  1246. readingsBulkUpdate($hash, "timerStartTime", $1);
  1247. }
  1248. if($data =~ /<Repeat>(.+)<\/Repeat>/)
  1249. {
  1250. readingsBulkUpdate($hash, "timerRepeat", lc($1));
  1251. }
  1252. }
  1253. elsif($arg eq "getTimer")
  1254. {
  1255. if($data =~ /<Mode>(.+)<\/Mode>/)
  1256. {
  1257. readingsBulkUpdate($hash, "timer", lc($1));
  1258. }
  1259. }
  1260. elsif($arg eq "networkInfo")
  1261. {
  1262. if($data =~ /<IP_Address>(.+)<\/IP_Address>/)
  1263. {
  1264. $hash->{IP_ADDRESS} = $1;
  1265. }
  1266. if($data =~ /<Subnet_Mask>(.+)<\/Subnet_Mask>/)
  1267. {
  1268. $hash->{SUBNET_MASK} = $1;
  1269. }
  1270. if($data =~ /<Default_Gateway>(.+)<\/Default_Gateway>/)
  1271. {
  1272. $hash->{DEFAULT_GATEWAY} = $1;
  1273. }
  1274. if($data =~ /<DNS_Server_1>(.+)<\/DNS_Server_1>/)
  1275. {
  1276. $hash->{DNS_SERVER_1} = $1;
  1277. }
  1278. if($data =~ /<DNS_Server_2>(.+)<\/DNS_Server_2>/)
  1279. {
  1280. $hash->{DNS_SERVER_2} = $1;
  1281. }
  1282. if($data =~ /<MAC_Address>(.+)<\/MAC_Address>/)
  1283. {
  1284. $hash->{MAC_ADDRESS} = $1;
  1285. # Add ':' after every two chars
  1286. $hash->{MAC_ADDRESS} =~ s/\w{2}\B/$&:/g;
  1287. }
  1288. }
  1289. elsif($arg eq "tunerPresetFM")
  1290. {
  1291. {
  1292. # May be also an empty string <Item_#></Item_#>
  1293. for (my $i = 1; $i < 31; $i++)
  1294. {
  1295. if ($data =~ /<Item_$i><\/Item_$i>/)
  1296. {
  1297. readingsBulkUpdate($hash, sprintf("tunerPresetFMItem_%02d", $i), "No Preset");
  1298. }
  1299. elsif($data =~ /<Item_$i>(.+?)<\/Item_$i>/)
  1300. {
  1301. readingsBulkUpdate($hash, sprintf("tunerPresetFMItem_%02d", $i), $1);
  1302. }
  1303. }
  1304. }
  1305. }
  1306. elsif($arg eq "tunerPresetDAB")
  1307. {
  1308. # May be also an empty string <Item_#></Item_#>
  1309. for (my $i = 1; $i < 31; $i++)
  1310. {
  1311. if ($data =~ /<Item_$i><\/Item_$i>/)
  1312. {
  1313. readingsBulkUpdate($hash, sprintf("tunerPresetDABItem_%02d", $i), "No Preset");
  1314. }
  1315. elsif($data =~ /<Item_$i>(.+?)<\/Item_$i>/)
  1316. {
  1317. readingsBulkUpdate($hash, sprintf("tunerPresetDABItem_%02d", $i), $1);
  1318. }
  1319. }
  1320. }
  1321. elsif ($arg eq "standbyMode")
  1322. {
  1323. if($data =~ /<Saving>(.+)<\/Saving>/)
  1324. {
  1325. readingsBulkUpdate($hash, "standbyMode", lc($1));
  1326. }
  1327. }
  1328. elsif ($arg eq "mediaRendererDesc")
  1329. {
  1330. if($data =~ /<friendlyName>(.+)<\/friendlyName>/)
  1331. {
  1332. $hash->{FRIENDLY_NAME} = $1;
  1333. }
  1334. if($data =~ /<UDN>(.+)<\/UDN>/)
  1335. {
  1336. my @uuid = split(/:/, $1);
  1337. $hash->{UNIQUE_DEVICE_NAME} = uc($uuid[1]);
  1338. }
  1339. # Replace \n, \r, \t from the string for XML parsing
  1340. # replace \n by ""
  1341. $data =~ s/\n//g;
  1342. # replace \t by ""
  1343. $data =~ s/\t//g;
  1344. # replace \r by ""
  1345. $data =~ s/\r//g;
  1346. if($data =~ /<iconList>(.+?)<\/iconList>/)
  1347. {
  1348. my $address = $hash->{helper}{ADDRESS};
  1349. my $i = 1;
  1350. while ($data =~ /<url>(.+?)<\/url>/g)
  1351. {
  1352. $hash->{"NP_ICON_$i"} = "http://".$address.":8080".$1;
  1353. $i++;
  1354. }
  1355. }
  1356. }
  1357. }
  1358. elsif($cmd eq "playerListGetList")
  1359. {
  1360. # Delete old List listLines
  1361. my $i = 1;
  1362. if($data =~ /<Menu_Status>(.*)<\/Menu_Status>/)
  1363. {
  1364. readingsBulkUpdate($hash, "playerListMenuStatus", $1);
  1365. }
  1366. if($data =~ /<Menu_Name>(.*)<\/Menu_Name>/)
  1367. {
  1368. readingsBulkUpdate($hash, "playerListMenuName", $1);
  1369. }
  1370. if($data =~ /<Menu_Layer>(.*)<\/Menu_Layer>/)
  1371. {
  1372. readingsBulkUpdate($hash, "playerListMenuLayer", $1);
  1373. }
  1374. if($data =~ /<Current_List>(.*)<\/Current_List>/)
  1375. {
  1376. # <Line_X><Txt>****</Txt><Attribute>Container|Item|Unselectable</Attribute></Line_X>
  1377. while($data =~ /<Line_$i><Txt>(.*?)<\/Txt><Attribute>(.*?)<\/Attribute><\/Line_$i>/gc)
  1378. {
  1379. readingsBulkUpdate($hash, "playerListLine_$i", $1);
  1380. readingsBulkUpdate($hash, "playerListLine_Attribute_$i", $2);
  1381. $i++;
  1382. }
  1383. }
  1384. if($data =~ /<Cursor_Position><Current_Line>(.*)<\/Current_Line><Max_Line>(.*)<\/Max_Line><\/Cursor_Position>/)
  1385. {
  1386. readingsBulkUpdate($hash, "playerListCurrentLine", $1);
  1387. readingsBulkUpdate($hash, "playerListMaxLine", $2);
  1388. }
  1389. }
  1390. elsif($cmd eq "on")
  1391. {
  1392. if($data =~ /RC="0"/ and $data =~ /<Power><\/Power>/)
  1393. {
  1394. readingsBulkUpdate($hash, "power", "on");
  1395. readingsBulkUpdate($hash, "state","on");
  1396. readingsEndUpdate($hash, 1);
  1397. YAMAHA_NP_ResetTimer($hash);
  1398. return;
  1399. }
  1400. }
  1401. elsif($cmd eq "off")
  1402. {
  1403. if($data =~ /RC="0"/ and $data =~ /<Power><\/Power>/)
  1404. {
  1405. readingsBulkUpdate($hash, "power", "off");
  1406. readingsBulkUpdate($hash, "state","off");
  1407. readingsEndUpdate($hash, 1);
  1408. blankTunerDABReadings($hash);
  1409. blankTunerFMReadings($hash);
  1410. blankPlayerReadings($hash);
  1411. YAMAHA_NP_ResetTimer($hash);
  1412. return;
  1413. }
  1414. }
  1415. elsif($cmd eq "mute")
  1416. {
  1417. if($data =~ /RC="0"/)
  1418. {
  1419. readingsBulkUpdate($hash, "mute", $arg);
  1420. }
  1421. }
  1422. elsif($cmd eq "standbyMode")
  1423. {
  1424. if($data =~ /RC="0"/)
  1425. {
  1426. readingsBulkUpdate($hash, "standbyMode", lc($arg));
  1427. }
  1428. }
  1429. elsif($cmd eq "volume" or $cmd eq "volumeStraight" or $cmd eq "volumeUp" or $cmd eq "volumeDown")
  1430. {
  1431. if($data =~ /RC="0"/)
  1432. {
  1433. if(AttrVal($name, "smooth-volume-change", "1") eq "1" )
  1434. {
  1435. my $volumeStraight;
  1436. $volumeStraight = $hash->{READINGS}{volumeStraight}{VAL};
  1437. if($hash->{helper}{targetVolume} eq $volumeStraight)
  1438. {
  1439. $hash->{helper}{volumeChangeDir} = "EQUAL";
  1440. }
  1441. if($hash->{helper}{volumeChangeDir} eq "EQUAL")
  1442. {
  1443. readingsBulkUpdate($hash, "volumeStraight", $hash->{helper}{targetVolume});
  1444. readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $hash->{helper}{targetVolume}));
  1445. }
  1446. elsif($hash->{helper}{volumeChangeDir} eq "UP")
  1447. {
  1448. # Reset timer in order to avoid status request collisions
  1449. # due to recursive volume change call
  1450. YAMAHA_NP_ResetTimer($hash);
  1451. readingsBulkUpdate($hash, "volumeStraight", $volumeStraight + 1);
  1452. readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $volumeStraight + 1));
  1453. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".($volumeStraight + 1)."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", ($volumeStraight + 1), 0);
  1454. }
  1455. elsif($hash->{helper}{volumeChangeDir} eq "DOWN")
  1456. {
  1457. # Reset timer in order to avoid status request collisions
  1458. # due to recursive volume change call
  1459. YAMAHA_NP_ResetTimer($hash);
  1460. readingsBulkUpdate($hash, "volumeStraight", $volumeStraight - 1);
  1461. readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $volumeStraight - 1));
  1462. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"PUT\"><System><Volume><Lvl>".($volumeStraight - 1)."</Lvl></Volume><\/System></YAMAHA_AV>", "volume", ($volumeStraight - 1), 0);
  1463. }
  1464. }
  1465. else
  1466. {
  1467. readingsBulkUpdate($hash, "volumeStraight", $hash->{helper}{targetVolume});
  1468. readingsBulkUpdate($hash, "volume", YAMAHA_NP_volume_abs2rel($hash, $hash->{helper}{targetVolume}));
  1469. $hash->{helper}{volumeChangeDir} = "EQUAL";
  1470. }
  1471. }
  1472. }
  1473. readingsEndUpdate($hash, 1);
  1474. #YAMAHA_NP_ResetTimer($hash, 0) if($cmd ne "statusRequest" and $cmd ne "on" and $cmd ne "volume");
  1475. }
  1476. return;
  1477. }
  1478. #############################
  1479. # Blanks dynamic DAB tuner readings
  1480. sub blankTunerDABReadings
  1481. {
  1482. my ($hash) = @_;
  1483. readingsBeginUpdate($hash);
  1484. readingsBulkUpdate($hash, "tunerDLSDAB", "");
  1485. readingsBulkUpdate($hash, "tunerEnsembleLabelDAB", "");
  1486. readingsBulkUpdate($hash, "tunerFrequencyDAB", "");
  1487. readingsBulkUpdate($hash, "tunerModeDAB", "");
  1488. readingsBulkUpdate($hash, "tunerServiceLabelDAB", "");
  1489. readingsBulkUpdate($hash, "tunerAudioModeDAB", "");
  1490. readingsBulkUpdate($hash, "tunerBitRateDAB", "");
  1491. readingsBulkUpdate($hash, "tunerChannelLabelDAB", "");
  1492. readingsBulkUpdate($hash, "tunerPresetDAB", "");
  1493. readingsEndUpdate($hash, 1);
  1494. return;
  1495. }
  1496. #############################
  1497. # Blanks dynamic FM tuner readings
  1498. sub blankTunerFMReadings
  1499. {
  1500. my ($hash) = @_;
  1501. readingsBeginUpdate($hash);
  1502. readingsBulkUpdate($hash, "tunerFrequencyFM", "");
  1503. readingsBulkUpdate($hash, "tunerProgramServiceFM", "");
  1504. readingsBulkUpdate($hash, "tunerRadioTextAFM", "");
  1505. readingsBulkUpdate($hash, "tunerRadioTextBFM", "");
  1506. readingsBulkUpdate($hash, "tunerPresetFM", "");
  1507. readingsEndUpdate($hash, 1);
  1508. return;
  1509. }
  1510. #############################
  1511. # Blanks dynamic Tuner readings
  1512. sub blankPlayerReadings
  1513. {
  1514. my ($hash) = @_;
  1515. readingsBeginUpdate($hash);
  1516. readingsBulkUpdate($hash, "playerAlbum", "");
  1517. readingsBulkUpdate($hash, "playerAlbumArtFormat", "");
  1518. readingsBulkUpdate($hash, "playerAlbumArtID", "");
  1519. readingsBulkUpdate($hash, "playerAlbumArtURL", "");
  1520. readingsBulkUpdate($hash, "playerArtist", "");
  1521. readingsBulkUpdate($hash, "playerDeviceType", "");
  1522. readingsBulkUpdate($hash, "playerIpodMode", "");
  1523. readingsBulkUpdate($hash, "playerListCurrentLine", "");
  1524. readingsBulkUpdate($hash, "playerListLine_1", "");
  1525. readingsBulkUpdate($hash, "playerListLine_2", "");
  1526. readingsBulkUpdate($hash, "playerListLine_3", "");
  1527. readingsBulkUpdate($hash, "playerListLine_4", "");
  1528. readingsBulkUpdate($hash, "playerListLine_5", "");
  1529. readingsBulkUpdate($hash, "playerListLine_6", "");
  1530. readingsBulkUpdate($hash, "playerListLine_7", "");
  1531. readingsBulkUpdate($hash, "playerListLine_8", "");
  1532. readingsBulkUpdate($hash, "playerListLine_Attribute_1", "");
  1533. readingsBulkUpdate($hash, "playerListLine_Attribute_2", "");
  1534. readingsBulkUpdate($hash, "playerListLine_Attribute_3", "");
  1535. readingsBulkUpdate($hash, "playerListLine_Attribute_4", "");
  1536. readingsBulkUpdate($hash, "playerListLine_Attribute_5", "");
  1537. readingsBulkUpdate($hash, "playerListLine_Attribute_6", "");
  1538. readingsBulkUpdate($hash, "playerListLine_Attribute_7", "");
  1539. readingsBulkUpdate($hash, "playerListLine_Attribute_8", "");
  1540. readingsBulkUpdate($hash, "playerListMaxLine", "");
  1541. readingsBulkUpdate($hash, "playerListMenuLayer", "");
  1542. readingsBulkUpdate($hash, "playerListMenuName", "");
  1543. readingsBulkUpdate($hash, "playerListMenuStatus", "");
  1544. readingsBulkUpdate($hash, "playerPlayTime", "");
  1545. readingsBulkUpdate($hash, "playerPlaybackInfo", "");
  1546. readingsBulkUpdate($hash, "playerRepeat", "");
  1547. readingsBulkUpdate($hash, "playerShuffle", "");
  1548. readingsBulkUpdate($hash, "playerSong", "");
  1549. readingsBulkUpdate($hash, "playerTotalTracks", "");
  1550. readingsBulkUpdate($hash, "playerTrackNumber", "");
  1551. readingsEndUpdate($hash, 1);
  1552. return;
  1553. }
  1554. #############################
  1555. # Converts all Values to FHEM usable command lists
  1556. sub YAMAHA_NP_Param2Fhem
  1557. {
  1558. my ($param, $replace_pipes) = @_;
  1559. $param =~ s/\s+//g;
  1560. $param =~ s/,//g;
  1561. $param =~ s/_//g;
  1562. $param =~ s/\(/_/g;
  1563. $param =~ s/\)//g;
  1564. $param =~ s/\|/,/g if($replace_pipes == 1);
  1565. return lc $param;
  1566. }
  1567. #############################
  1568. # Returns the Yamaha Parameter Name for the FHEM like equivalent
  1569. sub YAMAHA_NP_getParamName
  1570. {
  1571. my ($hash, $name, $list) = @_;
  1572. return if(not defined($list));
  1573. my @commands = split("\\|", $list);
  1574. foreach my $item (@commands)
  1575. {
  1576. if(YAMAHA_NP_Param2Fhem($item, 0) eq $name)
  1577. {
  1578. return $item;
  1579. }
  1580. }
  1581. return;
  1582. }
  1583. #############################
  1584. # queries the NP model, system-id and version
  1585. sub YAMAHA_NP_getModel
  1586. {
  1587. my ($hash) = @_;
  1588. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Config>GetParam</Config></System></YAMAHA_AV>", "statusRequest","systemConfig", 0);
  1589. YAMAHA_NP_getMediaRendererDesc($hash);
  1590. return;
  1591. }
  1592. #############################
  1593. # queries the addition model descriptions
  1594. sub YAMAHA_NP_getMediaRendererDesc
  1595. {
  1596. my ($hash) = @_;
  1597. my $name = $hash->{NAME};
  1598. my $address = $hash->{helper}{ADDRESS};
  1599. Log3 $name, 5, "YAMAHA_NP ($name) - execute nonblocking \"MediaRendererDesc\"";
  1600. HttpUtils_NonblockingGet
  1601. ({
  1602. url => "http://".$address.":8080/MediaRenderer/desc.xml",
  1603. timeout => AttrVal($name, "request-timeout", 4),
  1604. noshutdown => 1,
  1605. data => "",
  1606. loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
  1607. hash => $hash,
  1608. cmd => "statusRequest",
  1609. arg => "mediaRendererDesc",
  1610. callback => \&YAMAHA_NP_ParseResponse
  1611. });
  1612. return;
  1613. }
  1614. #############################
  1615. # converts straight volume in percentage volume (volumestraightmin .. volumestraightmax => 0 .. 100%)
  1616. sub YAMAHA_NP_volume_rel2abs
  1617. {
  1618. my ($hash, $percentage) = @_;
  1619. return int(($percentage * $hash->{helper}{VOLUMESTRAIGHTMAX} / 100 ));
  1620. }
  1621. #############################
  1622. # converts percentage volume in decibel volume (0 .. 100% => volumestraightmin .. volumestraightmax)
  1623. sub YAMAHA_NP_volume_abs2rel
  1624. {
  1625. my ($hash, $absolute) = @_;
  1626. # Prevent division by 0
  1627. if (defined($hash->{helper}{VOLUMESTRAIGHTMAX}) and $hash->{helper}{VOLUMESTRAIGHTMAX} ne "0")
  1628. {
  1629. return int($absolute * 100 / int($hash->{helper}{VOLUMESTRAIGHTMAX}));
  1630. }
  1631. else
  1632. {
  1633. return int(0)
  1634. }
  1635. }
  1636. #############################
  1637. # queries all available inputs
  1638. sub YAMAHA_NP_getInputs
  1639. {
  1640. my ($hash) = @_;
  1641. my $name = $hash->{NAME};
  1642. my $address = $hash->{helper}{ADDRESS};
  1643. # query all inputs
  1644. YAMAHA_NP_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><System><Config>GetParam</Config></System></YAMAHA_AV>", "statusRequest","getInputs", 0);
  1645. return;
  1646. }
  1647. #############################
  1648. # Restarts the internal status request timer according to the given interval or current NP state
  1649. sub YAMAHA_NP_ResetTimer
  1650. {
  1651. my ($hash, $interval) = @_;
  1652. RemoveInternalTimer($hash);
  1653. if($hash->{helper}{DISABLED} == 0)
  1654. {
  1655. if(defined($interval))
  1656. {
  1657. InternalTimer(gettimeofday()+ $interval, "YAMAHA_NP_GetStatus", $hash, 0);
  1658. }
  1659. 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"))
  1660. {
  1661. InternalTimer(gettimeofday() + $hash->{helper}{ON_INTERVAL}, "YAMAHA_NP_GetStatus", $hash, 0);
  1662. }
  1663. else
  1664. {
  1665. InternalTimer(gettimeofday() + $hash->{helper}{OFF_INTERVAL}, "YAMAHA_NP_GetStatus", $hash, 0);
  1666. }
  1667. }
  1668. return;
  1669. }
  1670. #############################
  1671. # convert all HTML entities into UTF-8 equivalent
  1672. sub YAMAHA_NP_html2txt
  1673. {
  1674. my ($string) = @_;
  1675. $string =~ s/&quot;/\"/g;
  1676. $string =~ s/&amp;/&/g;
  1677. $string =~ s/&amp;/&/g;
  1678. $string =~ s/&nbsp;/ /g;
  1679. $string =~ s/&apos;/'/g;
  1680. $string =~ s/(\xe4|&auml;)/ä/g;
  1681. $string =~ s/(\xc4|&Auml;)/Ä/g;
  1682. $string =~ s/(\xf6|&ouml;)/ö/g;
  1683. $string =~ s/(\xd6|&Ouml;)/Ö/g;
  1684. $string =~ s/(\xfc|&uuml;)/ü/g;
  1685. $string =~ s/(\xdc|&Uuml;)/Ü/g;
  1686. $string =~ s/(\xdf|&szlig;)/ß/g;
  1687. $string =~ s/<.+?>//g;
  1688. $string =~ s/(^\s+|\s+$)//g;
  1689. return $string;
  1690. }
  1691. 1;
  1692. =pod
  1693. =begin html
  1694. <a name="YAMAHA_NP"></a>
  1695. <h3>YAMAHA_NP</h3>
  1696. <ul>
  1697. <a name="YAMAHA_NPdefine"></a>
  1698. <b>Define</b>
  1699. <br><br>
  1700. <ul>
  1701. <code>
  1702. define &lt;name&gt; YAMAHA_NP &lt;ip-address&gt; [&lt;status_interval&gt;]<br><br>
  1703. define &lt;name&gt; YAMAHA_NP &lt;ip-address&gt; [&lt;off_status_interval&gt;] [&lt;on_status_interval&gt;]
  1704. </code>
  1705. <br><br>
  1706. This module controls a Yamaha Network Player (such as MCR-N560, MCR-N560D, CRX-N560, CRX-N560D, CD-N500 or NP-S2000) via Ethernet.
  1707. Theoretically, any device understanding the communication protocol of the Yamaha Network Player App should work.
  1708. <br><br>
  1709. Currently implemented features:
  1710. <br><br>
  1711. <ul>
  1712. <li>Power on/off</li>
  1713. <li>Timer on/off</li>
  1714. <li>Input selection</li>
  1715. <li>Timer on/off</li>
  1716. <li>Volume +/-</li>
  1717. <li>Mute on/off</li>
  1718. <li>System Clock Update</li>
  1719. <li>Tuner: tune +/-, preset +/-, Station information (FM/DAB)</li>
  1720. <li>Stand-by mode: eco/normal</li>
  1721. <li>Player (play, stop, next, prev, shuffle, repeat)</li>
  1722. <li>Menu navigation</li>
  1723. <li>...</li>
  1724. </ul>
  1725. <br>
  1726. Defining a YAMAHA_NP device will schedule an internal task (interval can be set
  1727. with optional parameters &lt;off_status_interval&gt; and &lt;on_status_interval&gt; in seconds.<br>
  1728. &lt;off_status_interval&gt; is a parameter used in case the device is powered off or not available.<br>
  1729. &lt;on_status_interval&gt; is a parameter used in case the device is powered on.<br>
  1730. If both parameters are unset, a default value 30 (seconds) for both is used.<br>
  1731. If &lt;off_status_interval&gt; is set only the same value is used for both parameters.
  1732. <br>
  1733. The internal task periodically reads the status of the Network Player (power state, selected
  1734. input, volume and mute status etc.) and triggers notify/filelog commands.
  1735. <br><br>
  1736. Example:<br><br>
  1737. <ul><br>
  1738. Add the following code into the <b>fhem.cfg</b> configuration file and restart fhem:<br><br>
  1739. <code>
  1740. define NP_Player YAMAHA_NP 192.168.0.15<br>
  1741. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp<br><br>
  1742. # With custom status interval of 60 seconds<br>
  1743. define NP_Player YAMAHA_NP 192.168.0.15 <b>60</b><br>
  1744. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp<br><br>
  1745. # With custom "off"-interval of 60 seconds and "on"-interval of 10 seconds<br>
  1746. define NP_Player YAMAHA_NP 192.168.0.15 <b>60 10</b><br>
  1747. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp
  1748. </code>
  1749. </ul>
  1750. </ul>
  1751. <br><br>
  1752. <a name="YAMAHA_NPset"></a>
  1753. <b>Set</b>
  1754. <ul>
  1755. <code>
  1756. set &lt;name&gt; &lt;command&gt; [&lt;parameter&gt;]
  1757. </code><br><br>
  1758. Currently, the following commands are defined.<br>
  1759. The available inputs are depending on the used network player.
  1760. The module offers only available inputs.<br><br>
  1761. <i>Note: Commands and parameters are case sensitive.</i><br>
  1762. <ul><br><br>
  1763. <u>Available commands:</u><br><br>
  1764. <li><b>cdTray</b>&nbsp;&nbsp;-&nbsp;&nbsp; open/close the CD tray.</li>
  1765. <li><b>clockUpdate</b>&nbsp;&nbsp;-&nbsp;&nbsp; updates the system clock with current time. The time information is taken from the FHEM server.</li>
  1766. <li><b>dimmer</b> [1..3] &nbsp;&nbsp;-&nbsp;&nbsp; Sets the display brightnes.</li>
  1767. <li><b>input</b> [&lt;parameter&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; selects the input channel. The inputs are read dynamically from the device. Available inputs can be set (e.g. cd, tuner, aux1, aux2, ...).</li>
  1768. <li><b>mute</b> [on|off] &nbsp;&nbsp;-&nbsp;&nbsp; activates/deactivates muting</li>
  1769. <li><b>off</b> &nbsp;&nbsp;-&nbsp;&nbsp; shuts down the device </li>
  1770. <li><b>on</b> &nbsp;&nbsp;-&nbsp;&nbsp; powers on the device</li>
  1771. <li><b>player [&lt;parameter&gt;] </b> &nbsp;&nbsp;-&nbsp;&nbsp; sets player related commands.</li>
  1772. <ul>
  1773. <li><b>play</b>&nbsp;&nbsp;-&nbsp;&nbsp; play.</li>
  1774. <li><b>stop</b>&nbsp;&nbsp;-&nbsp;&nbsp; stop.</li>
  1775. <li><b>pause</b>&nbsp;&nbsp;-&nbsp;&nbsp; pause.</li>
  1776. <li><b>next</b>&nbsp;&nbsp;-&nbsp;&nbsp; next item.</li>
  1777. <li><b>prev</b>&nbsp;&nbsp;-&nbsp;&nbsp; previous item.</li>
  1778. <li><b>shuffleToggle</b>&nbsp;&nbsp;-&nbsp;&nbsp; Toggles the shuffle mode.</li>
  1779. <li><b>repeatToggle</b>&nbsp;&nbsp;-&nbsp;&nbsp; Toggles the repeat modes.</li>
  1780. </ul>
  1781. <li><b>playerListCursorDown</b>&nbsp;&nbsp;-&nbsp;&nbsp;Command for list navigation in inputs such as Net Radio or Server. Command moves the cursor down. Next line displayed.</li>
  1782. <li><b>playerListCursorReturn</b>&nbsp;&nbsp;-&nbsp;&nbsp;Command for list navigation in inputs such as Net Radio or Server. Command returns from a hierarchical sub-menu. Higher level menu displayed.</li>
  1783. <li><b>playerListCursorUp</b>&nbsp;&nbsp;-&nbsp;&nbsp;Command for list navigation in inputs such as Net Radio or Server. Command moves the cursor up. Previous line displayed.</li>
  1784. <li><b>playerListGetList</b>&nbsp;&nbsp;-&nbsp;&nbsp;Command for list navigation in inputs such as Net Radio or Server. Command returns readings relevant for list/menu navigation.</li>
  1785. <li><b>playerListJumpLine [value]</b>&nbsp;&nbsp;-&nbsp;&nbsp;Command for list navigation in inputs such as Net Radio or Server. Command jumps to a given line.</li>
  1786. <li><b>playerListSelectLine [value]</b>&nbsp;&nbsp;-&nbsp;&nbsp;Command for list navigation in inputs such as Net Radio or Server. Command selects the given line. In case the line is a 'Container' (folder) it's entered. In case of 'Item' the playback starts.</li>
  1787. <li><b>sleep</b> [off|30min|60min|90min|120min] &nbsp;&nbsp;-&nbsp;&nbsp; activates the internal sleep timer</li>
  1788. <li><b>standbyMode</b> [eco|normal] &nbsp;&nbsp;-&nbsp;&nbsp; set the standby mode.</li>
  1789. <li><b>statusRequest [&lt;parameter&gt;] </b> &nbsp;&nbsp;-&nbsp;&nbsp; requests the current status of the device</li>
  1790. <ul>
  1791. <li><b>basicStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests the basic status such as volume input etc.</li>
  1792. <li><b>playerStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests the player status such as play status, song info, artist info etc.</li>
  1793. <li><b>standbyMode</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests the standby mode information</li>
  1794. <li><b>systemConfig</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests the system configuration</li>
  1795. <li><b>tunerStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests the tuner status such as FM frequency, preset number, DAB information etc.</li>
  1796. <li><b>timerStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests device's internal wake-up timer status</li>
  1797. <li><b>networkInfo</b>&nbsp;&nbsp;-&nbsp;&nbsp; requests device's network related information such as IP, Gateway, MAC address etc.</li>
  1798. </ul>
  1799. <li><b>timerHour</b> [0...23] &nbsp;&nbsp;-&nbsp;&nbsp; sets hour of device's internal wake-up timer</li>
  1800. <li><b>timerMinute</b> [0...59] &nbsp;&nbsp;-&nbsp;&nbsp; sets minutes of device's internal wake-up timer</li>
  1801. <li><b>timerRepeat</b> [once|every] &nbsp;&nbsp;-&nbsp;&nbsp; sets repetition mode of device's internal wake-up timer</li>
  1802. <li><b>timerSet</b> &nbsp;&nbsp;-&nbsp;&nbsp; configures the timer according to timerHour, timerMinute, timerRepeat, timerVolume. (ALL parameters must be set before. This command does not switch on the timer. &rarr; 'timer on'.)</li>
  1803. <li><b>timerVolume</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; sets volume of device's internal wake-up timer</li>
  1804. <li><b>timer</b> [on|off] &nbsp;&nbsp;-&nbsp;&nbsp; sets device's internal wake-up timer. <i>(Note: The timer will be activated according to the last stored timer parameters in the device. In order to modify please use the 'timerSet' command.)</i></li>
  1805. <li><b>tuner [&lt;parameter&gt;] </b> &nbsp;&nbsp;-&nbsp;&nbsp; sets tuner related commands.</li>
  1806. <ul>
  1807. <li><b>bandDAB</b>&nbsp;&nbsp;-&nbsp;&nbsp; sets the tuner band to DAB (if available).</li>
  1808. <li><b>bandFM</b>&nbsp;&nbsp;-&nbsp;&nbsp; sets the tuner band to FM.</li>
  1809. <li><b>tuneUp</b>&nbsp;&nbsp;-&nbsp;&nbsp; tuner tune up.</li>
  1810. <li><b>tuneDown</b>&nbsp;&nbsp;-&nbsp;&nbsp; tuner tune down.</li>
  1811. <li><b>presetUp</b>&nbsp;&nbsp;-&nbsp;&nbsp; tuner preset up.</li>
  1812. <li><b>presetDown</b>&nbsp;&nbsp;-&nbsp;&nbsp; tuner preset down.</li>
  1813. </ul>
  1814. <li><b>tunerFMFrequency</b> [87.50 ... 108.00] &nbsp;&nbsp;-&nbsp;&nbsp; Sets the FM frequency. The value must be 87.50 ... 108.00 including the decimal point ('.') with two digits after. Otherwise the value will be ignored.</li>
  1815. <li><b>tunerPresetDAB</b> [1...30] &nbsp;&nbsp;-&nbsp;&nbsp; Sets the DAB preset.</li>
  1816. <li><b>tunerPresetFM</b> [1...30] &nbsp;&nbsp;-&nbsp;&nbsp; Sets the FM preset.</li>
  1817. <li><b>volume</b> [0...100] &nbsp;&nbsp;-&nbsp;&nbsp; set the volume level in &#037;</li>
  1818. <li><b>volumeStraight</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; set the volume as used and displayed in the device. &lt;VOL_MIN&gt; and &lt;VOL_MAX&gt; are read and set from the device automatically.</li>
  1819. <li><b>volumeUp</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; increases the volume by one device's absolute step. &lt;VOL_MIN&gt; and &lt;VOL_MAX&gt; are read and set from the device automatically.</li>
  1820. <li><b>volumeDown</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; increases the volume by one device's absolute step. &lt;VOL_MIN&gt; and &lt;VOL_MAX&gt; are read and set from the device automatically.</li>
  1821. </ul><br><br>
  1822. A typical example is powering the device remotely and tuning the favourite radio station:<br><br>
  1823. Add the following code into the <b>fhem.cfg</b> configuration file:<br><br><br>
  1824. <ul>
  1825. <code>
  1826. define NP_player YAMAHA_NP 192.168.0.15 30 5<br>
  1827. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp
  1828. </code>
  1829. </ul><br><br>
  1830. Add the following code into the <b>99_MyUtils.pm</b> file:<br><br>
  1831. <ul>
  1832. <code>
  1833. sub startMyFavouriteRadioStation()<br>
  1834. {<br>
  1835. &nbsp;&nbsp;fhem "set NP_player on";<br>
  1836. &nbsp;&nbsp;sleep 1;<br>
  1837. &nbsp;&nbsp;fhem "set NP_player input tuner";<br>
  1838. &nbsp;&nbsp;sleep 1;<br>
  1839. &nbsp;&nbsp;fhem "set NP_player tunerPresetDAB 1";<br>
  1840. &nbsp;&nbsp;sleep 1;<br>
  1841. &nbsp;&nbsp;fhem "set NP_player volume 30";<br>
  1842. }
  1843. </code>
  1844. </ul>
  1845. <br><br>
  1846. 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...<br><br>
  1847. Now the function can be called by typing the following line in the FHEM command line or by the notify-definitions:<br><br>
  1848. <ul>
  1849. <code>
  1850. {startMyFavouriteRadioStation()}<br><br>
  1851. </code>
  1852. </ul>
  1853. </ul>
  1854. <a name="YAMAHA_NPget"></a>
  1855. <b>Get</b>
  1856. <ul>
  1857. <code>
  1858. get &lt;name&gt; &lt;reading&gt;
  1859. </code>
  1860. <br><br>
  1861. Currently, the 'get' command returns reading values only. For a specific list of possible values, see section <b>"Generated Readings"</b>.<br><br>
  1862. </ul>
  1863. <a name="YAMAHA_NPattr"></a>
  1864. <b>Attributes</b><br><br>
  1865. <ul>
  1866. <ul>
  1867. <li><b><a href="#do_not_notify">do_not_notify</a></b></li>
  1868. <li><b><a href="#readingFnAttributes">readingFnAttributes</a></b></li>
  1869. <li><b><a name="request-timeout">request-timeout</a></b></li>
  1870. <br>Optional attribute change the response timeout in seconds for all queries to the receiver.
  1871. <br>Possible values: 1...5 seconds. Default value is 4 seconds.<br><br>
  1872. <li><b><a name="disable">disable</a></b></li>
  1873. <br>Optional attribute to disable the internal cyclic status update of the receiver. Manual status updates via statusRequest command is still possible.
  1874. <br>Possible values: 0 &rarr; perform cyclic status update, 1 &rarr; don't perform cyclic status updates.<br><br>
  1875. <li><b><a name="auto-update-player-readings">auto-update-player-readings</a></b></li>
  1876. <br>Optional attribute for auto refresh of player related readings. Default is 1.<br><br>
  1877. <li><b><a name="auto-update-tuner-readings">auto-update-tuner-readings</a></b></li>
  1878. <br>Optional attribute for auto refresh of tuner related readings. Default is 1.<br><br>
  1879. <li><b><a name="smooth-volume-change">smooth-volume-change</a></b></li>
  1880. <br>Optional attribute for smooth volume change (more Ethernet traffic is generated during volume change). Default is 1.<br><br>
  1881. <br><br>
  1882. </ul>
  1883. </ul>
  1884. <b>Readings</b><br>
  1885. <ul>
  1886. <ul>
  1887. <br><br><u>Basic readings:</u><br><br>
  1888. <li><b>input</b> - The selected input source according to the FHEM input commands</li>
  1889. <li><b>mute</b> - Reports the mute status of the receiver (on|off)</li>
  1890. <li><b>power</b> - Reports the power status of the receiver (on|off)</li>
  1891. <li><b>presence</b> - Reports the presence status of the receiver or zone (absent|present). <i>Note: In case of "absent", the device cannot be controlled by FHEM. Check standbyMode.</i></li>
  1892. <li><b>volume</b> - Reports the current volume level of the receiver in &#037; (0...100&#037;)</li>
  1893. <li><b>volumeStraight</b> - Reports the current volume level of the receiver as used and displayed in the device (values device specific)</li>
  1894. <li><b>sleep</b> - Reports the current sleep timer status (30min|60min|90min|120min|off).</li>
  1895. <li><b>standbyMode</b> - Reports the standby mode (eco|normal).</li>
  1896. <li><b>state</b> - Reports the current power state and an absence of the device (on|off|absent)</li>
  1897. <br><br><u>Player related readings:</u><br><br>
  1898. <i>Note: In order to update the following readings use "statusRequest playerStatus" first.</i><br><br>
  1899. <li><b>playerPlaybackInfo</b> - Reports current player state (play|stop|pause).</li>
  1900. <li><b>playerDeviceType</b> - Reports the device type (ipod|msc).</li>
  1901. <li><b>playerIpodMode</b> - Reports the Ipod Mode (normal|off)</li>
  1902. <li><b>playerRepeat</b> - Reports the Repeat Mode (one|off)</li>
  1903. <li><b>playerShuffle</b> - Reports the Shuffle Mode (on|off)</li>
  1904. <li><b>playerPlayTime</b> - Reports the play time of the currently played audio (HH:MM:SS).</li>
  1905. <li><b>playerTrackNumber</b> - Reports the track number of the currently played audio.</li>
  1906. <li><b>playerTotalTracks</b> - Reports the total number of tracks for playing.</li>
  1907. <li><b>playerArtist</b> - Reports the artist (if available) of the currently played audio.</li>
  1908. <li><b>playerAlbum</b> - Reports the album (if available) of the currently played audio.</li>
  1909. <li><b>playerSong</b> - Reports the song name (if available) of the currently played audio.</li>
  1910. <li><b>playerAlbumArtURL</b> - Reports the album art url (if available) of the currently played audio. The URL points to the network player.</li>
  1911. <li><b>playerAlbumArtID</b> - Reports the album art ID (if available) of the currently played audio.</li>
  1912. <li><b>playerAlbumArtFormat</b> - Reports the album art format (if available) of the currently played audio.</li>
  1913. <br><br><u>Player List (Menu) related readings:</u><br><br>
  1914. <i>Note: In order to update the following readings use "statusRequest playerStatus" first.</i><br><br>
  1915. <li><b>playerListCurrentLine</b> - Reports the current active list line as displayd.</li>
  1916. <li><b>playerListLine_1..._8</b> - Reports the content of the Line 1...8 as provided by the device.</li>
  1917. <li><b>playerListLine_Attribute_1..._8</b> - Reports the attribute of the Line 1...8 (Container|Item|Unselectable).</li>
  1918. <li><b>playerListMaxLine</b> - Reports the number of lines in current list/menu.</li>
  1919. <li><b>playerListMenuName</b> - Reports the name of the current list/menu.</li>
  1920. <li><b>playerListStatus</b> - Reports the status of the current list/menu (Busy|Ready).</li>
  1921. <br><br><u>Tuner related readings:</u><br><br>
  1922. <i>Note: In order to update the following readings use "statusRequest tunerStatus" first.</i><br><br>
  1923. <li><b>tunerAudioModeDAB</b> - Reports current audio mode (Mono|Stereo).</li>
  1924. <li><b>tunerBand</b> - Reports the currently selected tuner band (FM|DAB). DAB if available.</li>
  1925. <li><b>tunerBitRateDAB</b> - Reports current DAB stream bit rate (kbit/s).</li>
  1926. <li><b>tunerPresetFM</b> - Reports the currently selected FM preset. If stored as such (1...30).</li>
  1927. <li><b>tunerFrequencyDAB</b> - Reports the currently tuned DAB frequency. (xxx.xxx MHz)</li>
  1928. <li><b>tunerFrequencyFM</b> - Reports the currently tuned FM frequency. (xxx.xx MHz)</li>
  1929. <li><b>tunerModeDAB</b> - Reports current DAB audio mode (DAB|DAB+).</li>
  1930. <li><b>tunerProgramServiceFM</b> - Reports the FM service name.</li>
  1931. <li><b>tunerRadioTextAFM</b> - Reports the Radio Text A of the selected FM service.</li>
  1932. <li><b>tunerRadioTextBFM</b> - Reports the Radio Text B of the selected FM service.</li>
  1933. <li><b>tunerPresetDAB</b> - Reports the currently selected DAB preset. If stored as such (1...30).</li>
  1934. <li><b>tunerServiceLabelDAB</b> - Reports the service label of the selected DAB service.</li>
  1935. <li><b>tunerChannelLabelDAB</b> - Reports the channel label of the selected DAB service.</li>
  1936. <li><b>tunerDLSDAB</b> - Reports the dynamic label segment of the selected DAB service.</li>
  1937. <li><b>tunerEnsembleLabelDAB</b> - Reports the ensemble label of the selected DAB service.</li>
  1938. <br><br><u>Timer related readings:</u><br><br>
  1939. <i>Note: In order to update the following readings use "statusRequest timerStatus" first.</i><br><br>
  1940. <li><b>timer</b> - Reports the time mode (on|off).</li>
  1941. <li><b>timerRepeat</b> - Reports the timer repeat mode (once|every).</li>
  1942. <li><b>timerStartTime</b> - Reports the timer start time (HH:MM).</li>
  1943. <li><b>timerVolumeLevel</b> - Reports the timer volume level.</li>
  1944. </ul>
  1945. </ul><br>
  1946. <b>Implementer's note</b><br><br>
  1947. <ul>
  1948. Trivial: In order to use that module the network player must be connected to the Ethernet.<br>
  1949. The device must be in standbyMode "Normal" in order to power on.<br>
  1950. 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.<br>
  1951. </ul><br>
  1952. </ul>
  1953. =end html
  1954. =begin html_DE
  1955. <a name="YAMAHA_NP"></a>
  1956. <h3>YAMAHA_NP</h3>
  1957. <ul>
  1958. <a name="YAMAHA_NPdefine"></a>
  1959. <b>Define</b><br><br>
  1960. <ul>
  1961. <code>
  1962. define &lt;name&gt; YAMAHA_NP &lt;ip-address&gt; [&lt;status_interval&gt;]<br><br>
  1963. define &lt;name&gt; YAMAHA_NP &lt;ip-address&gt; [&lt;off_status_interval&gt;] [&lt;on_status_interval&gt;]
  1964. </code>
  1965. <br><br>
  1966. Mit Hilfe dieses Moduls lassen sich Yamaha Network Player (z.B. MCR-N560, MCR-N560D, CRX-N560, CRX-N560D, CD-N500 or NP-S2000) via Ethernet steuern.<br>
  1967. Theoretisch sollten alle Ger&auml;te, die mit der Yamaha Network Player App kompatibel sind, bedient werden k&ouml;nnen.<br><br>
  1968. Die aktuelle Implementierung erm&ouml;glicht u.a. den folgenden Funktionsumfang:<br><br>
  1969. <ul>
  1970. <li>Power on/off</li>
  1971. <li>Timer on/off</li>
  1972. <li>Input selection</li>
  1973. <li>Timer on/off</li>
  1974. <li>Volume +/-</li>
  1975. <li>Mute on/off</li>
  1976. <li>System Clock Update</li>
  1977. <li>Tuner: tune +/-, preset +/-, Senderinformation (FM/DAB)</li>
  1978. <li>Stand-by mode: eco/normal</li>
  1979. <li>Player (play, stop, next, prev, shuffle, repeat)</li>
  1980. <li>Men&uuml;navigation</li>
  1981. <li>...</li>
  1982. </ul>
  1983. <br>
  1984. Eine YAMAHA_NP Definition initiiert einen internen Task, der von FHEM zyklisch abgearbeitet wird.<br>
  1985. Das Intervall (in Sekunden) kann f&uuml;r die Zust&auml;nde &lt;on_status_interval&gt; und &lt;off_status_interval&gt; optional gesetzt werden.<br>
  1986. &lt;off_status_interval&gt; steht f&uuml;r das Intervall, wenn das Ger&auml;t ausgeschaltet/abwesend ist.<br>
  1987. &lt;on_status_interval&gt; steht f&uuml;r das Intervall, wenn das Ger&auml;t eingeschaltet/verf&uuml;gbar ist.<br>
  1988. Wenn keine Parametere angegeben wurden, wird ein Default-Wert von 30 Sekunden f&uuml;r beide gesetzt.<br>
  1989. Wenn nur &lt;off_status_interval&gt; gesetzt wird, gilt dieser Wert f&uuml;r beide Zust&auml;nde (eingeschaltet/ausgeschaltet).<br>
  1990. Der Task liest zyklisch grundlegende Parameter vom Network Player wie z.B. (Power-Status , gew&auml;hlter Eingang, Lautst&auml;rke etc.) und triggert notify/filelog Befehle.<br><br>
  1991. Beispiel:<br><br>
  1992. <ul><br>
  1993. Definition in der <b>fhem.cfg</b> Konfigurationsdatei:<br><br>
  1994. <code>
  1995. define NP_Player YAMAHA_NP 192.168.0.15<br>
  1996. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp<br><br>
  1997. # 60 Sekunden Intervall<br>
  1998. define NP_Player YAMAHA_NP 192.168.0.15 <b>60</b><br>
  1999. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp<br><br>
  2000. # 60 Sekunden Intervall f&uuml;r "off" und 10 Sekunden f&uuml;r "on"<br>
  2001. define NP_Player YAMAHA_NP 192.168.0.15 <b>60 10</b><br>
  2002. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp
  2003. </code>
  2004. </ul>
  2005. </ul><br><br>
  2006. <a name="YAMAHA_NPset"></a>
  2007. <b>Set</b>
  2008. <ul>
  2009. <code>
  2010. set &lt;name&gt; &lt;command&gt; [&lt;parameter&gt;]
  2011. </code>
  2012. <br><br>
  2013. Aktuell sind folgende Befehle implementiert:<br>
  2014. Die verf&uuml;gbaren Eing&auml;nge des Network Players werden vom diesem gelesen und dynamisch in FHEM angepasst.<br><br>
  2015. <i>Bemerkung: Bitte bei den Befehlen und Parametern die Gro&szlig;- und Kleinschreibung beachten.</i><br><br>
  2016. <ul><br><br>
  2017. <u>Verf&uuml;gbare Befehle:</u><br><br>
  2018. <li><b>cdTray</b>&nbsp;&nbsp;-&nbsp;&nbsp; &Ouml;ffnen und Schlie&szlig;en des CD-Fachs.</li>
  2019. <li><b>clockUpdate</b>&nbsp;&nbsp;-&nbsp;&nbsp; Aktualisierung der Systemzeit des Network Players. Die Zeitinformation wird von dem FHEM Server bezogen, auf dem das Modul ausgef&uuml;hrt wird.</li>
  2020. <li><b>dimmer</b> [1..3] &nbsp;&nbsp;-&nbsp;&nbsp; Einstellung der Anzeigenhelligkeit.</li>
  2021. <li><b>input</b> [&lt;parameter&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; Auswahl des Eingangs des NP. Der aktive Eingang wird vom Ger&auml;t gelesen und in FHEM dynamisch dargestellt (z.B. cd, tuner, aux1, aux2, ...).</li>
  2022. <li><b>mute</b> [on|off] &nbsp;&nbsp;-&nbsp;&nbsp; Aktiviert/Deaktiviert die Stummschaltung.</li>
  2023. <li><b>off</b> &nbsp;&nbsp;-&nbsp;&nbsp; Network Player ausschalten.</li>
  2024. <li><b>on</b> &nbsp;&nbsp;-&nbsp;&nbsp; Network Player einschalten.</li>
  2025. <li><b>player [&lt;parameter&gt;] </b> &nbsp;&nbsp;-&nbsp;&nbsp; Setzt Player relevante Befehle.</li>
  2026. <ul>
  2027. <li><b>play</b>&nbsp;&nbsp;-&nbsp;&nbsp; play.</li>
  2028. <li><b>stop</b>&nbsp;&nbsp;-&nbsp;&nbsp; stop.</li>
  2029. <li><b>pause</b>&nbsp;&nbsp;-&nbsp;&nbsp; pause.</li>
  2030. <li><b>next</b>&nbsp;&nbsp;-&nbsp;&nbsp; n&auml;chstes Audiost&uuml;ck.</li>
  2031. <li><b>prev</b>&nbsp;&nbsp;-&nbsp;&nbsp; vorheriges Audiost&uuml;ck.</li>
  2032. <li><b>shuffleToggle</b>&nbsp;&nbsp;-&nbsp;&nbsp; Umschaltung des Zufallswiedergabe.</li>
  2033. <li><b>repeatToggle</b>&nbsp;&nbsp;-&nbsp;&nbsp; Umschaltung des Wiederholungsmodes.</li>
  2034. </ul>
  2035. <li><b>playerListCursorDown</b>&nbsp;&nbsp;-&nbsp;&nbsp;Befehl zur Navigation in Eing&auml;ngen wie Net Radio oder Server. Befehl bewegt den Cursor nach unten. N&auml;chste Zeile wird im Ger&auml;t angezeit.</li>
  2036. <li><b>playerListCursorReturn</b>&nbsp;&nbsp;-&nbsp;&nbsp;Befehl zur Navigation in Eing&auml;ngen wie Net Radio oder Server. Befehl kehrt zur&uuml;ck vom hierarchischen, untergeordneten Men&uuml;. &Uuml;bergeordnetes Men&uuml; wird angezeigt.</li>
  2037. <li><b>playerListCursorUp</b>&nbsp;&nbsp;-&nbsp;&nbsp;Befehl zur Navigation in Eing&auml;ngen wie Net Radio oder Server. Befehl bewegt den Cursor nach oben. Vorherige Zeile wird im Ger&auml;t angezeit.</li>
  2038. <li><b>playerListGetList</b>&nbsp;&nbsp;-&nbsp;&nbsp;Befehl zur Navigation in Eing&auml;ngen wie Net Radio oder Server. Befehl liefert Informationen (Readings) relevant zur Men&uuml;navigation.</li>
  2039. <li><b>playerListJumpLine [value]</b>&nbsp;&nbsp;-&nbsp;&nbsp;Befehl zur Navigation in Eing&auml;ngen wie Net Radio oder Server. Befehl spring zur angegebenen Zeile.</li>
  2040. <li><b>playerListSelectLine [value]</b>&nbsp;&nbsp;-&nbsp;&nbsp;Befehl zur Navigation in Eing&auml;ngen wie Net Radio oder Server. Befehl aktiviert die angegebenen Zeile. Falls die Zeile das Attribut 'Container' (Ordner) besitzt, wird dieser ge&ouml;ffnet. Falls 'Item' wird die Wiedergabe gestartet.</li>
  2041. <li><b>sleep</b> [off|30min|60min|90min|120min] &nbsp;&nbsp;-&nbsp;&nbsp; Aktiviert/Deaktiviert den internen Sleep-Timer</li>
  2042. <li><b>standbyMode</b> [eco|normal] &nbsp;&nbsp;-&nbsp;&nbsp; Umschaltung des Standby Modus.</li>
  2043. <li><b>statusRequest [&lt;parameter&gt;] </b> &nbsp;&nbsp;-&nbsp;&nbsp; Abfrage des aktuellen Status des Network Players.</li>
  2044. <ul>
  2045. <li><b>basicStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage der Elementarparameter (z.B. Lautst&auml;rke, Eingang, etc.)</li>
  2046. <li><b>playerStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage des Player-Status.</li>
  2047. <li><b>standbyMode</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage des standby Modus.</li>
  2048. <li><b>systemConfig</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage der Systemkonfiguration.</li>
  2049. <li><b>tunerStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage des Tuner-Status (z.B. FM Frequenz, Preset-Nummer, DAB Information etc.)</li>
  2050. <li><b>timerStatus</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage des internen Wake-up timers.</li>
  2051. <li><b>networkInfo</b>&nbsp;&nbsp;-&nbsp;&nbsp; Abfrage von Netzwerk-relevanten Informationen (z.B: IP-Adresse, Gateway-Adresse, MAC-address etc.)</li>
  2052. </ul>
  2053. <li><b>timerHour</b> [0...23] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die Stunde des internen Wake-up Timers</li>
  2054. <li><b>timerMinute</b> [0...59] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die Minute des internen Wake-up Timers</li>
  2055. <li><b>timerRepeat</b> [once|every] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt den Wiederholungsmodus des internen Wake-up Timers</li>
  2056. <li><b>timerSet</b> &nbsp;&nbsp;-&nbsp;&nbsp; konfiguriert den Timer nach den Vorgaben: timerHour, timerMinute, timerRepeat, timerVolume. (ALLE Paremeter m&uuml;ssen zuvor gesetzt werden. Dieser Befehl schaltet den Timer nicht ein &rarr; 'timer on'.)</li>
  2057. <li><b>timerVolume</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die Lautst&auml;rke des internen Wake-up Timers</li>
  2058. <li><b>timer</b> [on|off] &nbsp;&nbsp;-&nbsp;&nbsp; Schaltet ein/aus den internen Wake-up Timer. <i>(Bemerkung: Der Timer wird basierend auf den im Ger&auml;t gespeicherten Parametern aktiviert. Um diese zu &auml;ndern, bitte den 'timerSet' Befehl benutzen.)</i></li>
  2059. <li><b>tuner [&lt;parameter&gt;] </b> &nbsp;&nbsp;-&nbsp;&nbsp; Tuner-relevante Befehle.</li>
  2060. <ul>
  2061. <li><b>bandDAB</b>&nbsp;&nbsp;-&nbsp;&nbsp; Setzt das Tuner-Band auf DAB (falls verf&uuml;gbar).</li>
  2062. <li><b>bandFM</b>&nbsp;&nbsp;-&nbsp;&nbsp; Setzt das Tuner-Band auf FM.</li>
  2063. <li><b>tuneUp</b>&nbsp;&nbsp;-&nbsp;&nbsp; Tuner Frequenz +.</li>
  2064. <li><b>tuneDown</b>&nbsp;&nbsp;-&nbsp;&nbsp; Tuner Frquenz -.</li>
  2065. <li><b>presetUp</b>&nbsp;&nbsp;-&nbsp;&nbsp; Tuner Voreinstellung hoch.</li>
  2066. <li><b>presetDown</b>&nbsp;&nbsp;-&nbsp;&nbsp; Tuner Voreinstellung runter.</li>
  2067. </ul>
  2068. <li><b>tunerFMFrequency</b> [87.50 ... 108.00] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die FM Frequenz. Der Wert muss zwischen 87.50 ... 108.00 liegen und muss den Digitalpunkt beinhalten ('.') mit zwei Nachkommastellen.</li>
  2069. <li><b>tunerPresetDAB</b> [1...30] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die DAB Voreinstellung.</li>
  2070. <li><b>tunerPresetFM</b> [1...30] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die FM Voreinstellung.</li>
  2071. <li><b>volume</b> [0...100] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt den Lautst&auml;rkepegel in &#037;</li>
  2072. <li><b>volumeStraight</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die absolute Lautst&auml;rke wie vom Ger&auml;t benutzt und angezeigt. Die Parameter &lt;VOL_MIN&gt; and &lt;VOL_MAX&gt; werden automatisch ermittelt.</li>
  2073. <li><b>volumeUp</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; Erh&ouml;ht die Lautst&auml;rke um einen absoluten Schritt. Die Parameter &lt;VOL_MIN&gt; and &lt;VOL_MAX&gt; werden automatisch ermittelt.</li>
  2074. <li><b>volumeDown</b> [&lt;VOL_MIN&gt;...&lt;VOL_MAX&gt;] &nbsp;&nbsp;-&nbsp;&nbsp; Reduziert die Lautst&auml;rke um einen absoluten Schritt. Die Parameter &lt;VOL_MIN&gt; and &lt;VOL_MAX&gt; werden automatisch ermittelt.</li>
  2075. </ul><br><br>
  2076. Ein typisches Beispiel ist das Einschalten des Ger&auml;tes und das Umschalten auf den Lieblingsradiosender:<br><br>
  2077. Beispieldefinition in der <b>fhem.cfg</b> Konfigurationsdatei:<br><br><br>
  2078. <ul>
  2079. <code>
  2080. define NP_player YAMAHA_NP 192.168.0.15 30 5<br>
  2081. attr NP_player webCmd input:volume:mute:volumeDown:volumeUp
  2082. </code>
  2083. </ul><br><br>
  2084. Folgender Code kann anschlie&szlig;end in die Datei <b>99_MyUtils.pm</b> eingebunden werden:<br><br>
  2085. <ul>
  2086. <code>
  2087. sub startMyFavouriteRadioStation()<br>
  2088. {<br>
  2089. &nbsp;&nbsp;fhem "set NP_player on";<br>
  2090. &nbsp;&nbsp;sleep 1;<br>
  2091. &nbsp;&nbsp;fhem "set NP_player input tuner";<br>
  2092. &nbsp;&nbsp;sleep 1;<br>
  2093. &nbsp;&nbsp;fhem "set NP_player tunerPresetDAB 1";<br>
  2094. &nbsp;&nbsp;sleep 1;<br>
  2095. &nbsp;&nbsp;fhem "set NP_player volume 30";<br>
  2096. }
  2097. </code>
  2098. </ul><br><br>
  2099. <i>Bemerkung: Aufgrund der relativ langsamen Befehlsverarbeitung im Network Player im Vergleich zur asynchronen Ethernet-Kommunikation, kann es vorkommen, dass veraltete Statusinformationen zur&uuml;ckgesendet werden.<br>
  2100. Aus diesem Grund wird empfohlen, w&auml;hrend der Automatisierung zwischen den 'set' und 'get' Befehlen ein Delay einzubauen. Speziell beim Hochfahren des Network Players sollte dies beachtet werden.</i><br><br>
  2101. Die Funktion kann jetzt in der FHEM Befehlszeile eingegeben oder in die Notify-Definitionen eingebunden werden.<br><br>
  2102. <ul>
  2103. <code>
  2104. {startMyFavouriteRadioStation()}<br><br>
  2105. </code>
  2106. </ul>
  2107. </ul>
  2108. <a name="YAMAHA_NPget"></a>
  2109. <b>Get</b>
  2110. <code>
  2111. get &lt;name&gt; &lt;reading&gt;
  2112. </code><br><br>
  2113. Aktuell liefert der Befehl 'get' ausschlie&szlig;lich Reading-Werte (s. Abschnitt <b>"Readings"</b>).<br><br>
  2114. </ul>
  2115. <a name="YAMAHA_NPattr"></a>
  2116. <ul>
  2117. <b>Attribute</b><br><br>
  2118. <ul>
  2119. <ul>
  2120. <li><b><a href="#do_not_notify">do_not_notify</a></b></li>
  2121. <li><b><a href="#readingFnAttributes">readingFnAttributes</a></b></li><br>
  2122. <li><b><a name="request-timeout">request-timeout</a></b></li><br>
  2123. Optionales Attribut, um das HTTP response timeout zu beeinflu&szlig;en.<br>
  2124. M&ouml;gliche Werte: 1...5 Sekunden. Default Wert ist 4 Sekunden.<br><br>
  2125. <li><b><a name="disable">disable</a></b></li><br>
  2126. Optionales Attribut zum Deaktivieren des internen zyklischen Timers zum Aktualisieren des NP-Status. Manuelles Update ist nach wie vor m&ouml;glich.<br>
  2127. M&ouml;gliche Werte: 0 &rarr; Zyklisches Update aktiv., 1 &rarr; Zyklisches Update inaktiv.<br><br>
  2128. <li><b><a name="auto-update-player-readings">auto-update-player-readings</a></b></li>
  2129. <br>Optionales Attribut zum automtischen aktualisieren der Player-Readings. Default-Wert ist 1.<br><br>
  2130. <li><b><a name="auto-update-tuner-readings">auto-update-tuner-readings</a></b></li>
  2131. <br>Optionales Attribut zum automtischen aktualisieren der Tuner-Readings. Default-Wert ist 1.<br><br>
  2132. <li><b><a name="smooth-volume-change">smooth-volume-change</a></b></li>
  2133. <br>Optionales Attribut zur sanften Lautst&auml;rke&auml;nderung (Erzeugt mehr Ethernetkommunikation w&auml;hrend der Lautst&auml;rke&auml;nderung). Default-Wert ist 1.<br><br>
  2134. <br><br>
  2135. </ul>
  2136. </ul>
  2137. <b>Readings</b><br>
  2138. <ul>
  2139. <ul>
  2140. <br><br><u>Elementar-Readings:</u><br><br>
  2141. <li><b>input</b> - Aktivierter Eingang.</li>
  2142. <li><b>mute</b> - Abfrage des Mute Status (on|off)</li>
  2143. <li><b>power</b> - Abfrage des Power-Status (on|off)</li>
  2144. <li><b>presence</b> - Abfrage der Ger&auml;teanwesenheit im Netzwerk (absent|present). <i>Bemerkung: Falls abwesend ("absent"), l&auml;sst sich das Ger&auml;t nicht fernbedienen.</i></li>
  2145. <li><b>volume</b> - Abfrage der aktuell eingestellten Lautst&auml;rke in &#037; (0...100&#037;)</li>
  2146. <li><b>volumeStraight</b> - Abfrage der aktuellen absoluten Ger&auml;telautst&auml;rke im Ger&auml;t (ger&auml;tespezifisch)</li>
  2147. <li><b>sleep</b> - Abfrage des Sleep-Timer Status (30min|60min|90min|120min|off).</li>
  2148. <li><b>standbyMode</b> - Abfrage des standby Modus (eco|normal).</li>
  2149. <li><b>state</b> - Abfrage des aktuellen Power Zustands und Anwesenheit (on|off|absent).</li>
  2150. <br><br><u>Player Readings:</u><br><br>
  2151. <i>Bemerkung: Die folgenden Readings werden mit dem Befehl "statusRequest playerStatus" aktualisiert.</i><br><br>
  2152. <li><b>playerPlaybackInfo</b> - Abfrage des aktuellen Player Status (play|stop|pause).</li>
  2153. <li><b>playerDeviceType</b> - Abfrage des Device Typs (ipod|msc).</li>
  2154. <li><b>playerIpodMode</b> - Abfrage des *Pod/*Pad/*Phone Modus (normal|off)</li>
  2155. <li><b>playerRepeat</b> - Abfrage des Wiederholungsmodus (one|all)</li>
  2156. <li><b>playerShuffle</b> - Abfrage des Zufallswiedergabemodus (on|off)</li>
  2157. <li><b>playerPlayTime</b> - Abfrage der aktuellen Spielzeit (HH:MM:SS).</li>
  2158. <li><b>playerTrackNumber</b> - Abfrage der Audiotracknummer.</li>
  2159. <li><b>playerTotalTracks</b> - Abfrage der Gesamtzahl der zu wiedergebenden Tracks.</li>
  2160. <li><b>playerArtist</b> - Abfrage des K&uuml;nstler (Artist) (falls verf&uuml;gbar) der aktuellen Wiedergabe.</li>
  2161. <li><b>playerAlbum</b> - Abfrage des Albumnamens (falls verf&uuml;gbar) der aktuellen Wiedergabe.</li>
  2162. <li><b>playerSong</b> - Abfrage des Tracknamens (falls verf&uuml;gbar) der aktuellen Wiedergabe.</li>
  2163. <li><b>playerAlbumArtURL</b> - Abfrage der Album URL (falls verf&uuml;gbar) der aktuellen Wiedergabe.</li>
  2164. <li><b>playerAlbumArtID</b> - Abfrage der AlbumArtID (falls verf&uuml;gbar) der aktuellen Wiedergabe.</li>
  2165. <li><b>playerAlbumArtFormat</b> - Abfrage des AlbumArt Formats (falls verf&uuml;gbar) der aktuellen Wiedergabe.</li>
  2166. <br><br><u>Player List (Menu) Readings:</u><br><br>
  2167. <i>Bemerkung: Die folgenden Readings werden mit dem Befehl "statusRequest playerStatus" aktualisiert.</i><br><br>
  2168. <li><b>playerListCurrentLine</b> - Abfrage der aktuellen Listenzeile (wie im Ger&auml;t angezeigt).</li>
  2169. <li><b>playerListLine_1..._8</b> - Abfrage des Listeninhalts Zeile 1...8 (Das Ger&auml;t liefert 8 Zeilen Pakete).</li>
  2170. <li><b>playerListLine_Attribute_1..._8</b> - Abfrage der Listenzeilenattribute Zeile 1...8 (Container|Item|Unselectable).</li>
  2171. <li><b>playerListMaxLine</b> - Abfrage der Anzahl von Listenzeilen in der aktuellen Liste/Menu.</li>
  2172. <li><b>playerListMenuName</b> - Abfrage der bezeichnung der aktuellen Liste/Menus.</li>
  2173. <li><b>playerListStatus</b> - Abfrage des aktuellen Status der Liste/Menus (Busy|Ready).</li>
  2174. <br><br><u>Tuner Readings:</u><br><br>
  2175. <i>Bemerkung: Die folgenden Readings werden mit dem Befehl "statusRequest tunerStatus" aktualisiert.</i><br><br>
  2176. <li><b>tunerAudioModeDAB</b> - Abfrage des aktuellen DAB Audio-Modus (Mono|Stereo)..</li>
  2177. <li><b>tunerBand</b> - Abfrage des aktuellen Radio-Bandes (FM|DAB). DAB falls verf&uuml;gbar.</li>
  2178. <li><b>tunerBitRate</b> - Abfrage der aktuellen DAB Stream Bitrate (kbit/s).</li>
  2179. <li><b>tunerModeDAB</b> - Abfrage des aktuellen DAB Modus (DAB|DAB+).</li>
  2180. <li><b>tunerFrequencyDAB</b> - Abfrage der aktuellen DAB Frequenz. (xxx.xxx MHz)</li>
  2181. <li><b>tunerPresetFM</b> - Abfrage der aktuellen FM Voreinstellung. Falls gespeichtert (1...30).</li>
  2182. <li><b>tunerFrequencyFM</b> - Abfrage der aktuellen FM Frequenz. (xxx.xx MHz)</li>
  2183. <li><b>tunerProgramServiceFM</b> - Abfrage des FM Sendernamen.</li>
  2184. <li><b>tunerRadioTextAFM</b> - Abfrage des Radio Text A des FM Senders.</li>
  2185. <li><b>tunerRadioTextBFM</b> - Abfrage des Radio Text B des FM Senders.</li>
  2186. <li><b>tunerPresetDAB</b> - Abfrage der aktuellen DAB Voreinstellung. Falls gespeichtert (1...30).</li>
  2187. <li><b>tunerServiceLabelDAB</b> - Abfrage des DAB Sendernamen.</li>
  2188. <li><b>tunerChannelLabelDAB</b> - Abfrage des Channel Labels des gew&auml;hlten DAB Senders.</li>
  2189. <li><b>tunerDLSDAB</b> - Abfrage des 'Dynamic Label Segment' des gew&auml;hlten DAB Senders.</li>
  2190. <li><b>tunerEnsembleLabelDAB</b> - Abfrage des 'Ensemble Label' des gew&auml;hlten DAB Senders.</li>
  2191. <br><br><u>Timer Readings:</u><br><br>
  2192. <i>Bemerkung: Die folgenden Readings werden mit dem Befehl "statusRequest timerStatus" aktualisiert.</i><br><br>
  2193. <li><b>timer</b> - Abfrage des Time Modus (Wecker) (on|off).</li>
  2194. <li><b>timerRepeat</b> - Abfrage des Timer Wiederholungs Modus (once|every).</li>
  2195. <li><b>timerStartTime</b> - Abfrage der Timer Startzeit (HH:MM).</li>
  2196. <li><b>timerVolumeLevel</b> - Abfrage der Timer-Lautst&auml;rke.</li>
  2197. </ul>
  2198. </ul><br>
  2199. <b>Bemerkung des Entwicklers</b><br><br>
  2200. <ul>
  2201. Trivial: Um das Ger&auml;t fernbedienen zu k&ouml;nnen, muss es an das Ethernet-Netzwerk angeschlossen und erreichbar sein.<br>
  2202. Das Ger&auml;t muss sich im standbyMode "Normal" befinden, um es fergesteuert einzuschalten.<br>
  2203. Das Abschalten funktioniert auch standbyMode "Normal" Modus.<br>
  2204. </ul><br>
  2205. </ul>
  2206. =end html_DE
  2207. =cut