| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563 |
- ##############################################################################
- #
- # $Id: 71_PHILIPS_AUDIO.pm 11329 2016-04-27 18:00:43Z ra666ack $
- #
- # 71_PHILIPS_AUDIO.pm
- #
- # An FHEM Perl module for controlling Philips Audio Equipment connected to local network
- # such as MCi, Streamium and Fidelio devices.
- # The module provides basic functionality accessible through the port 8889 of the device:
- # (http://<device_ip>:8889/index).
- # e.g. AW9000, NP3500, NP3700, NP3900
- #
- # Copyright by Radoslaw Watroba
- # (e-mail: ra666ack at g**glemail d*t c*m)
- #
- # This file is part of fhem.
- #
- # Fhem is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 2 of the License, or
- # (at your option) any later version.
- #
- # Fhem is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with fhem. If not, see <http://www.gnu.org/licenses/>.
- #
- ##############################################################################
- package main;
- use strict;
- use warnings;
- use Time::HiRes qw(gettimeofday sleep);
- use Time::Piece;
- use POSIX qw{strftime};
- use HttpUtils;
- ###################################
- sub PHILIPS_AUDIO_Initialize
- {
- my ($hash) = @_;
- $hash->{DefFn} = "PHILIPS_AUDIO_Define";
- $hash->{GetFn} = "PHILIPS_AUDIO_Get";
- $hash->{SetFn} = "PHILIPS_AUDIO_Set";
- $hash->{AttrFn} = "PHILIPS_AUDIO_Attr";
- $hash->{UndefFn} = "PHILIPS_AUDIO_Undefine";
- $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;
-
- return;
- }
- ###################################
- sub PHILIPS_AUDIO_GetStatus
- {
- my ($hash, $local) = @_;
- my $name = $hash->{NAME};
- my $power;
- $local = 0 unless(defined($local));
- return "" if((!defined($hash->{IP_ADDRESS})) or (!defined($hash->{helper}{OFF_INTERVAL})) or (!defined($hash->{helper}{ON_INTERVAL})));
- my $device = $hash->{IP_ADDRESS};
-
-
- # Check for Presets availability
- if(not defined($hash->{READINGS}{"totalInetRadioPresets"}))
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", "getInetRadioPresets", "noArg");
- # Wait 10 seconds for next http request due to slow command processing of the streamium devices.
- PHILIPS_AUDIO_ResetTimer($hash, 10);
- return;
- }
- # Check for Favorites availability
- if(not defined($hash->{READINGS}{"totalInetRadioFavorites"}))
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", "getInetRadioFavorites", "noArg");
- # Wait 10 seconds for next http request due to slow command processing of the streamium devices.
- PHILIPS_AUDIO_ResetTimer($hash, 10);
- return;
- }
- PHILIPS_AUDIO_SendCommand($hash, "/nowplay", "","nowplay", "noArg");
- PHILIPS_AUDIO_ResetTimer($hash) unless($local == 1);
-
- return;
- }
- ###################################
- sub PHILIPS_AUDIO_Get
- {
- my ($hash, @a) = @_;
- my $what;
- my $return;
-
- my $name = $hash->{NAME};
-
- my $address = $hash->{IP_ADDRESS};
- $hash->{IP_ADDRESS} = $address;
-
- return "argument is missing" if(int(@a) != 2);
-
- if(not defined($hash->{MODEL}))
- {
- return "Please provide the model information as argument.";
- }
- $what = $a[1];
-
- if(exists($hash->{READINGS}{$what}))
- {
- if(defined($hash->{READINGS}{$what}))
- {
- return $hash->{READINGS}{$what}{VAL};
- }
- else
- {
- return "no such reading: $what";
- }
- }
- else
- {
- $return = "unknown argument $what, choose one of";
-
- foreach my $reading (keys %{$hash->{READINGS}})
- {
- $return .= " $reading:noArg";
- }
-
- return $return;
- }
- }
- ###################################
- sub PHILIPS_AUDIO_Set
- {
- my ($hash, @a) = @_;
- my $name = $hash->{NAME};
- my $port = $hash->{PORT};
-
- if(not defined($hash->{MODEL}))
- {
- return "Please provide the model information as argument.";
- }
-
- return "No Argument given" if(!defined($a[1]));
- my $what = $a[1];
- my $index;
-
- # Provide number of selectable presets according to the given attribute
- my $inetRadioPreset = "inetRadioPreset:";
- for ($index = 1; $index < AttrVal($name, "max-device-presets", "24"); $index++)
- {
- $inetRadioPreset .= $index . ",";
- }
- $inetRadioPreset .= $index . " ";
-
- # Provide number of selectable favorites according to the given attribute
- my $inetRadioFavorite = "inetRadioFavorite:";
- for ($index = 1; $index < AttrVal($name, "max-device-favorites", "24"); $index++)
- {
- $inetRadioFavorite .= $index . ",";
- }
- $inetRadioFavorite .= $index . " ";
- my $usage;
-
- my $model = $hash->{MODEL};
- $usage = "Unknown argument $what, choose one of ".
- "volumeStraight:slider,0,1,64 ".
- "volume:slider,0,1,100 ".
- #"volumeUp:noArg ".
- #"volumeDown:noArg ".
- "standbyButton:noArg ".
- "unmute:noArg ".
- "next:noArg ".
- "previous:noArg ".
- "play_pause:noArg ".
- "stop:noArg ".
- "shuffle:on,off ".
- "aux:noArg ".
- ((uc($model) eq "AW9000") ? "mp3link:noArg " : ""). # Input implemented in AW9000 only
- ((uc($model) eq "AW9000") ? "coaxial:noArg " : ""). # Input implemented in AW9000 only
- ((uc($model) eq "AW9000") ? "optical:noArg " : ""). # Input implemented in AW9000 only
- #"input:aux,internetRadio,mediaLibrary,onlineServices ".
- $inetRadioPreset.
- $inetRadioFavorite.
- "statusRequest:noArg ".
- "getInetRadioPresets:noArg ".
- "getInetRadioFavorites:noArg ".
- ((exists($hash->{helper}{PRESETS}))? "inetRadioPresetByName:".($hash->{helper}{PRESETS})." ":"").
- ((exists($hash->{helper}{FAVORITES}))? "inetRadioFavoriteByName:".($hash->{helper}{FAVORITES})." ":"").
- #"addToFavourites:noArg ".
- #"removeFromFavourites:noArg ".
- "repeat:single,all,off ".
- #"home:noArg ".
- "mute:noArg ";
-
- Log3 $name, 5, "PHILIPS_AUDIO ($name) - set ".join(" ", @a);
-
- if($what eq "standbyButton")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$STANDBY", "",$what, "noArg");
- }
- elsif($what eq "aux")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/aux", "",$what, $a[2]);
- }
- elsif($what eq "mp3link")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/mp3link", "",$what, $a[2]);
- }
- elsif($what eq "coaxial")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/digin_coaxial", "",$what, $a[2]);
- }
- elsif($what eq "optical")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/digin_optical", "",$what, $a[2]);
- }
- elsif($what eq "home")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/index", "",$what, $a[2]);
- }
- elsif($what eq "mediaLibrary")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$02\$01\$001\$0", "",$what, $a[2]);
- }
- elsif($what eq "internetRadio")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "",$what, $a[2]);
- }
- elsif($what eq "onlineServices")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$09\$01\$001\$0", "",$what, $a[2]);
- }
- elsif($what eq "shuffle")
- {
- if($a[2] eq "on")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/MODE\$SHUFFLE_ON", "",$what, $a[2]);
- }
- elsif($a[2] eq "off")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/MODE\$SHUFFLE_OFF", "",$what, $a[2]);
- }
- else
- {
- return $usage;
- }
- }
- elsif($what eq "repeat")
- {
- if($a[2] eq "single")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/MODE\$REPEAT_SINGLE", "",$what, $a[2]);
- }
- elsif($a[2] eq "all")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/MODE\$REPEAT_ALL", "",$what, $a[2]);
- }
- elsif($a[2] eq "off")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/MODE\$REPEAT_OFF", "",$what, $a[2]);
- }
- else
- {
- return $usage;
- }
- }
- elsif($what eq "statusRequest")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/nowplay", "","nowplay", "noArg");
- }
- elsif($what eq "addToFavourites")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$ADD2FAV", "",$what, "noArg");
- }
- elsif($what eq "removeFromFavourites")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$REMFAV", "",$what, "noArg");
- }
- elsif($what eq "mute")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$MUTE", "",$what, "noArg");
- }
- elsif($what eq "unmute")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$UNMUTE", "",$what, "noArg");
- }
- elsif($what eq "next")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$NEXT", "",$what, "noArg");
- }
- elsif($what eq "previous")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$PREV", "",$what, "noArg");
- }
- elsif($what eq "play_pause")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$PLAY_PAUSE", "",$what, "noArg");
- }
- elsif($what eq "stop")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/CTRL\$STOP", "",$what, "noArg");
- }
- elsif($what eq "inetRadioPreset")
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- $hash->{helper}{inetRadioPreset} = $a[2];
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
- }
- elsif($what eq "inetRadioPresetByName")
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- my ($presetNumber, $presetName) = split(/:/, $a[2], 2);
- $hash->{helper}{inetRadioPresetNumber} = $presetNumber;
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
- }
- elsif($what eq "inetRadioFavorite")
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- $hash->{helper}{inetRadioFavorite} = $a[2];
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
- }
- elsif($what eq "inetRadioFavoriteByName")
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- my ($favoriteNumber, $favoriteName) = split(/:/, $a[2], 2);
- $hash->{helper}{inetRadioFavoriteNumber} = $favoriteNumber;
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, $a[2]);
- }
- elsif($what eq "volumeStraight")
- {
- if($a[2] >= 0 and $a[2] <= 64)
- {
- $hash->{helper}{targetVolume} = $a[2];
- PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$VAL\$".$a[2], "",$what, $a[2]);
- }
- else
- {
- return "volumeStraight must be in the range 0...64.";
- }
- }
- elsif($what eq "volume")
- {
- if($a[2] >= 0 and $a[2] <= 100)
- {
- $hash->{helper}{targetVolume} = PHILIPS_AUDIO_volume_rel2abs($hash, $a[2]);
- PHILIPS_AUDIO_SendCommand($hash, "/VOLUME\$VAL\$".$a[2], "",$what, $a[2]);
- }
- else
- {
- return "volumeStraight must be in the range 0...100.";
- }
- }
- elsif($what eq "nowplay")
- {
- PHILIPS_AUDIO_SendCommand($hash, "/nowplay", "",$what, "noArg");
- }
- elsif($what eq "getInetRadioPresets")
- {
-
- delete($hash->{helper}{PRESETS});
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, "noArg");
- }
- elsif($what eq "getInetRadioFavorites")
- {
- # Hierarchichal navigation through the contents mandatory
- $hash->{helper}{cmdStep} = 1;
- PHILIPS_AUDIO_SendCommand($hash, "/index", "", $what, "noArg");
- }
- else
- {
- return $usage;
- }
- PHILIPS_AUDIO_ResetTimer($hash);
-
- return;
- }
- #############################
- sub PHILIPS_AUDIO_Define
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- my $name = $hash->{NAME};
-
- if(! @a >= 4)
- {
- my $msg = "Wrong syntax: define <name> PHILIPS_AUDIO <model> <ip-or-hostname> [<ON-statusinterval>] [<OFF-statusinterval>] ";
- Log3 $name, 2, $msg;
- return $msg;
- }
-
- if(defined($a[2]))
- {
- $hash->{MODEL} = uc($a[2]);
-
- # Used by 'fheminfo' command for statistics
- $attr{$name}{"model"} = $hash->{MODEL};
- }
-
- $hash->{IP_ADDRESS} = $a[3];
- $hash->{PORT} = 8889;
-
- # if an update interval was given which is greater than zero, use it.
- if(defined($a[4]) and $a[4] > 0)
- {
- $hash->{helper}{OFF_INTERVAL} = $a[4];
- # Minimum interval 3 sec
- if($hash->{helper}{OFF_INTERVAL} < 3)
- {
- $hash->{helper}{OFF_INTERVAL} = 3;
- }
- }
- else
- {
- $hash->{helper}{OFF_INTERVAL} = 30;
- }
-
- if(defined($a[5]) and $a[5] > 0)
- {
- $hash->{helper}{ON_INTERVAL} = $a[5];
- # Minimum interval 3 sec
- if($hash->{helper}{ON_INTERVAL} < 3)
- {
- $hash->{helper}{ON_INTERVAL} = 3;
- }
- }
- else
- {
- $hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL};
- }
-
- unless(exists($hash->{helper}{AVAILABLE}) and ($hash->{helper}{AVAILABLE} == 0))
- {
- $hash->{helper}{AVAILABLE} = 1;
- readingsSingleUpdate($hash, "presence", "present", 1);
- }
-
- # start the status update timer
- $hash->{helper}{DISABLED} = 0 unless(exists($hash->{helper}{DISABLED}));
- PHILIPS_AUDIO_ResetTimer($hash,0);
-
- return;
- }
- ##########################
- sub PHILIPS_AUDIO_Attr
- {
- my @a = @_;
- my $hash = $defs{$a[1]};
- if($a[0] eq "set" && $a[2] eq "disable")
- {
- if($a[3] eq "0")
- {
- $hash->{helper}{DISABLED} = 0;
- PHILIPS_AUDIO_GetStatus($hash, 1);
- }
- elsif($a[3] eq "1")
- {
- $hash->{helper}{DISABLED} = 1;
- }
- }
- elsif($a[0] eq "del" && $a[2] eq "disable")
- {
- $hash->{helper}{DISABLED} = 0;
- PHILIPS_AUDIO_GetStatus($hash, 1);
- }
- # Start/Stop Timer according to new disabled-Value
- PHILIPS_AUDIO_ResetTimer($hash);
- return;
- }
- #############################
- sub PHILIPS_AUDIO_Undefine
- {
- my($hash, $name) = @_;
- # Stop the internal GetStatus-Loop and exit
- RemoveInternalTimer($hash);
- return;
- }
- ############################################################################################################
- #
- # Begin of helper functions
- #
- ############################################################################################################
- #############################
- # sends a command to the receiver via HTTP
- sub PHILIPS_AUDIO_SendCommand
- {
- my ($hash,$url,$data,$cmd,$arg) = @_;
- my $name = $hash->{NAME};
- my $address = $hash->{IP_ADDRESS};
- my $port = $hash->{PORT};
- Log3 $name, 5, "PHILIPS_AUDIO ($name) - execute nonblocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data";
-
- HttpUtils_NonblockingGet
- ({
- url => "http://".$address.":".$port."".$url,
- timeout => AttrVal($name, "request-timeout", 30),
- noshutdown => 1,
- data => $data,
- loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
- hash => $hash,
- cmd => $cmd,
- arg => $arg,
- callback => \&PHILIPS_AUDIO_ParseResponse
- });
- return;
- }
- #############################
- # parses the receiver response
- sub PHILIPS_AUDIO_ParseResponse
- {
- my ($param, $err, $data ) = @_;
-
- my $hash = $param->{hash};
- my $name = $hash->{NAME};
- my $cmd = $param->{cmd};
- my $arg = $param->{arg};
-
- if(exists($param->{code}))
- {
- Log3 $name, 5, "PHILIPS_AUDIO ($name) - received HTTP code ".$param->{code}." for command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\"";
- }
-
- #Log3 $name, 5, "Error = $err";
- #Log3 $name, 5, "Data = $data";
-
- if($err ne "")
- {
- Log3 $name, 5, "PHILIPS_AUDIO ($name) - could not execute command \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $err";
- if((not exists($hash->{helper}{AVAILABLE})) or (exists($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} == 1))
- {
- 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.";
- readingsSingleUpdate($hash, "presence", "absent", 1);
- readingsSingleUpdate($hash, "state", "absent", 1);
- $hash->{STATE} = "absent";
- }
- $hash->{helper}{AVAILABLE} = 0;
- }
- elsif($data ne "")
- {
- Log3 $name, 5, "PHILIPS_AUDIO ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data";
- if (defined($hash->{helper}{AVAILABLE}) and $hash->{helper}{AVAILABLE} eq 0)
- {
- Log3 $name, 3, "PHILIPS_AUDIO ($name) - device $name reappeared";
- readingsSingleUpdate($hash, "presence", "present", 1);
- }
-
- $hash->{helper}{AVAILABLE} = 1;
-
- readingsBeginUpdate($hash);
-
- readingsBulkUpdate($hash, "power", "on");
- readingsBulkUpdate($hash, "state","on");
- $hash->{STATE} = "on";
-
- if($cmd eq "standbyButton")
- {
- if($data =~ /SUCCESS/)
- {
- #readingsBulkUpdate($hash, "power", "on");
- #readingsBulkUpdate($hash, "state","on");
- }
- }
- elsif($cmd eq "mute")
- {
- if($data =~ /SUCCESS/)
- {
- readingsBulkUpdate($hash, "mute", "on");
- }
- }
- elsif($cmd eq "unmute")
- {
- if($data =~ /SUCCESS/)
- {
- readingsBulkUpdate($hash, "mute", "off");
- }
- }
- elsif($cmd eq "removeFromFavourites")
- {
- # evtl. for future use
- }
- elsif($cmd eq "addToFavourites")
- {
- # evtl. for future use
- }
- elsif($cmd eq "inetRadioPreset")
- {
- # This command must be processed hierarchicaly through the navigation path
- if($hash->{helper}{cmdStep} == 1)
- {
- $hash->{helper}{cmdStep} = 2;
- # Internet radio
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioPreset", $hash->{helper}{inetRadioPreset});
- }
- elsif($hash->{helper}{cmdStep} == 2)
- {
- $hash->{helper}{cmdStep} = 3;
- # Presets
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$001\$0", "","inetRadioPreset", $hash->{helper}{inetRadioPreset});
- }
- elsif($hash->{helper}{cmdStep} == 3)
- {
- $hash->{helper}{cmdStep} = 4;
- # Preset select
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$".sprintf("%03d", $hash->{helper}{inetRadioPreset})."\$1", "","inetRadioPreset", $hash->{helper}{inetRadioPreset});
- }
- }
- elsif($cmd eq "inetRadioPresetByName")
- {
- # This command must be processed hierarchicaly through the navigation path
- if($hash->{helper}{cmdStep} == 1)
- {
- $hash->{helper}{cmdStep} = 2;
- # Internet radio
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioPresetByName", $hash->{helper}{inetRadioPresetNumber});
- }
- elsif($hash->{helper}{cmdStep} == 2)
- {
- $hash->{helper}{cmdStep} = 3;
- # Presets
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$001\$0", "","inetRadioPresetByName", $hash->{helper}{inetRadioPresetNumber});
- }
- elsif($hash->{helper}{cmdStep} == 3)
- {
- $hash->{helper}{cmdStep} = 4;
- # Preset select
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$". sprintf("%03d", $hash->{helper}{inetRadioPresetNumber}) . "\$1", "", "inetRadioPresetByName", $hash->{helper}{inetRadioPresetNumber});
- }
- }
- elsif($cmd eq "inetRadioFavorite")
- {
- # This command must be processed hierarchicaly through the navigation path
- if($hash->{helper}{cmdStep} == 1)
- {
- $hash->{helper}{cmdStep} = 2;
- # Internet radio favorite
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioFavorite", $hash->{helper}{inetRadioFavorite});
- }
- elsif($hash->{helper}{cmdStep} == 2)
- {
- $hash->{helper}{cmdStep} = 3;
- # Favorite Presets
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$002\$0", "","inetRadioFavorite", $hash->{helper}{inetRadioFavorite});
- }
- elsif($hash->{helper}{cmdStep} == 3)
- {
- $hash->{helper}{cmdStep} = 4;
- # Favorite Preset select
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$".sprintf("%03d", $hash->{helper}{inetRadioFavorite})."\$1", "","inetRadioFavorite", $hash->{helper}{inetRadioFavorite});
- }
- }
- elsif($cmd eq "inetRadioFavoriteByName")
- {
- # This command must be processed hierarchicaly through the navigation path
- if($hash->{helper}{cmdStep} == 1)
- {
- $hash->{helper}{cmdStep} = 2;
- # Internet radio
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "", "inetRadioFavoriteByName", $hash->{helper}{inetRadioFavoriteNumber});
- }
- elsif($hash->{helper}{cmdStep} == 2)
- {
- $hash->{helper}{cmdStep} = 3;
- # Favorites
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$002\$0", "","inetRadioFavoriteByName", $hash->{helper}{inetRadioFavoriteNumber});
- }
- elsif($hash->{helper}{cmdStep} == 3)
- {
- $hash->{helper}{cmdStep} = 4;
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$03\$". sprintf("%03d", $hash->{helper}{inetRadioFavoriteNumber}) . "\$1", "", "inetRadioFavoriteByName", $hash->{helper}{inetRadioFavoriteNumber});
- }
- }
- elsif($cmd eq "play_pause")
- {
- if($data =~ /SUCCESS/)
- {
- #readingsBulkUpdate($hash, "play_pause", "on");
- #readingsBulkUpdate($hash, "stop", "off");
- }
- }
- elsif($cmd eq "stop")
- {
- if($data =~ /STOP/)
- {
- readingsBulkUpdate($hash, "playing", "no");
- }
- }
- elsif($cmd eq "volume" or $cmd eq "volumeStraight")
- {
- if($data =~ /SUCCESS/)
- {
- readingsBulkUpdate($hash, "volumeStraight", $hash->{helper}{targetVolume});
- my $targetVolume = $hash->{helper}{targetVolume};
- readingsBulkUpdate($hash, "volume", PHILIPS_AUDIO_volume_abs2rel($hash, $targetVolume));
- }
- }
- elsif($cmd eq "nowplay")
- {
- if($data =~ /'title':'\\'(.+)\\''/)
- {
- readingsBulkUpdate($hash, "title", PHILIPS_AUDIO_STREAMIUMNP2txt($1));
- }
- else
- {
- readingsBulkUpdate($hash, "title", "");
- }
-
- if($data =~ /'title':'(.+)'/)
- {
- readingsBulkUpdate($hash, "title", PHILIPS_AUDIO_STREAMIUMNP2txt($1));
- }
- else
- {
- readingsBulkUpdate($hash, "title", "");
- }
-
- if($data =~ /'subTitle':'(.+)'/)
- {
- readingsBulkUpdate($hash, "subtitle", $1);
- }
- else
- {
- readingsBulkUpdate($hash, "subtitle", "");
- }
-
- if($data =~ /'albumArt':'(.+)'/)
- {
- readingsBulkUpdate($hash, "albumArt", $1);
- }
- else
- {
- readingsBulkUpdate($hash, "albumArt", "");
- }
-
- if($data =~ /'volume':(.+),/)
- {
- readingsBulkUpdate($hash, "volumeStraight", $1);
- readingsBulkUpdate($hash, "volume", PHILIPS_AUDIO_volume_abs2rel($hash, $1));
- }
- else
- {
- readingsBulkUpdate($hash, "volumeStraight", "0");
- readingsBulkUpdate($hash, "volume", "0");
- }
-
- if($data =~ /'elapsetime':(.+),/)
- {
- readingsBulkUpdate($hash, "elapseTime", strftime("\%H:\%M:\%S", gmtime($1)));
- }
- else
- {
- readingsBulkUpdate($hash, "elapseTime", "");
- }
- if($data =~ /'totaltime':(.+),/)
- {
- # Playing radio delivers that total time
- if($1 eq "65535")
- {
- readingsBulkUpdate($hash, "totalTime", "infinite");
- }
- else
- {
- readingsBulkUpdate($hash, "totalTime", strftime("\%H:\%M:\%S", gmtime($1)));
- }
- }
- else
- {
- readingsBulkUpdate($hash, "totalTime", "");
- }
-
- if($data =~ /'muteStatus':(.+),/)
- {
- if($1 == 1)
- {
- readingsBulkUpdate($hash, "mute", "on");
- }
- else
- {
- readingsBulkUpdate($hash, "mute", "off");
- }
- }
-
- # typo in the (buggy) Streamium firmware...
- if($data =~ /'playStaus':(.+),/)
- {
- if($1 == 1)
- {
- readingsBulkUpdate($hash, "playing", "yes");
- }
- else
- {
- readingsBulkUpdate($hash, "playing", "no");
- }
- }
- else
- {
- readingsBulkUpdate($hash, "playing", "no");
- }
- }
-
- # Eventual future UPNP implementation. Requires IO::Socket::Multicast non-standard module.
- elsif ($cmd eq "getModel")
- {
- if($data =~ /<friendlyName>(.+)<\/friendlyName>/)
- {
- $hash->{FRIENDLY_NAME} = $1;
- }
- if($data =~ /<UDN>(.+)<\/UDN>/)
- {
- $hash->{UNIQUE_DEVICE_NAME} = uc($1);
- }
-
- my $modelName = "";
- my $modelNumber = "";
-
- if($data =~ /<modelName>(.+)<\/modelName>/)
- {
- $modelName = $1;
- }
- if($data =~ /<modelNumber>(.+)<\/modelNumber>/)
- {
- $modelNumber = $1;
- }
- # Combine both strings
- if(($modelName ne "") and ($modelNumber ne ""))
- {
- $hash->{MODEL} = $modelName . $modelNumber;
- }
-
- if($data =~ /<serialNumber>(.+)<\/serialNumber>/)
- {
- $hash->{SERIAL_NUMBER} = uc($1);
- }
- if($data =~ /<modelDescription>(.+)<\/modelDescription>/)
- {
- $hash->{MODEL_DESCRIPTION} = $1;
- }
- # Replace \n, \r, \t from the string for XML parsing
-
- # replace \n by ""
- $data =~ s/\n//g;
-
- # replace \t by ""
- $data =~ s/\t//g;
-
- # replace \r by ""
- $data =~ s/\r//g;
-
- if($data =~ /<iconList>(.+?)<\/iconList>/)
- {
- my $address = $hash->{IP_ADDRESS};
- my $i = 1;
-
- while ($data =~ /<url>(.+?)<\/url>/g)
- {
- $hash->{"NP_ICON_$i"} = "http://".$address.":".$arg."/".$1;
- $i++;
- }
- }
- }
- elsif ($cmd eq "getInetRadioPresets")
- {
- # This command must be processed hierarchicaly through the navigation path
- if($hash->{helper}{cmdStep} == 1)
- {
- $hash->{helper}{cmdStep} = 2;
- # Internet radio
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "","getInetRadioPresets", "noArg");
- }
- elsif($hash->{helper}{cmdStep} == 2)
- {
- $hash->{helper}{cmdStep} = 3;
- # Presets
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$001\$0", "","getInetRadioPresets", "noArg");
- }
- elsif($hash->{helper}{cmdStep} == 3)
- {
-
- my $listedItems; # Visible Items in the display. Max 8
- my $nextreqURL;
- my $i;
- my $presetID = 0;
- my $presetName;
- # Parse first 8 Presets
- if($data =~ /<title>Error<\/title>/)
- {
- # In case on presets defined the player returns an Error
- # Do nothing
- $hash->{helper}{TOTALINETRADIOPRESETS} = 0;
- readingsBulkUpdate($hash, "totalInetRadioPresets", "0");
- }
- else
- {
- if ($data =~ /'nextrequrl':'(.+?)',/)
- {
- $nextreqURL = $1;
- #Log3 $name, 5, "NextreqURL: $nextreqURL";
- }
- if ($data =~ /'totalListCount':(.+),/)
- {
- $hash->{helper}{TOTALINETRADIOPRESETS} = $1;
- readingsBulkUpdate($hash, "totalInetRadioPresets", $1);
- #Log3 $name, 5, "ListedItems: $listedItems";
- }
-
- #if ($data =~ /'totalitems':(.+),/)
- #{
- # $listedItems = $1;
- #}
-
- $data =~ s/\R//g; # Remove new lines
- for(;;)
- {
- if($data =~ /{'title':'(.+?)',/g)
- {
- $presetName = $1;
- #Log3 $name, 5, "PresetName: $presetName";
-
- if($data =~ /'id':(.+?),/g)
- {
- $presetID = $1;
- #Log3 $name, 5, "PresetIDLoop: $presetID";
- }
- if ($presetID ne "" and $presetName ne "")
- {
- readingsBulkUpdate($hash, sprintf("inetRadioPreset%02d", $presetID), $presetName);
- }
- }
- else
- {
- last;
- }
- }
- #Log3 $name, 5, "PresetIDNachLoop: $presetID";
- if($presetID < ($hash->{helper}{TOTALINETRADIOPRESETS})) # Maximum listed items = 8. Get the next items by sending the nextreqURL
- {
- PHILIPS_AUDIO_SendCommand($hash, $nextreqURL, "","getInetRadioPresets", "noArg");
- }
- else
- {
- $hash->{helper}{cmdStep} = 4;
- if (exists($hash->{helper}{PRESETS}))
- {
- $hash->{helper}{PRESETS} = ""; # Reset the pull-down menue
- }
- PHILIPS_AUDIO_updatePresets($hash);
- #my $debug = $hash->{helper}{PRESETS};
- #Log3 $name, 5, "Presets: $debug";
- }
- }
- }
- }
- elsif ($cmd eq "getInetRadioFavorites")
- {
- # This command must be processed hierarchicaly through the navigation path
- if($hash->{helper}{cmdStep} == 1)
- {
- $hash->{helper}{cmdStep} = 2;
- # Internet radio
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$01\$001\$0", "","getInetRadioFavorites", "noArg");
- }
- elsif($hash->{helper}{cmdStep} == 2)
- {
- $hash->{helper}{cmdStep} = 3;
- # Favorites
- PHILIPS_AUDIO_SendCommand($hash, "/nav\$03\$02\$002\$0", "","getInetRadioFavorites", "noArg");
- }
- elsif($hash->{helper}{cmdStep} == 3)
- {
- if($data =~ /<title>Error<\/title>/)
- {
- # In case on presets defined the player returns an Error
- # Do nothing
- $hash->{helper}{TOTALINETRADIOFAVORITES} = 0;
- readingsBulkUpdate($hash, "totalInetRadioFavorites", "0");
- }
- else
- {
- my $listedItems; # Visible Items in the display. Max 8
- my $nextreqURL;
- my $i;
- my $favoriteID = 0;
- my $favoriteName;
- # Parse first 8 Presets
- if ($data =~ /'nextrequrl':'(.+?)',/)
- {
- $nextreqURL = $1;
- #Log3 $name, 5, "NextreqURL: $nextreqURL";
- }
- if ($data =~ /'totalListCount':(.+),/)
- {
- $hash->{helper}{TOTALINETRADIOFAVORITES} = $1;
- readingsBulkUpdate($hash, "totalInetRadioFavorites", $1);
- #Log3 $name, 5, "ListedItems: $listedItems";
- }
-
- #if ($data =~ /'totalitems':(.+),/)
- #{
- # $listedItems = $1;
- #}
-
- $data =~ s/\R//g; # Remove new lines
- for(;;)
- {
- if($data =~ /{'title':'(.+?)',/g)
- {
- $favoriteName = $1;
- #Log3 $name, 5, "FavoriteName: $favoriteName";
-
- if($data =~ /'id':(.+?),/g)
- {
- $favoriteID = $1;
- #Log3 $name, 5, "FavoriteIDLoop: $favoriteID";
- }
- if ($favoriteID ne "" and $favoriteName ne "")
- {
- readingsBulkUpdate($hash, sprintf("inetRadioFavorite%02d", $favoriteID), $favoriteName);
- }
- }
- else
- {
- last;
- }
- }
- #Log3 $name, 5, "FavoriteIDNachLoop: $favoriteID";
- if($favoriteID < ($hash->{helper}{TOTALINETRADIOFAVORITES})) # Maximum listed items = 8. Get the next items by sending the nextreqURL
- {
- PHILIPS_AUDIO_SendCommand($hash, $nextreqURL, "","getInetRadioFavorites", "noArg");
- }
- else
- {
- $hash->{helper}{cmdStep} = 4;
- if (exists($hash->{helper}{FAVORITES}))
- {
- $hash->{helper}{FAVORITES} = ""; # Reset the pull-down menue
- }
- PHILIPS_AUDIO_updateFavorites($hash);
- #my $debug = $hash->{helper}{FAVORITES};
- #Log3 $name, 5, "Favorites: $debug";
- }
- }
- }
- }
- readingsEndUpdate($hash, 1);
- return;
- }
- }
- #############################
- # converts straight volume in percentage volume (volumestraightmin .. volumestraightmax => 0 .. 100%)
- sub PHILIPS_AUDIO_volume_rel2abs
- {
- my ($hash, $percentage) = @_;
-
- return int(($percentage * 64 / 100 ));
- }
- #############################
- # converts relative volume to "straight" volume (0 .. 100% => volumestraightmin .. volumestraightmax)
- sub PHILIPS_AUDIO_volume_abs2rel
- {
- my ($hash, $absolute) = @_;
-
- return int(int($absolute * 100) / int(64));
- }
- #############################
- # Restarts the internal status request timer according to the given interval or current receiver state
- sub PHILIPS_AUDIO_ResetTimer
- {
- my ($hash, $interval) = @_;
- RemoveInternalTimer($hash);
- if($hash->{helper}{DISABLED} == 0)
- {
- if(defined($interval))
- {
- InternalTimer(gettimeofday()+$interval, "PHILIPS_AUDIO_GetStatus", $hash, 0);
- }
- elsif((exists($hash->{READINGS}{presence}{VAL}) and $hash->{READINGS}{presence}{VAL} eq "present") and (exists($hash->{READINGS}{power}{VAL}) and $hash->{READINGS}{power}{VAL} eq "on"))
- {
- InternalTimer(gettimeofday() + $hash->{helper}{ON_INTERVAL}, "PHILIPS_AUDIO_GetStatus", $hash, 0);
- }
- else
- {
- InternalTimer(gettimeofday() + $hash->{helper}{OFF_INTERVAL}, "PHILIPS_AUDIO_GetStatus", $hash, 0);
- }
- }
- return;
- }
- #############################
- # convert all HTML entities into UTF-8 equivalent
- sub PHILIPS_AUDIO_STREAMIUMNP2txt
- {
- my ($string) = @_;
- $string =~ s/\\'//g;
- return $string;
- }
- #############################
- # Updates the pull-down menue
- sub PHILIPS_AUDIO_updatePresets
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- if((not defined($hash->{helper}{PRESETS}) or length($hash->{helper}{PRESETS}) == 0))
- {
- my $presetName;
-
- for(my $i = 1; $i < (AttrVal($name, "max-device-presets", "24") + 1); $i++)
- {
- if(exists($hash->{READINGS}{sprintf("inetRadioPreset%02d", $i)}))
- {
- if($i != 1)
- {
- $presetName = ",";
- }
- $presetName .= sprintf("%02d", $i) . ":";
- $presetName .= $hash->{READINGS}{sprintf("inetRadioPreset%02d", $i)}{VAL};
- $presetName =~ s/ /_/g; # Replace blank by underscore
- $hash->{helper}{PRESETS} .= $presetName;
- }
- else
- {
- last;
- }
- }
- }
- else
- {
- $hash->{helper}{PRESETS} = "";
- }
- return;
- }
- #############################
- # Updates the pull-down menue
- sub PHILIPS_AUDIO_updateFavorites
- {
- my ($hash) = @_;
- my $name = $hash->{NAME};
- if((not defined($hash->{helper}{FAVORITES}) or length($hash->{helper}{FAVORITES}) == 0))
- {
- my $favoriteName;
-
- for(my $i = 1; $i < (AttrVal($name, "max-device-favorites", "24") + 1); $i++)
- {
- if(exists($hash->{READINGS}{sprintf("inetRadioFavorite%02d", $i)}))
- {
- if($i != 1)
- {
- $favoriteName = ",";
- }
- $favoriteName .= sprintf("%02d", $i) . ":";
- $favoriteName .= $hash->{READINGS}{sprintf("inetRadioFavorite%02d" , $i)}{VAL};
- $favoriteName =~ s/ /_/g; # Replace blank by underscore
- $hash->{helper}{FAVORITES} .= $favoriteName;
- }
- else
- {
- last;
- }
- }
- }
- }
- 1;
- =pod
- =begin html
- <a name="PHILIPS_AUDIO"></a>
- <h3>PHILIPS_AUDIO</h3>
- <ul>
- <a name="PHILIPS_AUDIOdefine"></a>
- <b>Define</b>
- <br><br>
- <ul>
- <code>
- define <name> PHILIPS_AUDIO <device model> <ip-address> [<status_interval>]<br><br>
- define <name> PHILIPS_AUDIO <device model> [<off_status_interval>] [<on_status_interval>]
- </code>
- <br><br>
- This module controls a Philips Audio Player e.g. MCi, Streamium or Fidelio and (potentially) any other device including a navigation server.<br>
- To check, open the following URL in the browser: http://[ip # of your device]:8889/index
- <br><br>
- (So far tested on: AW9000, NP3500, NP3700 and NP3900)
- <br><br>
- Currently implemented features:
- <br><br>
- <ul>
- <li>Power on/off</li>
- <li>Internet Radio Preset Selection</li>
- <li>Input selection</li>
- <li>Volume +/-</li>
- <li>Mute on/off</li>
- <li>...</li>
- </ul>
- <br>
- Defining a PHILIPS_AUDIO device will schedule an internal task (interval can be set
- with optional parameters <off_status_interval> and <on_status_interval> in seconds.<br>
- <off_status_interval> is a parameter used in case the device is powered off or not available.<br>
- <on_status_interval> is a parameter used in case the device is powered on.<br>
- If both parameters are unset, a default value 30 (seconds) for both is used.<br>
- If <off_status_interval> is set only the same value is used for both parameters.<br>
- Due to a relatively low-performance of the devices the minimum interval is set to 3 seconds.
- <br>
- The internal task periodically reads the status of the Network Player (power state, volume and mute status etc.) and triggers notify/filelog commands.
- <br><br>
- Example:<br><br>
- <ul><br>
- Add the following code into the <b>fhem.cfg</b> configuration file and restart fhem:<br><br>
- <code>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15<br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
- # With custom status interval of 60 seconds<br>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60</b><br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
- # With custom "off"-interval of 60 seconds and "on"-interval of 10 seconds<br>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60 10</b><br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
- </code>
- </ul>
- </ul>
- <br><br>
- <a name="PHILIPS_AUDIOset"></a>
- <b>Set</b>
- <ul>
- <code>
- set <name> <command> [<parameter>]
- </code><br><br>
- Currently, the following commands are defined.<br>
- <i>Note: Commands and parameters are case sensitive.</i><br>
- <ul><br><br>
- <u>Available commands:</u><br><br>
- <li><b>aux</b> - Switches to the AUX input (MP3 Link or similar).</li>
- <li><b>getInetRadioFavorites</b> - Reads the favorites. (May take some seconds...).</li>
- <li><b>getInetRadioPresets</b> - Reads the presets. (May take some seconds...).</li>
- <li><b>inetRadioFavorite</b> [1..24] - Selects an internet radio favorite (May take some seconds...).</li>
- <li><b>inetRadioPreset</b> [1..24] - Selects an internet radio preset (May take some seconds...).</li>
- <li><b>inetRadioFavoriteByName</b> [name] - Selects an internet radio favorite by name. (getInetRadioFavorites must be run previously for the command to become available.) (May take some seconds...).</li>
- <li><b>inetRadioPresetByName</b> [name] - Selects an internet radio preset by name. (getInetRadioPresets must be run previously for the command to become available.) (May take some seconds...).</li>
- <li><b>mute</b> - Mutes the device.</li>
- <li><b>unmute</b> - Unmutes the device.</li>
- <li><b>next</b> - Selects the next song, preset etc.</li>
- <li><b>play_pause</b> - Toggles PLAY/PAUSE.</li>
- <li><b>previous</b> - Selects the previous song, preset etc.</li>
- <li><b>repeat [single|all|off]</b> - Sets the repeat mode.</li>
- <li><b>shuffle [on|off]</b> - Sets the shuffle mode.</li>
- <li><b>standbyButton</b> - Toggles between standby and power on.</li>
- <li><b>statusRequest</b> - Updates the readings.</li>
- <li><b>stop</b> - Stops the player.</li>
- <li><b>volume</b> - Sets the relative volume 0...100%.</li>
- <li><b>volumeStraight</b> - Sets the absolute volume 0...64.</li>
- </ul><br><br>
- A typical example is powering the device remotely and tuning the favourite radio station:<br><br>
- Add the following code into the <b>fhem.cfg</b> configuration file:<br><br><br>
- <ul>
- <code>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 30 5<br>
- attr PHAUDIO_player webCmd volume:mute:inetRadioPreset
- </code>
- </ul><br><br>
- Add the following code into the <b>99_MyUtils.pm</b> file:<br><br>
- <ul>
- <code>
- sub startMyFavouriteRadioStation()<br>
- {<br>
- fhem "set PHAUDIO_player inetRadioPreset 1";<br>
- sleep 1;<br>
- fhem "set PHAUDIO_player volume 30";<br>
- }
- </code>
- </ul>
- <br><br>
- 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>
- Now the function can be called by typing the following line in the FHEM command line or by the notify-definitions:<br><br>
- <ul>
- <code>
- {startMyFavouriteRadioStation()}<br><br>
- </code>
- </ul>
- </ul>
- <a name="PHILIPS_AUDIOget"></a>
- <b>Get</b>
- <ul>
- <code>
- get <name> <reading>
- </code>
- <br><br>
- Currently, the 'get' command returns reading values only. For a specific list of possible values, see section <b>"Generated Readings"</b>.<br><br>
- </ul>
- <a name="PHILIPS_AUDIOattr"></a>
- <b>Attributes</b><br><br>
- <ul>
- <ul>
- <li><b><a href="#do_not_notify">do_not_notify</a></b></li>
- <li><b><a href="#readingFnAttributes">readingFnAttributes</a></b></li>
- <li><b><a name="request-timeout">request-timeout</a></b></li>
- <br>Optional attribute change the response timeout in seconds for all queries to the receiver.
- <br>Possible values: 1...5 seconds. Default value is 4 seconds.<br><br>
- <li><b><a name="max-device-presets">max-device-presets</a></b></li>
- <br>Optional attribute defining maximum number of available preset slots in device's memory. Default value 24.<br><br>
- <li><b><a name="max-device-favorites">max-device-favorites</a></b></li>
- <br>Optional attribute defining maximum number of favorite slots in device's memory. Default value 24.<br><br>
- <li><b><a name="disable">disable</a></b></li>
- <br>Optional attribute to disable the internal cyclic status update of the receiver. Manual status updates via statusRequest command is still possible.
- <br>Possible values: 0 → perform cyclic status update, 1 → don't perform cyclic status updates.<br><br><br>
- </ul>
- </ul>
- <b>Readings</b><br><br>
- <ul>
- <ul>
- <li><b>albumArt</b> - Link to current album art or radio station.</li>
- <li><b>elapseTime</b> - Elapse time of the played audio.</li>
- <li><b>inetRadioFavorite[value]</b> - Name of the stored favorite.</li>
- <li><b>inetRadioPreset[value]</b> - Name of the stored preset.</li>
- <li><b>mute</b> - Reports the mute status (on|off).</li>
- <li><b>playing</b> - Reports the current playier status (yes|no).</li>
- <li><b>power</b> - Reports the current power status (on|absent).</li>
- <li><b>presence</b> - Reports the current presence (present|absent).</li>
- <li><b>state</b> - Reports the current state status (on|absent).</li>
- <li><b>subtitle</b> - Reports the current subtitle of played audio.</li>
- <li><b>totalInetRadioFavorites</b> - Number of stored favorites.</li>
- <li><b>totalInetRadioPresets</b> - Number of stored presets.</li>
- <li><b>title</b> - Reports the current title of played audio.</li>
- <li><b>totalTime</b> - Reports the total time of the played audio.</li>
- <li><b>volume</b> - Reports current relative volume (0..100).</li>
- <li><b>volumeStraight</b> - Reports current absolute volume (0..64).</li>
- </ul>
- </ul><br>
- <b>Implementer's note</b><br><br>
- <ul>
- Trivial: In order to use that module the network player must be connected to the Ethernet.<br>
- 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>
- </ul><br>
- </ul>
- =end html
- =begin html_DE
- <a name="PHILIPS_AUDIO"></a>
- <h3>PHILIPS_AUDIO</h3>
- <ul>
- <a name="PHILIPS_AUDIOdefine"></a>
- <b>Define</b><br><br>
- <ul>
- <code>
- define <name> PHILIPS_AUDIO <device model> <ip-address> [<status_interval>]<br><br>
- define <name> PHILIPS_AUDIO <device model> [<off_status_interval>] [<on_status_interval>]
- </code>
- <br><br>
- Mit Hilfe dieses Moduls lassen sich Philips Audio Netzwerk Player wie z.B. MCi, Streamium oder Fidelio via Ethernet steuern.<br>
- Theoretisch sollten alle Geräte, die über einer implementierten HTTP Server am Port 8889 haben (http://[ip Nummer des Gerätes]:8889/index), bedient werden können.<br>
- <br>
- <br>
- (Getestet mit: AW9000, NP3500, NP3700 und NP3900)
- <br>
- <br>
- Die aktuelle Implementierung ermöglicht u.a. den folgenden Funktionsumfang:<br><br>
- <ul>
- <li>Power on/off</li>
- <li>Internet Radio Preset Auswahl</li>
- <li>Input Auswahl</li>
- <li>Volume +/-</li>
- <li>Mute on/off</li>
- <li>...</li>
- </ul>
- <br>
- Eine PHILIPS_AUDIO Definition initiiert einen internen Task, der von FHEM zyklisch abgearbeitet wird.<br>
- Das Intervall (in Sekunden) kann für die Zustände <on_status_interval> und <off_status_interval> optional gesetzt werden.<br>
- <off_status_interval> steht für das Intervall, wenn das Gerät ausgeschaltet/abwesend ist.<br>
- <on_status_interval> steht für das Intervall, wenn das Gerät eingeschaltet/verfügbar ist.<br>
- Wenn keine Parameter angegeben wurden, wird ein Default-Wert von 30 Sekunden für beide gesetzt.<br>
- Wenn nur <off_status_interval> gesetzt wird, gilt dieser Wert für beide Zustände (eingeschaltet/ausgeschaltet).<br>
- Der Task liest zyklisch grundlegende Parameter vom Player und triggert notify/filelog Befehle.<br>
- Aufgrund der recht schwachen Rechenleistung der Player wurde das minimale Intervall auf 3 Sekunden beschränkt.<br><br>
- Beispiel:<br><br>
- <ul><br>
- Definition in der <b>fhem.cfg</b> Konfigurationsdatei:<br><br>
- <code>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15<br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
- # 60 Sekunden Intervall<br>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60</b><br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset<br><br>
- # 60 Sekunden Intervall für "off" und 10 Sekunden für "on"<br>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 <b>60 10</b><br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset
- </code>
- </ul>
- </ul><br><br>
- <a name="PHILIPS_AUDIOset"></a>
- <b>Set</b>
- <ul>
- <code>
- set <name> <command> [<parameter>]
- </code>
- <br><br>
- Aktuell sind folgende Befehle implementiert:<br>
- <i>Bemerkung: Bitte bei den Befehlen und Parametern die Groß- und Kleinschreibung beachten.</i><br>
- <ul><br><br>
- <li><b>aux</b> - Schaltet auf den AUX Eingang um (MP3 Link oder ähnlich.).</li>
- <li><b>getInetRadioFavorites</b> - Liest die Favoriten. (Kann einige Sekunden dauern...).</li>
- <li><b>getInetRadioPresets</b> - Liest die Presets. (Kann einige Sekunden dauern...).</li>
- <li><b>inetRadioFavorite</b> [1..24] - Wählt den Internetradio-Lieblingssender (Das Umschalten kann einige Sekunden dauern...).</li>
- <li><b>inetRadioPreset</b> [1..24] - Wählt die Internetradio Voreinstellung (Das Umschalten kann einige Sekunden dauern...).</li>
- <li><b>inetRadioFavoriteByName</b> [name] - Wählt einen Internetradio Favoriten mit Hilfe seines Names. (getInetRadioFavorites muss zuvor ausgeführt werden, damit der Befehl verfügbar wird. (Kann einige Sekunden dauern...).</li>
- <li><b>inetRadioPresetByName</b> [name] - Wählt eine Internetradio Voreinstellung mit Hilfe ihres Names. (getInetRadioPresets muss zuvor ausgeführt werden, damit der Befehl verfügbar wird. (Kann einige Sekunden dauern...).</li>
- <li><b>mute</b> - Stummschaltung des Players.</li>
- <li><b>unmute</b> - Deaktivierung der Stummschaltung.</li>
- <li><b>next</b> - Wählt den nächten Titel, Voreinstellung etc.</li>
- <li><b>play_pause</b> - Schaltet um zwischen PLAY um PAUSE.</li>
- <li><b>previous</b> - Wählt den vorherigen Titel, Voreinstellung etc.</li>
- <li><b>repeat [single|all|off]</b> - Bestimmt den Wiederholungsmodus.</li>
- <li><b>shuffle [on|off]</b> - Bestimmt den Zufallswiedergabemodus.</li>
- <li><b>standbyButton</b> - Schaltet um zwischen Standby und Power on.</li>
- <li><b>statusRequest</b> - Readings Update.</li>
- <li><b>stop</b> - Stoppt den Player.</li>
- <li><b>volume</b> - Setzt die relative Lautstärke 0...100%.</li>
- <li><b>volumeStraight</b> - Setzt die absolute Lautstärke 0...64.</li>
- </ul><br><br>
- Ein typisches Beispiel ist das Einschalten des Gerätes und das Umschalten auf den Lieblingsradiosender:<br><br>
- Beispieldefinition in der <b>fhem.cfg</b> Konfigurationsdatei:<br><br><br>
- <ul>
- <code>
- define PHAUDIO_player PHILIPS_AUDIO NP3900 192.168.0.15 30 5<br>
- attr PHAUDIO_player webCmd input:volume:mute:inetRadioPreset
- </code>
- </ul><br><br>
- Folgender Code kann anschließend in die Datei <b>99_MyUtils.pm</b> eingebunden werden:<br><br>
- <ul>
- <code>
- sub startMyFavouriteRadioStation()<br>
- {<br>
- fhem "set PHAUDIO_player inetRadioPreset 1";<br>
- sleep 1;<br>
- fhem "set PHAUDIO_player volume 30";<br>}
- </code>
- </ul><br><br>
- <i>Bemerkung: Aufgrund der relativ langsamen Befehlsverarbeitung im Player im Vergleich zur asynchronen Ethernet-Kommunikation, kann es vorkommen, dass veraltete Statusinformationen zurückgesendet werden.<br>
- Aus diesem Grund wird empfohlen, während der Automatisierung zwischen den 'set' und 'get' Befehlen ein Delay einzubauen.</i><br><br>
- Die Funktion kann jetzt in der FHEM Befehlszeile eingegeben oder in die Notify-Definitionen eingebunden werden.<br><br>
- <ul>
- <code>
- {startMyFavouriteRadioStation()}<br><br>
- </code>
- </ul>
- </ul>
- <a name="PHILIPS_AUDIOget"></a>
- <b>Get</b>
- <code>
- get <name> <reading>
- </code><br><br>
- Aktuell liefert der Befehl 'get' ausschließlich Reading-Werte (s. Abschnitt <b>"Readings"</b>).<br><br>
- </ul>
- <a name="PHILIPS_AUDIOattr"></a>
- <ul>
- <b>Attribute</b><br><br>
- <ul>
- <ul>
- <li><b><a href="#do_not_notify">do_not_notify</a></b></li>
- <li><b><a href="#readingFnAttributes">readingFnAttributes</a></b></li><br>
- <li><b><a name="request-timeout">request-timeout</a></b></li><br>
- Optionales Attribut, um das HTTP response timeout zu beeinflußen.<br>
- Mögliche Werte: 1...5 Sekunden. Default Wert ist 4 Sekunden.<br><br>
- <li><b><a name="max-device-presets">max-device-presets</a></b></li>
- <br>Optionales Attribut zur Bestimmung der max. Anzahl von verfügbaren Preset-Speicherplätzen des Players. Default-Wert 24.<br><br>
- <li><b><a name="max-device-favorites">max-device-favorites</a></b></li>
- <br>Optionales Attribut zur Bestimmung der max. Anzahl von verfügbaren Favorite-Speicherplätzen des Players. Default-Wert 24.<br><br>
- <li><b><a name="disable">disable</a></b></li><br>
- Optionales Attribut zum Deaktivieren des internen zyklischen Timers zum Aktualisieren des NP-Status. Manuelles Update ist nach wie vor möglich.<br>
- Mögliche Werte: 0 → Zyklisches Update aktiv., 1 → Zyklisches Update inaktiv.<br><br><br>
- </ul>
- </ul>
- <b>Readings</b><br><br>
- <ul>
- <ul>
- <li><b>albumArt</b> - Link zum aktuellen Album art oder Radiostation.</li>
- <li><b>elapseTime</b> - Aktuelle Zeit des abgespielten Audiostückes.</li>
- <li><b>inetRadioFavorite[Wert]</b> - Name des/der gespeicherten Favoriten.</li>
- <li><b>inetRadioPreset[Wert]</b> - Name des/der gespeicherten Presets.</li>
- <li><b>mute</b> - Abfrage des Stummschaltungstatus (on|off).</li>
- <li><b>playing</b> - Abfrage des aktuelle Playierstatus (yes|no).</li>
- <li><b>power</b> - Abfrage des aktuellen Gerätezustands (on|absent).</li>
- <li><b>presence</b> - Abfrage der Geräteanwesenheit (present|absent).</li>
- <li><b>state</b> - Abfrage des aktuellen 'state'-Status (on|absent).</li>
- <li><b>subtitle</b> - Untertiltel des abgespielten Audiostückes.</li>
- <li><b>title</b> - Titel des abgespielten Audiostückes.</li>
- <li><b>totalInetRadioFavorites</b> - Anzahl der gespeicherten Favoriten.</li>
- <li><b>totalInetRadioPresets</b> - Anzahl der gespeicherten Presets.</li>
- <li><b>totalTime</b> Gesamtspieldauer des Audiostückes.</li>
- <li><b>volume</b> - Aktuelle relative Lautstärke (0..100).</li>
- <li><b>volumeStraight</b> - Aktuelle absolute Lautstärke (0..64).</li>
- </ul>
- </ul><br>
- <b>Bemerkung des Entwicklers</b><br><br>
- <ul>
- Trivial: Um das Gerät fernbedienen zu können, muss es an das Ethernet-Netzwerk angeschlossen und erreichbar sein.<br>
- Es gibt keine Möglichkeit, den Zustand Power-on/Standby des Gerätes abzufragen. Diese Limitierung liegt auf Seiten des Gerätes.<br>
- </ul><br>
- </ul>
- =end html_DE
- =cut
|