71_PHILIPS_AUDIO.pm 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563
  1. ##############################################################################
  2. #
  3. # $Id: 71_PHILIPS_AUDIO.pm 11329 2016-04-27 18:00:43Z ra666ack $
  4. #
  5. # 71_PHILIPS_AUDIO.pm
  6. #
  7. # An FHEM Perl module for controlling Philips Audio Equipment connected to local network
  8. # such as MCi, Streamium and Fidelio devices.
  9. # The module provides basic functionality accessible through the port 8889 of the device:
  10. # (http://<device_ip>:8889/index).
  11. # e.g. AW9000, NP3500, NP3700, NP3900
  12. #
  13. # Copyright by Radoslaw Watroba
  14. # (e-mail: ra666ack at g**glemail d*t c*m)
  15. #
  16. # This file is part of fhem.
  17. #
  18. # Fhem is free software: you can redistribute it and/or modify
  19. # it under the terms of the GNU General Public License as published by
  20. # the Free Software Foundation, either version 2 of the License, or
  21. # (at your option) any later version.
  22. #
  23. # Fhem is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. # GNU General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU General Public License
  29. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  30. #
  31. ##############################################################################
  32. package main;
  33. use strict;
  34. use warnings;
  35. use Time::HiRes qw(gettimeofday sleep);
  36. use Time::Piece;
  37. use POSIX qw{strftime};
  38. use HttpUtils;
  39. ###################################
  40. sub PHILIPS_AUDIO_Initialize
  41. {
  42. my ($hash) = @_;
  43. $hash->{DefFn} = "PHILIPS_AUDIO_Define";
  44. $hash->{GetFn} = "PHILIPS_AUDIO_Get";
  45. $hash->{SetFn} = "PHILIPS_AUDIO_Set";
  46. $hash->{AttrFn} = "PHILIPS_AUDIO_Attr";
  47. $hash->{UndefFn} = "PHILIPS_AUDIO_Undefine";
  48. $hash->{AttrList} = "do_not_notify:0,1 disable:0,1 model max-device-presets max-device-favorites request-timeout:1,2,3,4,5 ".$readingFnAttributes;
  49. return;
  50. }
  51. ###################################
  52. sub PHILIPS_AUDIO_GetStatus
  53. {
  54. my ($hash, $local) = @_;
  55. my $name = $hash->{NAME};
  56. my $power;
  57. $local = 0 unless(defined($local));
  58. return "" if((!defined($hash->{IP_ADDRESS})) or (!defined($hash->{helper}{OFF_INTERVAL})) or (!defined($hash->{helper}{ON_INTERVAL})));
  59. my $device = $hash->{IP_ADDRESS};
  60. # Check for Presets availability
  61. if(not defined($hash->{READINGS}{"totalInetRadioPresets"}))
  62. {
  63. # Hierarchichal navigation through the contents mandatory
  64. $hash->{helper}{cmdStep} = 1;
  65. PHILIPS_AUDIO_SendCommand($hash, "/index", "", "getInetRadioPresets", "noArg");
  66. # Wait 10 seconds for next http request due to slow command processing of the streamium devices.
  67. PHILIPS_AUDIO_ResetTimer($hash, 10);
  68. return;
  69. }
  70. # Check for Favorites availability
  71. if(not defined($hash->{READINGS}{"totalInetRadioFavorites"}))
  72. {
  73. # Hierarchichal navigation through the contents mandatory
  74. $hash->{helper}{cmdStep} = 1;
  75. PHILIPS_AUDIO_SendCommand($hash, "/index", "", "getInetRadioFavorites", "noArg");
  76. # Wait 10 seconds for next http request due to slow command processing of the streamium devices.
  77. PHILIPS_AUDIO_ResetTimer($hash, 10);
  78. return;
  79. }
  80. PHILIPS_AUDIO_SendCommand($hash, "/nowplay", "","nowplay", "noArg");
  81. PHILIPS_AUDIO_ResetTimer($hash) unless($local == 1);
  82. return;
  83. }
  84. ###################################
  85. sub PHILIPS_AUDIO_Get
  86. {
  87. my ($hash, @a) = @_;
  88. my $what;
  89. my $return;
  90. my $name = $hash->{NAME};
  91. my $address = $hash->{IP_ADDRESS};
  92. $hash->{IP_ADDRESS} = $address;
  93. return "argument is missing" if(int(@a) != 2);
  94. if(not defined($hash->{MODEL}))
  95. {
  96. return "Please provide the model information as argument.";
  97. }
  98. $what = $a[1];
  99. if(exists($hash->{READINGS}{$what}))
  100. {
  101. if(defined($hash->{READINGS}{$what}))
  102. {
  103. return $hash->{READINGS}{$what}{VAL};
  104. }
  105. else
  106. {
  107. return "no such reading: $what";
  108. }
  109. }
  110. else
  111. {
  112. $return = "unknown argument $what, choose one of";
  113. foreach my $reading (keys %{$hash->{READINGS}})
  114. {
  115. $return .= " $reading:noArg";
  116. }
  117. return $return;
  118. }
  119. }
  120. ###################################
  121. sub PHILIPS_AUDIO_Set
  122. {
  123. my ($hash, @a) = @_;
  124. my $name = $hash->{NAME};
  125. my $port = $hash->{PORT};
  126. if(not defined($hash->{MODEL}))
  127. {
  128. return "Please provide the model information as argument.";
  129. }
  130. return "No Argument given" if(!defined($a[1]));
  131. my $what = $a[1];
  132. my $index;
  133. # Provide number of selectable presets according to the given attribute
  134. my $inetRadioPreset = "inetRadioPreset:";
  135. for ($index = 1; $index < AttrVal($name, "max-device-presets", "24"); $index++)
  136. {
  137. $inetRadioPreset .= $index . ",";
  138. }
  139. $inetRadioPreset .= $index . " ";
  140. # Provide number of selectable favorites according to the given attribute
  141. my $inetRadioFavorite = "inetRadioFavorite:";
  142. for ($index = 1; $index < AttrVal($name, "max-device-favorites", "24"); $index++)
  143. {
  144. $inetRadioFavorite .= $index . ",";
  145. }
  146. $inetRadioFavorite .= $index . " ";
  147. my $usage;
  148. my $model = $hash->{MODEL};
  149. $usage = "Unknown argument $what, choose one of ".
  150. "volumeStraight:slider,0,1,64 ".
  151. "volume:slider,0,1,100 ".
  152. #"volumeUp:noArg ".
  153. #"volumeDown:noArg ".
  154. "standbyButton:noArg ".
  155. "unmute:noArg ".
  156. "next:noArg ".
  157. "previous:noArg ".
  158. "play_pause:noArg ".
  159. "stop:noArg ".
  160. "shuffle:on,off ".
  161. "aux:noArg ".
  162. ((uc($model) eq "AW9000") ? "mp3link:noArg " : ""). # Input implemented in AW9000 only
  163. ((uc($model) eq "AW9000") ? "coaxial:noArg " : ""). # Input implemented in AW9000 only
  164. ((uc($model) eq "AW9000") ? "optical:noArg " : ""). # Input implemented in AW9000 only
  165. #"input:aux,internetRadio,mediaLibrary,onlineServices ".
  166. $inetRadioPreset.
  167. $inetRadioFavorite.
  168. "statusRequest:noArg ".
  169. "getInetRadioPresets:noArg ".
  170. "getInetRadioFavorites:noArg ".
  171. ((exists($hash->{helper}{PRESETS}))? "inetRadioPresetByName:".($hash->{helper}{PRESETS})." ":"").
  172. ((exists($hash->{helper}{FAVORITES}))? "inetRadioFavoriteByName:".($hash->{helper}{FAVORITES})." ":"").
  173. #"addToFavourites:noArg ".
  174. #"removeFromFavourites:noArg ".
  175. "repeat:single,all,off ".
  176. #"home:noArg ".
  177. "mute:noArg ";
  178. Log3 $name, 5, "PHILIPS_AUDIO ($name) - set ".join(" ", @a);
  179. if($what eq "standbyButton")
  180. {
  181. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$STANDBY", "",$what, "noArg");
  182. }
  183. elsif($what eq "aux")
  184. {
  185. PHILIPS_AUDIO_SendCommand($hash, "/aux", "",$what, $a[2]);
  186. }
  187. elsif($what eq "mp3link")
  188. {
  189. PHILIPS_AUDIO_SendCommand($hash, "/mp3link", "",$what, $a[2]);
  190. }
  191. elsif($what eq "coaxial")
  192. {
  193. PHILIPS_AUDIO_SendCommand($hash, "/digin_coaxial", "",$what, $a[2]);
  194. }
  195. elsif($what eq "optical")
  196. {
  197. PHILIPS_AUDIO_SendCommand($hash, "/digin_optical", "",$what, $a[2]);
  198. }
  199. elsif($what eq "home")
  200. {
  201. PHILIPS_AUDIO_SendCommand($hash, "/index", "",$what, $a[2]);
  202. }
  203. elsif($what eq "mediaLibrary")
  204. {
  205. PHILIPS_AUDIO_SendCommand($hash, "/nav\$02\$01\$001\$0", "",$what, $a[2]);
  206. }
  207. elsif($what eq "internetRadio")
  208. {
  209. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "",$what, $a[2]);
  210. }
  211. elsif($what eq "onlineServices")
  212. {
  213. PHILIPS_AUDIO_SendCommand($hash, "/nav\$09\$01\$001\$0", "",$what, $a[2]);
  214. }
  215. elsif($what eq "shuffle")
  216. {
  217. if($a[2] eq "on")
  218. {
  219. PHILIPS_AUDIO_SendCommand($hash, "/MODE\$SHUFFLE_ON", "",$what, $a[2]);
  220. }
  221. elsif($a[2] eq "off")
  222. {
  223. PHILIPS_AUDIO_SendCommand($hash, "/MODE\$SHUFFLE_OFF", "",$what, $a[2]);
  224. }
  225. else
  226. {
  227. return $usage;
  228. }
  229. }
  230. elsif($what eq "repeat")
  231. {
  232. if($a[2] eq "single")
  233. {
  234. PHILIPS_AUDIO_SendCommand($hash, "/MODE\$REPEAT_SINGLE", "",$what, $a[2]);
  235. }
  236. elsif($a[2] eq "all")
  237. {
  238. PHILIPS_AUDIO_SendCommand($hash, "/MODE\$REPEAT_ALL", "",$what, $a[2]);
  239. }
  240. elsif($a[2] eq "off")
  241. {
  242. PHILIPS_AUDIO_SendCommand($hash, "/MODE\$REPEAT_OFF", "",$what, $a[2]);
  243. }
  244. else
  245. {
  246. return $usage;
  247. }
  248. }
  249. elsif($what eq "statusRequest")
  250. {
  251. PHILIPS_AUDIO_SendCommand($hash, "/nowplay", "","nowplay", "noArg");
  252. }
  253. elsif($what eq "addToFavourites")
  254. {
  255. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$ADD2FAV", "",$what, "noArg");
  256. }
  257. elsif($what eq "removeFromFavourites")
  258. {
  259. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$REMFAV", "",$what, "noArg");
  260. }
  261. elsif($what eq "mute")
  262. {
  263. PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$MUTE", "",$what, "noArg");
  264. }
  265. elsif($what eq "unmute")
  266. {
  267. PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$UNMUTE", "",$what, "noArg");
  268. }
  269. elsif($what eq "next")
  270. {
  271. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$NEXT", "",$what, "noArg");
  272. }
  273. elsif($what eq "previous")
  274. {
  275. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$PREV", "",$what, "noArg");
  276. }
  277. elsif($what eq "play_pause")
  278. {
  279. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$PLAY_PAUSE", "",$what, "noArg");
  280. }
  281. elsif($what eq "stop")
  282. {
  283. PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$STOP", "",$what, "noArg");
  284. }
  285. elsif($what eq "inetRadioPreset")
  286. {
  287. # Hierarchichal navigation through the contents mandatory
  288. $hash->{helper}{cmdStep} = 1;
  289. $hash->{helper}{inetRadioPreset} = $a[2];
  290. PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
  291. }
  292. elsif($what eq "inetRadioPresetByName")
  293. {
  294. # Hierarchichal navigation through the contents mandatory
  295. $hash->{helper}{cmdStep} = 1;
  296. my ($presetNumber, $presetName) = split(/:/, $a[2], 2);
  297. $hash->{helper}{inetRadioPresetNumber} = $presetNumber;
  298. PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
  299. }
  300. elsif($what eq "inetRadioFavorite")
  301. {
  302. # Hierarchichal navigation through the contents mandatory
  303. $hash->{helper}{cmdStep} = 1;
  304. $hash->{helper}{inetRadioFavorite} = $a[2];
  305. PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
  306. }
  307. elsif($what eq "inetRadioFavoriteByName")
  308. {
  309. # Hierarchichal navigation through the contents mandatory
  310. $hash->{helper}{cmdStep} = 1;
  311. my ($favoriteNumber, $favoriteName) = split(/:/, $a[2], 2);
  312. $hash->{helper}{inetRadioFavoriteNumber} = $favoriteNumber;
  313. PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
  314. }
  315. elsif($what eq "volumeStraight")
  316. {
  317. if($a[2] >= 0 and $a[2] <= 64)
  318. {
  319. $hash->{helper}{targetVolume} = $a[2];
  320. PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$VAL\$".$a[2], "",$what, $a[2]);
  321. }
  322. else
  323. {
  324. return "volumeStraight must be in the range 0...64.";
  325. }
  326. }
  327. elsif($what eq "volume")
  328. {
  329. if($a[2] >= 0 and $a[2] <= 100)
  330. {
  331. $hash->{helper}{targetVolume} = PHILIPS_AUDIO_volume_rel2abs($hash, $a[2]);
  332. PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$VAL\$".$a[2], "",$what, $a[2]);
  333. }
  334. else
  335. {
  336. return "volumeStraight must be in the range 0...100.";
  337. }
  338. }
  339. elsif($what eq "nowplay")
  340. {
  341. PHILIPS_AUDIO_SendCommand($hash, "/nowplay", "",$what, "noArg");
  342. }
  343. elsif($what eq "getInetRadioPresets")
  344. {
  345. delete($hash->{helper}{PRESETS});
  346. # Hierarchichal navigation through the contents mandatory
  347. $hash->{helper}{cmdStep} = 1;
  348. PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, "noArg");
  349. }
  350. elsif($what eq "getInetRadioFavorites")
  351. {
  352. # Hierarchichal navigation through the contents mandatory
  353. $hash->{helper}{cmdStep} = 1;
  354. PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, "noArg");
  355. }
  356. else
  357. {
  358. return $usage;
  359. }
  360. PHILIPS_AUDIO_ResetTimer($hash);
  361. return;
  362. }
  363. #############################
  364. sub PHILIPS_AUDIO_Define
  365. {
  366. my ($hash, $def) = @_;
  367. my @a = split("[ \t][ \t]*", $def);
  368. my $name = $hash->{NAME};
  369. if(! @a >= 4)
  370. {
  371. my $msg = "Wrong syntax: define <name> PHILIPS_AUDIO <model> <ip-or-hostname> [<ON-statusinterval>] [<OFF-statusinterval>] ";
  372. Log3 $name, 2, $msg;
  373. return $msg;
  374. }
  375. if(defined($a[2]))
  376. {
  377. $hash->{MODEL} = uc($a[2]);
  378. # Used by 'fheminfo' command for statistics
  379. $attr{$name}{"model"} = $hash->{MODEL};
  380. }
  381. $hash->{IP_ADDRESS} = $a[3];
  382. $hash->{PORT} = 8889;
  383. # if an update interval was given which is greater than zero, use it.
  384. if(defined($a[4]) and $a[4] > 0)
  385. {
  386. $hash->{helper}{OFF_INTERVAL} = $a[4];
  387. # Minimum interval 3 sec
  388. if($hash->{helper}{OFF_INTERVAL} < 3)
  389. {
  390. $hash->{helper}{OFF_INTERVAL} = 3;
  391. }
  392. }
  393. else
  394. {
  395. $hash->{helper}{OFF_INTERVAL} = 30;
  396. }
  397. if(defined($a[5]) and $a[5] > 0)
  398. {
  399. $hash->{helper}{ON_INTERVAL} = $a[5];
  400. # Minimum interval 3 sec
  401. if($hash->{helper}{ON_INTERVAL} < 3)
  402. {
  403. $hash->{helper}{ON_INTERVAL} = 3;
  404. }
  405. }
  406. else
  407. {
  408. $hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL};
  409. }
  410. unless(exists($hash->{helper}{AVAILABLE}) and ($hash->{helper}{AVAILABLE} == 0))
  411. {
  412. $hash->{helper}{AVAILABLE} = 1;
  413. readingsSingleUpdate($hash, "presence", "present", 1);
  414. }
  415. # start the status update timer
  416. $hash->{helper}{DISABLED} = 0 unless(exists($hash->{helper}{DISABLED}));
  417. PHILIPS_AUDIO_ResetTimer($hash,0);
  418. return;
  419. }
  420. ##########################
  421. sub PHILIPS_AUDIO_Attr
  422. {
  423. my @a = @_;
  424. my $hash = $defs{$a[1]};
  425. if($a[0] eq "set" && $a[2] eq "disable")
  426. {
  427. if($a[3] eq "0")
  428. {
  429. $hash->{helper}{DISABLED} = 0;
  430. PHILIPS_AUDIO_GetStatus($hash, 1);
  431. }
  432. elsif($a[3] eq "1")
  433. {
  434. $hash->{helper}{DISABLED} = 1;
  435. }
  436. }
  437. elsif($a[0] eq "del" && $a[2] eq "disable")
  438. {
  439. $hash->{helper}{DISABLED} = 0;
  440. PHILIPS_AUDIO_GetStatus($hash, 1);
  441. }
  442. # Start/Stop Timer according to new disabled-Value
  443. PHILIPS_AUDIO_ResetTimer($hash);
  444. return;
  445. }
  446. #############################
  447. sub PHILIPS_AUDIO_Undefine
  448. {
  449. my($hash, $name) = @_;
  450. # Stop the internal GetStatus-Loop and exit
  451. RemoveInternalTimer($hash);
  452. return;
  453. }
  454. ############################################################################################################
  455. #
  456. # Begin of helper functions
  457. #
  458. ############################################################################################################
  459. #############################
  460. # sends a command to the receiver via HTTP
  461. sub PHILIPS_AUDIO_SendCommand
  462. {
  463. my ($hash,$url,$data,$cmd,$arg) = @_;
  464. my $name = $hash->{NAME};
  465. my $address = $hash->{IP_ADDRESS};
  466. my $port = $hash->{PORT};
  467. Log3 $name, 5, "PHILIPS_AUDIO ($name) - execute nonblocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data";
  468. HttpUtils_NonblockingGet
  469. ({
  470. url => "http://".$address.":".$port."".$url,
  471. timeout => AttrVal($name, "request-timeout", 30),
  472. noshutdown => 1,
  473. data => $data,
  474. loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
  475. hash => $hash,
  476. cmd => $cmd,
  477. arg => $arg,
  478. callback => \&PHILIPS_AUDIO_ParseResponse
  479. });
  480. return;
  481. }
  482. #############################
  483. # parses the receiver response
  484. sub PHILIPS_AUDIO_ParseResponse
  485. {
  486. my ($param, $err, $data ) = @_;
  487. my $hash = $param->{hash};
  488. my $name = $hash->{NAME};
  489. my $cmd = $param->{cmd};
  490. my $arg = $param->{arg};
  491. if(exists($param->{code}))
  492. {
  493. Log3 $name, 5, "PHILIPS_AUDIO ($name) - received HTTP code ".$param->{code}." for command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\"";
  494. }
  495. #Log3 $name, 5, "Error = $err";
  496. #Log3 $name, 5, "Data = $data";
  497. if($err ne "")
  498. {
  499. Log3 $name, 5, "PHILIPS_AUDIO ($name) - could not execute command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $err";
  500. if((not exists($hash->{helper}{AVAILABLE})) or (exists($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} == 1))
  501. {
  502. Log3 $name, 3, "PHILIPS_AUDIO ($name) - could not execute command on device $name. Please turn on your device in case of deactivated network standby or check for correct hostaddress.";
  503. readingsSingleUpdate($hash, "presence", "absent", 1);
  504. readingsSingleUpdate($hash, "state", "absent", 1);
  505. $hash->{STATE} = "absent";
  506. }
  507. $hash->{helper}{AVAILABLE} = 0;
  508. }
  509. elsif($data ne "")
  510. {
  511. Log3 $name, 5, "PHILIPS_AUDIO ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data";
  512. if (defined($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 0)
  513. {
  514. Log3 $name, 3, "PHILIPS_AUDIO ($name) - device $name reappeared";
  515. readingsSingleUpdate($hash, "presence", "present", 1);
  516. }
  517. $hash->{helper}{AVAILABLE} = 1;
  518. readingsBeginUpdate($hash);
  519. readingsBulkUpdate($hash, "power", "on");
  520. readingsBulkUpdate($hash, "state","on");
  521. $hash->{STATE} = "on";
  522. if($cmd eq "standbyButton")
  523. {
  524. if($data =~ /SUCCESS/)
  525. {
  526. #readingsBulkUpdate($hash, "power", "on");
  527. #readingsBulkUpdate($hash, "state","on");
  528. }
  529. }
  530. elsif($cmd eq "mute")
  531. {
  532. if($data =~ /SUCCESS/)
  533. {
  534. readingsBulkUpdate($hash, "mute", "on");
  535. }
  536. }
  537. elsif($cmd eq "unmute")
  538. {
  539. if($data =~ /SUCCESS/)
  540. {
  541. readingsBulkUpdate($hash, "mute", "off");
  542. }
  543. }
  544. elsif($cmd eq "removeFromFavourites")
  545. {
  546. # evtl. for future use
  547. }
  548. elsif($cmd eq "addToFavourites")
  549. {
  550. # evtl. for future use
  551. }
  552. elsif($cmd eq "inetRadioPreset")
  553. {
  554. # This command must be processed hierarchicaly through the navigation path
  555. if($hash->{helper}{cmdStep} == 1)
  556. {
  557. $hash->{helper}{cmdStep} = 2;
  558. # Internet radio
  559. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioPreset", $hash->{helper}{inetRadioPreset});
  560. }
  561. elsif($hash->{helper}{cmdStep} == 2)
  562. {
  563. $hash->{helper}{cmdStep} = 3;
  564. # Presets
  565. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$001\$0", "","inetRadioPreset", $hash->{helper}{inetRadioPreset});
  566. }
  567. elsif($hash->{helper}{cmdStep} == 3)
  568. {
  569. $hash->{helper}{cmdStep} = 4;
  570. # Preset select
  571. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$".sprintf("%03d", $hash->{helper}{inetRadioPreset})."\$1", "","inetRadioPreset", $hash->{helper}{inetRadioPreset});
  572. }
  573. }
  574. elsif($cmd eq "inetRadioPresetByName")
  575. {
  576. # This command must be processed hierarchicaly through the navigation path
  577. if($hash->{helper}{cmdStep} == 1)
  578. {
  579. $hash->{helper}{cmdStep} = 2;
  580. # Internet radio
  581. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioPresetByName", $hash->{helper}{inetRadioPresetNumber});
  582. }
  583. elsif($hash->{helper}{cmdStep} == 2)
  584. {
  585. $hash->{helper}{cmdStep} = 3;
  586. # Presets
  587. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$001\$0", "","inetRadioPresetByName", $hash->{helper}{inetRadioPresetNumber});
  588. }
  589. elsif($hash->{helper}{cmdStep} == 3)
  590. {
  591. $hash->{helper}{cmdStep} = 4;
  592. # Preset select
  593. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$". sprintf("%03d", $hash->{helper}{inetRadioPresetNumber}) . "\$1", "", "inetRadioPresetByName", $hash->{helper}{inetRadioPresetNumber});
  594. }
  595. }
  596. elsif($cmd eq "inetRadioFavorite")
  597. {
  598. # This command must be processed hierarchicaly through the navigation path
  599. if($hash->{helper}{cmdStep} == 1)
  600. {
  601. $hash->{helper}{cmdStep} = 2;
  602. # Internet radio favorite
  603. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioFavorite", $hash->{helper}{inetRadioFavorite});
  604. }
  605. elsif($hash->{helper}{cmdStep} == 2)
  606. {
  607. $hash->{helper}{cmdStep} = 3;
  608. # Favorite Presets
  609. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$002\$0", "","inetRadioFavorite", $hash->{helper}{inetRadioFavorite});
  610. }
  611. elsif($hash->{helper}{cmdStep} == 3)
  612. {
  613. $hash->{helper}{cmdStep} = 4;
  614. # Favorite Preset select
  615. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$".sprintf("%03d", $hash->{helper}{inetRadioFavorite})."\$1", "","inetRadioFavorite", $hash->{helper}{inetRadioFavorite});
  616. }
  617. }
  618. elsif($cmd eq "inetRadioFavoriteByName")
  619. {
  620. # This command must be processed hierarchicaly through the navigation path
  621. if($hash->{helper}{cmdStep} == 1)
  622. {
  623. $hash->{helper}{cmdStep} = 2;
  624. # Internet radio
  625. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioFavoriteByName", $hash->{helper}{inetRadioFavoriteNumber});
  626. }
  627. elsif($hash->{helper}{cmdStep} == 2)
  628. {
  629. $hash->{helper}{cmdStep} = 3;
  630. # Favorites
  631. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$002\$0", "","inetRadioFavoriteByName", $hash->{helper}{inetRadioFavoriteNumber});
  632. }
  633. elsif($hash->{helper}{cmdStep} == 3)
  634. {
  635. $hash->{helper}{cmdStep} = 4;
  636. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$". sprintf("%03d", $hash->{helper}{inetRadioFavoriteNumber}) . "\$1", "", "inetRadioFavoriteByName", $hash->{helper}{inetRadioFavoriteNumber});
  637. }
  638. }
  639. elsif($cmd eq "play_pause")
  640. {
  641. if($data =~ /SUCCESS/)
  642. {
  643. #readingsBulkUpdate($hash, "play_pause", "on");
  644. #readingsBulkUpdate($hash, "stop", "off");
  645. }
  646. }
  647. elsif($cmd eq "stop")
  648. {
  649. if($data =~ /STOP/)
  650. {
  651. readingsBulkUpdate($hash, "playing", "no");
  652. }
  653. }
  654. elsif($cmd eq "volume" or $cmd eq "volumeStraight")
  655. {
  656. if($data =~ /SUCCESS/)
  657. {
  658. readingsBulkUpdate($hash, "volumeStraight", $hash->{helper}{targetVolume});
  659. my $targetVolume = $hash->{helper}{targetVolume};
  660. readingsBulkUpdate($hash, "volume", PHILIPS_AUDIO_volume_abs2rel($hash, $targetVolume));
  661. }
  662. }
  663. elsif($cmd eq "nowplay")
  664. {
  665. if($data =~ /'title':'\\'(.+)\\''/)
  666. {
  667. readingsBulkUpdate($hash, "title", PHILIPS_AUDIO_STREAMIUMNP2txt($1));
  668. }
  669. else
  670. {
  671. readingsBulkUpdate($hash, "title", "");
  672. }
  673. if($data =~ /'title':'(.+)'/)
  674. {
  675. readingsBulkUpdate($hash, "title", PHILIPS_AUDIO_STREAMIUMNP2txt($1));
  676. }
  677. else
  678. {
  679. readingsBulkUpdate($hash, "title", "");
  680. }
  681. if($data =~ /'subTitle':'(.+)'/)
  682. {
  683. readingsBulkUpdate($hash, "subtitle", $1);
  684. }
  685. else
  686. {
  687. readingsBulkUpdate($hash, "subtitle", "");
  688. }
  689. if($data =~ /'albumArt':'(.+)'/)
  690. {
  691. readingsBulkUpdate($hash, "albumArt", $1);
  692. }
  693. else
  694. {
  695. readingsBulkUpdate($hash, "albumArt", "");
  696. }
  697. if($data =~ /'volume':(.+),/)
  698. {
  699. readingsBulkUpdate($hash, "volumeStraight", $1);
  700. readingsBulkUpdate($hash, "volume", PHILIPS_AUDIO_volume_abs2rel($hash, $1));
  701. }
  702. else
  703. {
  704. readingsBulkUpdate($hash, "volumeStraight", "0");
  705. readingsBulkUpdate($hash, "volume", "0");
  706. }
  707. if($data =~ /'elapsetime':(.+),/)
  708. {
  709. readingsBulkUpdate($hash, "elapseTime", strftime("\%H:\%M:\%S", gmtime($1)));
  710. }
  711. else
  712. {
  713. readingsBulkUpdate($hash, "elapseTime", "");
  714. }
  715. if($data =~ /'totaltime':(.+),/)
  716. {
  717. # Playing radio delivers that total time
  718. if($1 eq "65535")
  719. {
  720. readingsBulkUpdate($hash, "totalTime", "infinite");
  721. }
  722. else
  723. {
  724. readingsBulkUpdate($hash, "totalTime", strftime("\%H:\%M:\%S", gmtime($1)));
  725. }
  726. }
  727. else
  728. {
  729. readingsBulkUpdate($hash, "totalTime", "");
  730. }
  731. if($data =~ /'muteStatus':(.+),/)
  732. {
  733. if($1 == 1)
  734. {
  735. readingsBulkUpdate($hash, "mute", "on");
  736. }
  737. else
  738. {
  739. readingsBulkUpdate($hash, "mute", "off");
  740. }
  741. }
  742. # typo in the (buggy) Streamium firmware...
  743. if($data =~ /'playStaus':(.+),/)
  744. {
  745. if($1 == 1)
  746. {
  747. readingsBulkUpdate($hash, "playing", "yes");
  748. }
  749. else
  750. {
  751. readingsBulkUpdate($hash, "playing", "no");
  752. }
  753. }
  754. else
  755. {
  756. readingsBulkUpdate($hash, "playing", "no");
  757. }
  758. }
  759. # Eventual future UPNP implementation. Requires IO::Socket::Multicast non-standard module.
  760. elsif ($cmd eq "getModel")
  761. {
  762. if($data =~ /<friendlyName>(.+)<\/friendlyName>/)
  763. {
  764. $hash->{FRIENDLY_NAME} = $1;
  765. }
  766. if($data =~ /<UDN>(.+)<\/UDN>/)
  767. {
  768. $hash->{UNIQUE_DEVICE_NAME} = uc($1);
  769. }
  770. my $modelName = "";
  771. my $modelNumber = "";
  772. if($data =~ /<modelName>(.+)<\/modelName>/)
  773. {
  774. $modelName = $1;
  775. }
  776. if($data =~ /<modelNumber>(.+)<\/modelNumber>/)
  777. {
  778. $modelNumber = $1;
  779. }
  780. # Combine both strings
  781. if(($modelName ne "") and ($modelNumber ne ""))
  782. {
  783. $hash->{MODEL} = $modelName . $modelNumber;
  784. }
  785. if($data =~ /<serialNumber>(.+)<\/serialNumber>/)
  786. {
  787. $hash->{SERIAL_NUMBER} = uc($1);
  788. }
  789. if($data =~ /<modelDescription>(.+)<\/modelDescription>/)
  790. {
  791. $hash->{MODEL_DESCRIPTION} = $1;
  792. }
  793. # Replace \n, \r, \t from the string for XML parsing
  794. # replace \n by ""
  795. $data =~ s/\n//g;
  796. # replace \t by ""
  797. $data =~ s/\t//g;
  798. # replace \r by ""
  799. $data =~ s/\r//g;
  800. if($data =~ /<iconList>(.+?)<\/iconList>/)
  801. {
  802. my $address = $hash->{IP_ADDRESS};
  803. my $i = 1;
  804. while ($data =~ /<url>(.+?)<\/url>/g)
  805. {
  806. $hash->{"NP_ICON_$i"} = "http://".$address.":".$arg."/".$1;
  807. $i++;
  808. }
  809. }
  810. }
  811. elsif ($cmd eq "getInetRadioPresets")
  812. {
  813. # This command must be processed hierarchicaly through the navigation path
  814. if($hash->{helper}{cmdStep} == 1)
  815. {
  816. $hash->{helper}{cmdStep} = 2;
  817. # Internet radio
  818. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "","getInetRadioPresets", "noArg");
  819. }
  820. elsif($hash->{helper}{cmdStep} == 2)
  821. {
  822. $hash->{helper}{cmdStep} = 3;
  823. # Presets
  824. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$001\$0", "","getInetRadioPresets", "noArg");
  825. }
  826. elsif($hash->{helper}{cmdStep} == 3)
  827. {
  828. my $listedItems; # Visible Items in the display. Max 8
  829. my $nextreqURL;
  830. my $i;
  831. my $presetID = 0;
  832. my $presetName;
  833. # Parse first 8 Presets
  834. if($data =~ /<title>Error<\/title>/)
  835. {
  836. # In case on presets defined the player returns an Error
  837. # Do nothing
  838. $hash->{helper}{TOTALINETRADIOPRESETS} = 0;
  839. readingsBulkUpdate($hash, "totalInetRadioPresets", "0");
  840. }
  841. else
  842. {
  843. if ($data =~ /'nextrequrl':'(.+?)',/)
  844. {
  845. $nextreqURL = $1;
  846. #Log3 $name, 5, "NextreqURL: $nextreqURL";
  847. }
  848. if ($data =~ /'totalListCount':(.+),/)
  849. {
  850. $hash->{helper}{TOTALINETRADIOPRESETS} = $1;
  851. readingsBulkUpdate($hash, "totalInetRadioPresets", $1);
  852. #Log3 $name, 5, "ListedItems: $listedItems";
  853. }
  854. #if ($data =~ /'totalitems':(.+),/)
  855. #{
  856. # $listedItems = $1;
  857. #}
  858. $data =~ s/\R//g; # Remove new lines
  859. for(;;)
  860. {
  861. if($data =~ /{'title':'(.+?)',/g)
  862. {
  863. $presetName = $1;
  864. #Log3 $name, 5, "PresetName: $presetName";
  865. if($data =~ /'id':(.+?),/g)
  866. {
  867. $presetID = $1;
  868. #Log3 $name, 5, "PresetIDLoop: $presetID";
  869. }
  870. if ($presetID ne "" and $presetName ne "")
  871. {
  872. readingsBulkUpdate($hash, sprintf("inetRadioPreset%02d", $presetID), $presetName);
  873. }
  874. }
  875. else
  876. {
  877. last;
  878. }
  879. }
  880. #Log3 $name, 5, "PresetIDNachLoop: $presetID";
  881. if($presetID < ($hash->{helper}{TOTALINETRADIOPRESETS})) # Maximum listed items = 8. Get the next items by sending the nextreqURL
  882. {
  883. PHILIPS_AUDIO_SendCommand($hash, $nextreqURL, "","getInetRadioPresets", "noArg");
  884. }
  885. else
  886. {
  887. $hash->{helper}{cmdStep} = 4;
  888. if (exists($hash->{helper}{PRESETS}))
  889. {
  890. $hash->{helper}{PRESETS} = ""; # Reset the pull-down menue
  891. }
  892. PHILIPS_AUDIO_updatePresets($hash);
  893. #my $debug = $hash->{helper}{PRESETS};
  894. #Log3 $name, 5, "Presets: $debug";
  895. }
  896. }
  897. }
  898. }
  899. elsif ($cmd eq "getInetRadioFavorites")
  900. {
  901. # This command must be processed hierarchicaly through the navigation path
  902. if($hash->{helper}{cmdStep} == 1)
  903. {
  904. $hash->{helper}{cmdStep} = 2;
  905. # Internet radio
  906. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "","getInetRadioFavorites", "noArg");
  907. }
  908. elsif($hash->{helper}{cmdStep} == 2)
  909. {
  910. $hash->{helper}{cmdStep} = 3;
  911. # Favorites
  912. PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$002\$0", "","getInetRadioFavorites", "noArg");
  913. }
  914. elsif($hash->{helper}{cmdStep} == 3)
  915. {
  916. if($data =~ /<title>Error<\/title>/)
  917. {
  918. # In case on presets defined the player returns an Error
  919. # Do nothing
  920. $hash->{helper}{TOTALINETRADIOFAVORITES} = 0;
  921. readingsBulkUpdate($hash, "totalInetRadioFavorites", "0");
  922. }
  923. else
  924. {
  925. my $listedItems; # Visible Items in the display. Max 8
  926. my $nextreqURL;
  927. my $i;
  928. my $favoriteID = 0;
  929. my $favoriteName;
  930. # Parse first 8 Presets
  931. if ($data =~ /'nextrequrl':'(.+?)',/)
  932. {
  933. $nextreqURL = $1;
  934. #Log3 $name, 5, "NextreqURL: $nextreqURL";
  935. }
  936. if ($data =~ /'totalListCount':(.+),/)
  937. {
  938. $hash->{helper}{TOTALINETRADIOFAVORITES} = $1;
  939. readingsBulkUpdate($hash, "totalInetRadioFavorites", $1);
  940. #Log3 $name, 5, "ListedItems: $listedItems";
  941. }
  942. #if ($data =~ /'totalitems':(.+),/)
  943. #{
  944. # $listedItems = $1;
  945. #}
  946. $data =~ s/\R//g; # Remove new lines
  947. for(;;)
  948. {
  949. if($data =~ /{'title':'(.+?)',/g)
  950. {
  951. $favoriteName = $1;
  952. #Log3 $name, 5, "FavoriteName: $favoriteName";
  953. if($data =~ /'id':(.+?),/g)
  954. {
  955. $favoriteID = $1;
  956. #Log3 $name, 5, "FavoriteIDLoop: $favoriteID";
  957. }
  958. if ($favoriteID ne "" and $favoriteName ne "")
  959. {
  960. readingsBulkUpdate($hash, sprintf("inetRadioFavorite%02d", $favoriteID), $favoriteName);
  961. }
  962. }
  963. else
  964. {
  965. last;
  966. }
  967. }
  968. #Log3 $name, 5, "FavoriteIDNachLoop: $favoriteID";
  969. if($favoriteID < ($hash->{helper}{TOTALINETRADIOFAVORITES})) # Maximum listed items = 8. Get the next items by sending the nextreqURL
  970. {
  971. PHILIPS_AUDIO_SendCommand($hash, $nextreqURL, "","getInetRadioFavorites", "noArg");
  972. }
  973. else
  974. {
  975. $hash->{helper}{cmdStep} = 4;
  976. if (exists($hash->{helper}{FAVORITES}))
  977. {
  978. $hash->{helper}{FAVORITES} = ""; # Reset the pull-down menue
  979. }
  980. PHILIPS_AUDIO_updateFavorites($hash);
  981. #my $debug = $hash->{helper}{FAVORITES};
  982. #Log3 $name, 5, "Favorites: $debug";
  983. }
  984. }
  985. }
  986. }
  987. readingsEndUpdate($hash, 1);
  988. return;
  989. }
  990. }
  991. #############################
  992. # converts straight volume in percentage volume (volumestraightmin .. volumestraightmax => 0 .. 100%)
  993. sub PHILIPS_AUDIO_volume_rel2abs
  994. {
  995. my ($hash, $percentage) = @_;
  996. return int(($percentage * 64 / 100 ));
  997. }
  998. #############################
  999. # converts relative volume to "straight" volume (0 .. 100% => volumestraightmin .. volumestraightmax)
  1000. sub PHILIPS_AUDIO_volume_abs2rel
  1001. {
  1002. my ($hash, $absolute) = @_;
  1003. return int(int($absolute * 100) / int(64));
  1004. }
  1005. #############################
  1006. # Restarts the internal status request timer according to the given interval or current receiver state
  1007. sub PHILIPS_AUDIO_ResetTimer
  1008. {
  1009. my ($hash, $interval) = @_;
  1010. RemoveInternalTimer($hash);
  1011. if($hash->{helper}{DISABLED} == 0)
  1012. {
  1013. if(defined($interval))
  1014. {
  1015. InternalTimer(gettimeofday()+$interval, "PHILIPS_AUDIO_GetStatus", $hash, 0);
  1016. }
  1017. 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"))
  1018. {
  1019. InternalTimer(gettimeofday() + $hash->{helper}{ON_INTERVAL}, "PHILIPS_AUDIO_GetStatus", $hash, 0);
  1020. }
  1021. else
  1022. {
  1023. InternalTimer(gettimeofday() + $hash->{helper}{OFF_INTERVAL}, "PHILIPS_AUDIO_GetStatus", $hash, 0);
  1024. }
  1025. }
  1026. return;
  1027. }
  1028. #############################
  1029. # convert all HTML entities into UTF-8 equivalent
  1030. sub PHILIPS_AUDIO_STREAMIUMNP2txt
  1031. {
  1032. my ($string) = @_;
  1033. $string =~ s/\\'//g;
  1034. return $string;
  1035. }
  1036. #############################
  1037. # Updates the pull-down menue
  1038. sub PHILIPS_AUDIO_updatePresets
  1039. {
  1040. my ($hash) = @_;
  1041. my $name = $hash->{NAME};
  1042. if((not defined($hash->{helper}{PRESETS}) or length($hash->{helper}{PRESETS}) == 0))
  1043. {
  1044. my $presetName;
  1045. for(my $i = 1; $i < (AttrVal($name, "max-device-presets", "24") + 1); $i++)
  1046. {
  1047. if(exists($hash->{READINGS}{sprintf("inetRadioPreset%02d", $i)}))
  1048. {
  1049. if($i != 1)
  1050. {
  1051. $presetName = ",";
  1052. }
  1053. $presetName .= sprintf("%02d", $i) . ":";
  1054. $presetName .= $hash->{READINGS}{sprintf("inetRadioPreset%02d", $i)}{VAL};
  1055. $presetName =~ s/ /_/g; # Replace blank by underscore
  1056. $hash->{helper}{PRESETS} .= $presetName;
  1057. }
  1058. else
  1059. {
  1060. last;
  1061. }
  1062. }
  1063. }
  1064. else
  1065. {
  1066. $hash->{helper}{PRESETS} = "";
  1067. }
  1068. return;
  1069. }
  1070. #############################
  1071. # Updates the pull-down menue
  1072. sub PHILIPS_AUDIO_updateFavorites
  1073. {
  1074. my ($hash) = @_;
  1075. my $name = $hash->{NAME};
  1076. if((not defined($hash->{helper}{FAVORITES}) or length($hash->{helper}{FAVORITES}) == 0))
  1077. {
  1078. my $favoriteName;
  1079. for(my $i = 1; $i < (AttrVal($name, "max-device-favorites", "24") + 1); $i++)
  1080. {
  1081. if(exists($hash->{READINGS}{sprintf("inetRadioFavorite%02d", $i)}))
  1082. {
  1083. if($i != 1)
  1084. {
  1085. $favoriteName = ",";
  1086. }
  1087. $favoriteName .= sprintf("%02d", $i) . ":";
  1088. $favoriteName .= $hash->{READINGS}{sprintf("inetRadioFavorite%02d" , $i)}{VAL};
  1089. $favoriteName =~ s/ /_/g; # Replace blank by underscore
  1090. $hash->{helper}{FAVORITES} .= $favoriteName;
  1091. }
  1092. else
  1093. {
  1094. last;
  1095. }
  1096. }
  1097. }
  1098. }
  1099. 1;
  1100. =pod
  1101. =begin html
  1102. <a name="PHILIPS_AUDIO"></a>
  1103. <h3>PHILIPS_AUDIO</h3>
  1104. <ul>
  1105. <a name="PHILIPS_AUDIOdefine"></a>
  1106. <b>Define</b>
  1107. <br><br>
  1108. <ul>
  1109. <code>
  1110. define &lt;name&gt; PHILIPS_AUDIO &lt;device model&gt; &lt;ip-address&gt; [&lt;status_interval&gt;]<br><br>
  1111. define &lt;name&gt; PHILIPS_AUDIO &lt;device model&gt; [&lt;off_status_interval&gt;] [&lt;on_status_interval&gt;]
  1112. </code>
  1113. <br><br>
  1114. This module controls a Philips Audio Player e.g. MCi, Streamium or Fidelio and (potentially) any other device including a navigation server.<br>
  1115. To check, open the following URL in the browser: http://[ip # of your device]:8889/index
  1116. <br><br>
  1117. (So far tested on: AW9000, NP3500, NP3700 and NP3900)
  1118. <br><br>
  1119. Currently implemented features:
  1120. <br><br>
  1121. <ul>
  1122. <li>Power on/off</li>
  1123. <li>Internet Radio Preset Selection</li>
  1124. <li>Input selection</li>
  1125. <li>Volume +/-</li>
  1126. <li>Mute on/off</li>
  1127. <li>...</li>
  1128. </ul>
  1129. <br>
  1130. Defining a PHILIPS_AUDIO device will schedule an internal task (interval can be set
  1131. with optional parameters &lt;off_status_interval&gt; and &lt;on_status_interval&gt; in seconds.<br>
  1132. &lt;off_status_interval&gt; is a parameter used in case the device is powered off or not available.<br>
  1133. &lt;on_status_interval&gt; is a parameter used in case the device is powered on.<br>
  1134. If both parameters are unset, a default value 30 (seconds) for both is used.<br>
  1135. If &lt;off_status_interval&gt; is set only the same value is used for both parameters.<br>
  1136. Due to a relatively low-performance of the devices the minimum interval is set to 3 seconds.
  1137. <br>
  1138. The internal task periodically reads the status of the Network Player (power state, volume and mute status etc.) and triggers notify/filelog commands.
  1139. <br><br>
  1140. Example:<br><br>
  1141. <ul><br>
  1142. Add the following code into the <b>fhem.cfg</b> configuration file and restart fhem:<br><br>
  1143. <code>
  1144. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15<br>
  1145. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
  1146. # With custom status interval of 60 seconds<br>
  1147. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60</b><br>
  1148. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
  1149. # With custom "off"-interval of 60 seconds and "on"-interval of 10 seconds<br>
  1150. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60 10</b><br>
  1151. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
  1152. </code>
  1153. </ul>
  1154. </ul>
  1155. <br><br>
  1156. <a name="PHILIPS_AUDIOset"></a>
  1157. <b>Set</b>
  1158. <ul>
  1159. <code>
  1160. set &lt;name&gt; &lt;command&gt; [&lt;parameter&gt;]
  1161. </code><br><br>
  1162. Currently, the following commands are defined.<br>
  1163. <i>Note: Commands and parameters are case sensitive.</i><br>
  1164. <ul><br><br>
  1165. <u>Available commands:</u><br><br>
  1166. <li><b>aux</b>&nbsp;&nbsp;-&nbsp;&nbsp; Switches to the AUX input (MP3 Link or similar).</li>
  1167. <li><b>getInetRadioFavorites</b> &nbsp;&nbsp;-&nbsp;&nbsp; Reads the favorites. (May take some seconds...).</li>
  1168. <li><b>getInetRadioPresets</b> &nbsp;&nbsp;-&nbsp;&nbsp; Reads the presets. (May take some seconds...).</li>
  1169. <li><b>inetRadioFavorite</b> [1..24] &nbsp;&nbsp;-&nbsp;&nbsp; Selects an internet radio favorite (May take some seconds...).</li>
  1170. <li><b>inetRadioPreset</b> [1..24] &nbsp;&nbsp;-&nbsp;&nbsp; Selects an internet radio preset (May take some seconds...).</li>
  1171. <li><b>inetRadioFavoriteByName</b> [name] &nbsp;&nbsp;-&nbsp;&nbsp; Selects an internet radio favorite by name. (getInetRadioFavorites must be run previously for the command to become available.) (May take some seconds...).</li>
  1172. <li><b>inetRadioPresetByName</b> [name] &nbsp;&nbsp;-&nbsp;&nbsp; Selects an internet radio preset by name. (getInetRadioPresets must be run previously for the command to become available.) (May take some seconds...).</li>
  1173. <li><b>mute</b>&nbsp;&nbsp;-&nbsp;&nbsp; Mutes the device.</li>
  1174. <li><b>unmute</b>&nbsp;&nbsp;-&nbsp;&nbsp; Unmutes the device.</li>
  1175. <li><b>next</b> &nbsp;&nbsp;-&nbsp;&nbsp; Selects the next song, preset etc.</li>
  1176. <li><b>play_pause</b> &nbsp;&nbsp;-&nbsp;&nbsp; Toggles PLAY/PAUSE.</li>
  1177. <li><b>previous</b> &nbsp;&nbsp;-&nbsp;&nbsp; Selects the previous song, preset etc.</li>
  1178. <li><b>repeat [single|all|off]</b> &nbsp;&nbsp;-&nbsp;&nbsp; Sets the repeat mode.</li>
  1179. <li><b>shuffle [on|off]</b> &nbsp;&nbsp;-&nbsp;&nbsp; Sets the shuffle mode.</li>
  1180. <li><b>standbyButton</b> &nbsp;&nbsp;-&nbsp;&nbsp; Toggles between standby and power on.</li>
  1181. <li><b>statusRequest</b> &nbsp;&nbsp;-&nbsp;&nbsp; Updates the readings.</li>
  1182. <li><b>stop</b> &nbsp;&nbsp;-&nbsp;&nbsp; Stops the player.</li>
  1183. <li><b>volume</b> &nbsp;&nbsp;-&nbsp;&nbsp; Sets the relative volume 0...100%.</li>
  1184. <li><b>volumeStraight</b> &nbsp;&nbsp;-&nbsp;&nbsp; Sets the absolute volume 0...64.</li>
  1185. </ul><br><br>
  1186. A typical example is powering the device remotely and tuning the favourite radio station:<br><br>
  1187. Add the following code into the <b>fhem.cfg</b> configuration file:<br><br><br>
  1188. <ul>
  1189. <code>
  1190. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 30 5<br>
  1191. attr PHAUDIO_player webCmd volume:mute:inetRadioPreset
  1192. </code>
  1193. </ul><br><br>
  1194. Add the following code into the <b>99_MyUtils.pm</b> file:<br><br>
  1195. <ul>
  1196. <code>
  1197. sub startMyFavouriteRadioStation()<br>
  1198. {<br>
  1199. &nbsp;&nbsp;fhem "set PHAUDIO_player inetRadioPreset 1";<br>
  1200. &nbsp;&nbsp;sleep 1;<br>
  1201. &nbsp;&nbsp;fhem "set PHAUDIO_player volume 30";<br>
  1202. }
  1203. </code>
  1204. </ul>
  1205. <br><br>
  1206. It's a good idea to insert a 'sleep' instruction between each fhem commands due to internal processing time of the player. Be patient when executing the commands...<br><br>
  1207. Now the function can be called by typing the following line in the FHEM command line or by the notify-definitions:<br><br>
  1208. <ul>
  1209. <code>
  1210. {startMyFavouriteRadioStation()}<br><br>
  1211. </code>
  1212. </ul>
  1213. </ul>
  1214. <a name="PHILIPS_AUDIOget"></a>
  1215. <b>Get</b>
  1216. <ul>
  1217. <code>
  1218. get &lt;name&gt; &lt;reading&gt;
  1219. </code>
  1220. <br><br>
  1221. Currently, the 'get' command returns reading values only. For a specific list of possible values, see section <b>"Generated Readings"</b>.<br><br>
  1222. </ul>
  1223. <a name="PHILIPS_AUDIOattr"></a>
  1224. <b>Attributes</b><br><br>
  1225. <ul>
  1226. <ul>
  1227. <li><b><a href="#do_not_notify">do_not_notify</a></b></li>
  1228. <li><b><a href="#readingFnAttributes">readingFnAttributes</a></b></li>
  1229. <li><b><a name="request-timeout">request-timeout</a></b></li>
  1230. <br>Optional attribute change the response timeout in seconds for all queries to the receiver.
  1231. <br>Possible values: 1...5 seconds. Default value is 4 seconds.<br><br>
  1232. <li><b><a name="max-device-presets">max-device-presets</a></b></li>
  1233. <br>Optional attribute defining maximum number of available preset slots in device's memory. Default value 24.<br><br>
  1234. <li><b><a name="max-device-favorites">max-device-favorites</a></b></li>
  1235. <br>Optional attribute defining maximum number of favorite slots in device's memory. Default value 24.<br><br>
  1236. <li><b><a name="disable">disable</a></b></li>
  1237. <br>Optional attribute to disable the internal cyclic status update of the receiver. Manual status updates via statusRequest command is still possible.
  1238. <br>Possible values: 0 &rarr; perform cyclic status update, 1 &rarr; don't perform cyclic status updates.<br><br><br>
  1239. </ul>
  1240. </ul>
  1241. <b>Readings</b><br><br>
  1242. <ul>
  1243. <ul>
  1244. <li><b>albumArt</b> - Link to current album art or radio station.</li>
  1245. <li><b>elapseTime</b> - Elapse time of the played audio.</li>
  1246. <li><b>inetRadioFavorite[value]</b> - Name of the stored favorite.</li>
  1247. <li><b>inetRadioPreset[value]</b> - Name of the stored preset.</li>
  1248. <li><b>mute</b> - Reports the mute status (on|off).</li>
  1249. <li><b>playing</b> - Reports the current playier status (yes|no).</li>
  1250. <li><b>power</b> - Reports the current power status (on|absent).</li>
  1251. <li><b>presence</b> - Reports the current presence (present|absent).</li>
  1252. <li><b>state</b> - Reports the current state status (on|absent).</li>
  1253. <li><b>subtitle</b> - Reports the current subtitle of played audio.</li>
  1254. <li><b>totalInetRadioFavorites</b> - Number of stored favorites.</li>
  1255. <li><b>totalInetRadioPresets</b> - Number of stored presets.</li>
  1256. <li><b>title</b> - Reports the current title of played audio.</li>
  1257. <li><b>totalTime</b> - Reports the total time of the played audio.</li>
  1258. <li><b>volume</b> - Reports current relative volume (0..100).</li>
  1259. <li><b>volumeStraight</b> - Reports current absolute volume (0..64).</li>
  1260. </ul>
  1261. </ul><br>
  1262. <b>Implementer's note</b><br><br>
  1263. <ul>
  1264. Trivial: In order to use that module the network player must be connected to the Ethernet.<br>
  1265. There's no possibility to read back the current power on/standby status from the device. This fuctionality is missing in the server application.<br>
  1266. </ul><br>
  1267. </ul>
  1268. =end html
  1269. =begin html_DE
  1270. <a name="PHILIPS_AUDIO"></a>
  1271. <h3>PHILIPS_AUDIO</h3>
  1272. <ul>
  1273. <a name="PHILIPS_AUDIOdefine"></a>
  1274. <b>Define</b><br><br>
  1275. <ul>
  1276. <code>
  1277. define &lt;name&gt; PHILIPS_AUDIO &lt;device model&gt; &lt;ip-address&gt; [&lt;status_interval&gt;]<br><br>
  1278. define &lt;name&gt; PHILIPS_AUDIO &lt;device model&gt; [&lt;off_status_interval&gt;] [&lt;on_status_interval&gt;]
  1279. </code>
  1280. <br><br>
  1281. Mit Hilfe dieses Moduls lassen sich Philips Audio Netzwerk Player wie z.B. MCi, Streamium oder Fidelio via Ethernet steuern.<br>
  1282. Theoretisch sollten alle Ger&auml;te, die &uuml;ber einer implementierten HTTP Server am Port 8889 haben (http://[ip Nummer des Ger&auml;tes]:8889/index), bedient werden k&ouml;nnen.<br>
  1283. <br>
  1284. <br>
  1285. (Getestet mit: AW9000, NP3500, NP3700 und NP3900)
  1286. <br>
  1287. <br>
  1288. Die aktuelle Implementierung erm&ouml;glicht u.a. den folgenden Funktionsumfang:<br><br>
  1289. <ul>
  1290. <li>Power on/off</li>
  1291. <li>Internet Radio Preset Auswahl</li>
  1292. <li>Input Auswahl</li>
  1293. <li>Volume +/-</li>
  1294. <li>Mute on/off</li>
  1295. <li>...</li>
  1296. </ul>
  1297. <br>
  1298. Eine PHILIPS_AUDIO Definition initiiert einen internen Task, der von FHEM zyklisch abgearbeitet wird.<br>
  1299. 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>
  1300. &lt;off_status_interval&gt; steht f&uuml;r das Intervall, wenn das Ger&auml;t ausgeschaltet/abwesend ist.<br>
  1301. &lt;on_status_interval&gt; steht f&uuml;r das Intervall, wenn das Ger&auml;t eingeschaltet/verf&uuml;gbar ist.<br>
  1302. Wenn keine Parameter angegeben wurden, wird ein Default-Wert von 30 Sekunden f&uuml;r beide gesetzt.<br>
  1303. Wenn nur &lt;off_status_interval&gt; gesetzt wird, gilt dieser Wert f&uuml;r beide Zust&auml;nde (eingeschaltet/ausgeschaltet).<br>
  1304. Der Task liest zyklisch grundlegende Parameter vom Player und triggert notify/filelog Befehle.<br>
  1305. Aufgrund der recht schwachen Rechenleistung der Player wurde das minimale Intervall auf 3 Sekunden beschr&auml;nkt.<br><br>
  1306. Beispiel:<br><br>
  1307. <ul><br>
  1308. Definition in der <b>fhem.cfg</b> Konfigurationsdatei:<br><br>
  1309. <code>
  1310. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15<br>
  1311. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
  1312. # 60 Sekunden Intervall<br>
  1313. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60</b><br>
  1314. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
  1315. # 60 Sekunden Intervall f&uuml;r "off" und 10 Sekunden f&uuml;r "on"<br>
  1316. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60 10</b><br>
  1317. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset
  1318. </code>
  1319. </ul>
  1320. </ul><br><br>
  1321. <a name="PHILIPS_AUDIOset"></a>
  1322. <b>Set</b>
  1323. <ul>
  1324. <code>
  1325. set &lt;name&gt; &lt;command&gt; [&lt;parameter&gt;]
  1326. </code>
  1327. <br><br>
  1328. Aktuell sind folgende Befehle implementiert:<br>
  1329. <i>Bemerkung: Bitte bei den Befehlen und Parametern die Gro&szlig;- und Kleinschreibung beachten.</i><br>
  1330. <ul><br><br>
  1331. <li><b>aux</b>&nbsp;&nbsp;-&nbsp;&nbsp; Schaltet auf den AUX Eingang um (MP3 Link oder &auml;hnlich.).</li>
  1332. <li><b>getInetRadioFavorites</b> &nbsp;&nbsp;-&nbsp;&nbsp; Liest die Favoriten. (Kann einige Sekunden dauern...).</li>
  1333. <li><b>getInetRadioPresets</b> &nbsp;&nbsp;-&nbsp;&nbsp; Liest die Presets. (Kann einige Sekunden dauern...).</li>
  1334. <li><b>inetRadioFavorite</b> [1..24] &nbsp;&nbsp;-&nbsp;&nbsp; W&auml;hlt den Internetradio-Lieblingssender (Das Umschalten kann einige Sekunden dauern...).</li>
  1335. <li><b>inetRadioPreset</b> [1..24] &nbsp;&nbsp;-&nbsp;&nbsp; W&auml;hlt die Internetradio Voreinstellung (Das Umschalten kann einige Sekunden dauern...).</li>
  1336. <li><b>inetRadioFavoriteByName</b> [name] &nbsp;&nbsp;-&nbsp;&nbsp; W&auml;hlt einen Internetradio Favoriten mit Hilfe seines Names. (getInetRadioFavorites muss zuvor ausgef&uuml;hrt werden, damit der Befehl verf&uuml;gbar wird. (Kann einige Sekunden dauern...).</li>
  1337. <li><b>inetRadioPresetByName</b> [name] &nbsp;&nbsp;-&nbsp;&nbsp; W&auml;hlt eine Internetradio Voreinstellung mit Hilfe ihres Names. (getInetRadioPresets muss zuvor ausgef&uuml;hrt werden, damit der Befehl verf&uuml;gbar wird. (Kann einige Sekunden dauern...).</li>
  1338. <li><b>mute</b>&nbsp;&nbsp;-&nbsp;&nbsp; Stummschaltung des Players.</li>
  1339. <li><b>unmute</b>&nbsp;&nbsp;-&nbsp;&nbsp; Deaktivierung der Stummschaltung.</li>
  1340. <li><b>next</b> &nbsp;&nbsp;-&nbsp;&nbsp; W&auml;hlt den n&auml;chten Titel, Voreinstellung etc.</li>
  1341. <li><b>play_pause</b> &nbsp;&nbsp;-&nbsp;&nbsp; Schaltet um zwischen PLAY um PAUSE.</li>
  1342. <li><b>previous</b> &nbsp;&nbsp;-&nbsp;&nbsp; W&auml;hlt den vorherigen Titel, Voreinstellung etc.</li>
  1343. <li><b>repeat [single|all|off]</b> &nbsp;&nbsp;-&nbsp;&nbsp; Bestimmt den Wiederholungsmodus.</li>
  1344. <li><b>shuffle [on|off]</b> &nbsp;&nbsp;-&nbsp;&nbsp; Bestimmt den Zufallswiedergabemodus.</li>
  1345. <li><b>standbyButton</b> &nbsp;&nbsp;-&nbsp;&nbsp; Schaltet um zwischen Standby und Power on.</li>
  1346. <li><b>statusRequest</b> &nbsp;&nbsp;-&nbsp;&nbsp; Readings Update.</li>
  1347. <li><b>stop</b> &nbsp;&nbsp;-&nbsp;&nbsp; Stoppt den Player.</li>
  1348. <li><b>volume</b> &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die relative Lautst&auml;rke 0...100%.</li>
  1349. <li><b>volumeStraight</b> &nbsp;&nbsp;-&nbsp;&nbsp; Setzt die absolute Lautst&auml;rke 0...64.</li>
  1350. </ul><br><br>
  1351. Ein typisches Beispiel ist das Einschalten des Ger&auml;tes und das Umschalten auf den Lieblingsradiosender:<br><br>
  1352. Beispieldefinition in der <b>fhem.cfg</b> Konfigurationsdatei:<br><br><br>
  1353. <ul>
  1354. <code>
  1355. define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 30 5<br>
  1356. attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset
  1357. </code>
  1358. </ul><br><br>
  1359. Folgender Code kann anschlie&szlig;end in die Datei <b>99_MyUtils.pm</b> eingebunden werden:<br><br>
  1360. <ul>
  1361. <code>
  1362. sub startMyFavouriteRadioStation()<br>
  1363. {<br>
  1364. &nbsp;&nbsp;fhem "set PHAUDIO_player inetRadioPreset 1";<br>
  1365. &nbsp;&nbsp;sleep 1;<br>
  1366. &nbsp;&nbsp;fhem "set PHAUDIO_player volume 30";<br>}
  1367. </code>
  1368. </ul><br><br>
  1369. <i>Bemerkung: Aufgrund der relativ langsamen Befehlsverarbeitung im Player im Vergleich zur asynchronen Ethernet-Kommunikation, kann es vorkommen, dass veraltete Statusinformationen zur&uuml;ckgesendet werden.<br>
  1370. Aus diesem Grund wird empfohlen, w&auml;hrend der Automatisierung zwischen den 'set' und 'get' Befehlen ein Delay einzubauen.</i><br><br>
  1371. Die Funktion kann jetzt in der FHEM Befehlszeile eingegeben oder in die Notify-Definitionen eingebunden werden.<br><br>
  1372. <ul>
  1373. <code>
  1374. {startMyFavouriteRadioStation()}<br><br>
  1375. </code>
  1376. </ul>
  1377. </ul>
  1378. <a name="PHILIPS_AUDIOget"></a>
  1379. <b>Get</b>
  1380. <code>
  1381. get &lt;name&gt; &lt;reading&gt;
  1382. </code><br><br>
  1383. Aktuell liefert der Befehl 'get' ausschlie&szlig;lich Reading-Werte (s. Abschnitt <b>"Readings"</b>).<br><br>
  1384. </ul>
  1385. <a name="PHILIPS_AUDIOattr"></a>
  1386. <ul>
  1387. <b>Attribute</b><br><br>
  1388. <ul>
  1389. <ul>
  1390. <li><b><a href="#do_not_notify">do_not_notify</a></b></li>
  1391. <li><b><a href="#readingFnAttributes">readingFnAttributes</a></b></li><br>
  1392. <li><b><a name="request-timeout">request-timeout</a></b></li><br>
  1393. Optionales Attribut, um das HTTP response timeout zu beeinflu&szlig;en.<br>
  1394. M&ouml;gliche Werte: 1...5 Sekunden. Default Wert ist 4 Sekunden.<br><br>
  1395. <li><b><a name="max-device-presets">max-device-presets</a></b></li>
  1396. <br>Optionales Attribut zur Bestimmung der max. Anzahl von verf&uumlgbaren Preset-Speicherpl&aumltzen des Players. Default-Wert 24.<br><br>
  1397. <li><b><a name="max-device-favorites">max-device-favorites</a></b></li>
  1398. <br>Optionales Attribut zur Bestimmung der max. Anzahl von verf&uumlgbaren Favorite-Speicherpl&aumltzen des Players. Default-Wert 24.<br><br>
  1399. <li><b><a name="disable">disable</a></b></li><br>
  1400. Optionales Attribut zum Deaktivieren des internen zyklischen Timers zum Aktualisieren des NP-Status. Manuelles Update ist nach wie vor m&ouml;glich.<br>
  1401. M&ouml;gliche Werte: 0 &rarr; Zyklisches Update aktiv., 1 &rarr; Zyklisches Update inaktiv.<br><br><br>
  1402. </ul>
  1403. </ul>
  1404. <b>Readings</b><br><br>
  1405. <ul>
  1406. <ul>
  1407. <li><b>albumArt</b> - Link zum aktuellen Album art oder Radiostation.</li>
  1408. <li><b>elapseTime</b> - Aktuelle Zeit des abgespielten Audiost&uuml;ckes.</li>
  1409. <li><b>inetRadioFavorite[Wert]</b> - Name des/der gespeicherten Favoriten.</li>
  1410. <li><b>inetRadioPreset[Wert]</b> - Name des/der gespeicherten Presets.</li>
  1411. <li><b>mute</b> - Abfrage des Stummschaltungstatus (on|off).</li>
  1412. <li><b>playing</b> - Abfrage des aktuelle Playierstatus (yes|no).</li>
  1413. <li><b>power</b> - Abfrage des aktuellen Ger&auml;tezustands (on|absent).</li>
  1414. <li><b>presence</b> - Abfrage der Ger&auml;teanwesenheit (present|absent).</li>
  1415. <li><b>state</b> - Abfrage des aktuellen 'state'-Status (on|absent).</li>
  1416. <li><b>subtitle</b> - Untertiltel des abgespielten Audiost&uuml;ckes.</li>
  1417. <li><b>title</b> - Titel des abgespielten Audiost&uuml;ckes.</li>
  1418. <li><b>totalInetRadioFavorites</b> - Anzahl der gespeicherten Favoriten.</li>
  1419. <li><b>totalInetRadioPresets</b> - Anzahl der gespeicherten Presets.</li>
  1420. <li><b>totalTime</b> Gesamtspieldauer des Audiost&uuml;ckes.</li>
  1421. <li><b>volume</b> - Aktuelle relative Lautst&auml;rke (0..100).</li>
  1422. <li><b>volumeStraight</b> - Aktuelle absolute Lautst&auml;rke (0..64).</li>
  1423. </ul>
  1424. </ul><br>
  1425. <b>Bemerkung des Entwicklers</b><br><br>
  1426. <ul>
  1427. Trivial: Um das Ger&auml;t fernbedienen zu k&ouml;nnen, muss es an das Ethernet-Netzwerk angeschlossen und erreichbar sein.<br>
  1428. Es gibt keine M&ouml;glichkeit, den Zustand Power-on/Standby des Ger&auml;tes abzufragen. Diese Limitierung liegt auf Seiten des Ger&auml;tes.<br>
  1429. </ul><br>
  1430. </ul>
  1431. =end html_DE
  1432. =cut