70_MEDIAPORTAL.pm 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. #################################################
  2. #
  3. # 70_MEDIAPORTAL.pm
  4. # Connects to a running MediaPortal instance via the WifiRemote plugin
  5. #
  6. # $Id: 70_MEDIAPORTAL.pm 16619 2018-04-15 10:29:01Z Reinerlein $
  7. #
  8. # Changed, adopted and new copyrighted by Reiner Leins (Reinerlein), (c) in February 2018
  9. # Original Copyright by Andreas Kwasnik (gemx)
  10. #
  11. # Fhem is free software: you can redistribute it and/or modify
  12. # it under the terms of the GNU General Public License as published by
  13. # the Free Software Foundation, either version 2 of the License, or
  14. # (at your option) any later version.
  15. #
  16. # Fhem is distributed in the hope that it will be useful,
  17. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. # GNU General Public License for more details.
  20. #
  21. # You should have received a copy of the GNU General Public License
  22. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  23. #
  24. ########################################################################################
  25. # Changelog
  26. # 15.04.2018
  27. # Beim Stoppen der Wiedergabe werden nun noch einige Readings geleert, damit diese sauber neu belegt werden können.
  28. # 26.02.2018
  29. # Es gab einen Fehler bei der prozentualen Positionsberechnung. Nun wird ein Dezimalbruch zwischen 0.0 und 100.0 ausgegeben, den man mit dem Attribut "PositionPercentFormat" z.B. auch auf mehrere Nachkommastellen formatieren kann.
  30. # Heartbeat und 3facher Verbindungsversuch wurden wieder abgeschafft, da es keinen Vorteil gebracht hat.
  31. # Der Verbindungsaufbau über die Fhem-Schnittstelle DevIO wird nun sauber durchgeführt und gehalten, sodass das Wiederverbinden sauber klappt
  32. # Einige neue Readings, um bei den verschiedenen Quellen auch die echten Quell-Infos zu erhalten (und nicht nur einen zusammengesetzten Titel)
  33. # 18.04.2017
  34. # Es gibt ein neues Reading "PositionPercent", welches die aktuelle Postion als Prozentangabe enthält
  35. # Bei einem Disconnect wird nun 3x versucht eine neue Verbindung aufzubauen
  36. # Es wurde ein Fehlerhandling eingebaut, wenn keine Plugins geladen werden konnten.
  37. # 12.03.2017
  38. # Es gibt einen neuen Getter "plugins", der das Reading "Plugins" mit den aktuell verfügbaren Plugins und deren WindowIds belegt
  39. # Es gibt einen neuen Setter "window" der als Parameter eine WindowId oder einen Pluginnamen (URL-Encoded mit %20 für Leerzeichen!) erhält
  40. # 14.03.2016
  41. # Es gibt nun ein Attribut "HeartbeatInterval", mit dem das Intervall für die Verbindungsprüfung festgelegt werden kann. Ein Wert von "0" deaktiviert die Prüfung.
  42. # Es gibt nun das Attribut "disable", mit dem das Modul deaktiviert werden kann.
  43. # 08.02.2016
  44. # Neuer MediaType "recording" hinzugefügt
  45. # 07.02.2016
  46. # In das offizielle Fhem-Release übernommen
  47. # Allgemein im Code aufgeräumt
  48. # Dokumentation hinzugefügt
  49. # Umlautproblem bei der Titelanzeige behoben
  50. # Mehr Readings befüllt, die sowieso geliefert werden. Dazu gehören z.B. Titelinformationen bei TV, Beschreibungen und die Informationen über den nächsten Titel.
  51. # $readingsFnAttributes hinzugefügt. Damit geht z.B. stateFormat oder event-on-change-reading
  52. # Fehlende Titelanzeige bei initialem Start der Wiedergabe behoben
  53. # WakeUp und Sleep hinzugefügt, damit man schnell den entsprechenden Mediaportal-Rechner hochfahren bzw. in den Hibernate-Modus schalten kann. Dazu wurde ein Attribut "macaddress" eingeführt.
  54. # Mögliche Parameter für Get und Set angegeben, sodass diese in FhemWeb entsprechend angeboten werden.
  55. # Volume umbenannt, damit das Reading die Grundlage für die Lautstärkeauswahl (Slider) ist.
  56. # Es gibt jetzt ein Attribut "generateNowPlayingUpdateEvents", mit dem man die Generierung von (bei der Wiedergabe) sekündlichen Aktualisierungen an-/abschalten kann
  57. # Die Mac-Adresse, die für das Aufwecken benötigt wird, wird nun automatisch ermittelt.
  58. # Die Read-Callbackfunktion wurde überarbeitet, da in einigen Fällen halbe Nachrichten zu einem Freeze geführt hatten.
  59. # Es gibt jetzt einen Setter "reconnect", der eine neue Verbindung zu Mediaportal aufbaut.
  60. # Wenn festgestellt wird, dass eine Verbindung zu Mediaportal nicht mehr lebendig ist, wird ein reconnect ausgeführt.
  61. #
  62. ##############################################################################
  63. package main;
  64. use strict;
  65. use warnings;
  66. use Time::HiRes qw(gettimeofday);
  67. use DevIo;
  68. use JSON;
  69. use HttpUtils;
  70. use Scalar::Util qw(looks_like_number);
  71. use Data::Dumper;
  72. # Forward-Declarations
  73. sub MEDIAPORTAL_Set($@);
  74. sub MEDIAPORTAL_Log($$$);
  75. my $MEDIAPORTAL_HeartbeatInterval = 15;
  76. my $MEDIAPORTAL_MaxGraceRetries = 3;
  77. ########################################################################################
  78. #
  79. # MEDIAPORTAL_Initialize
  80. #
  81. ########################################################################################
  82. sub MEDIAPORTAL_Initialize($) {
  83. my ($hash) = @_;
  84. require "$attr{global}{modpath}/FHEM/DevIo.pm";
  85. $hash->{ReadFn} = 'MEDIAPORTAL_Read';
  86. $hash->{ReadyFn} = 'MEDIAPORTAL_Ready';
  87. $hash->{GetFn} = 'MEDIAPORTAL_Get';
  88. $hash->{SetFn} = 'MEDIAPORTAL_Set';
  89. $hash->{DefFn} = 'MEDIAPORTAL_Define';
  90. $hash->{UndefFn} = 'MEDIAPORTAL_Undef';
  91. $hash->{AttrFn} = 'MEDIAPORTAL_Attribute';
  92. $hash->{AttrList} = 'authmethod:none,userpassword,passcode,both username password HeartbeatInterval generateNowPlayingUpdateEvents:1,0 PositionPercentFormat macaddress '.$readingFnAttributes;
  93. $hash->{STATE} = 'Initialized';
  94. }
  95. ########################################################################################
  96. #
  97. # MEDIAPORTAL_Define
  98. #
  99. ########################################################################################
  100. sub MEDIAPORTAL_Define($$) {
  101. my ($hash, $def) = @_;
  102. my @a = split("[ \t][ \t]*", $def);
  103. if(@a != 3) {
  104. my $msg = 'wrong syntax: define <name> MEDIAPORTAL ip[:port]';
  105. MEDIAPORTAL_Log $hash->{NAME}, 2, $msg;
  106. return $msg;
  107. }
  108. DevIo_CloseDev($hash);
  109. my $name = $a[0];
  110. my $dev = $a[2];
  111. $dev .= ":8017" if ($dev !~ m/:/ && $dev ne "none" && $dev !~ m/\@/);
  112. $hash->{DeviceName} = $dev;
  113. $hash->{STATE} = 'disconnected';
  114. my $ret = undef;
  115. $ret = DevIo_OpenDev($hash, 0, 'MEDIAPORTAL_DoInit') if (!AttrVal($hash->{NAME}, 'disable', 0));
  116. return $ret;
  117. }
  118. ########################################################################################
  119. #
  120. # MEDIAPORTAL_Undef
  121. #
  122. ########################################################################################
  123. sub MEDIAPORTAL_Undef($$) {
  124. my ($hash, $arg) = @_;
  125. RemoveInternalTimer($hash);
  126. DevIo_CloseDev($hash);
  127. return undef;
  128. }
  129. ########################################################################################
  130. #
  131. # MEDIAPORTAL_Attribute
  132. #
  133. ########################################################################################
  134. sub MEDIAPORTAL_Attribute($@) {
  135. my ($mode, $devName, $attrName, $attrValue) = @_;
  136. my $hash = $defs{$devName};
  137. my $disableChange = 0;
  138. if($mode eq 'set') {
  139. if ($attrName eq 'disable') {
  140. if ($attrValue && AttrVal($devName, $attrName, 0) != 1) {
  141. MEDIAPORTAL_Log($devName, 5, 'Neu-Disabled');
  142. $disableChange = 1;
  143. }
  144. if (!$attrValue && AttrVal($devName, $attrName, 0) != 0) {
  145. MEDIAPORTAL_Log($devName, 5, 'Neu-Enabled');
  146. $disableChange = 1;
  147. }
  148. }
  149. } elsif ($mode eq 'del') {
  150. if ($attrName eq 'disable') {
  151. if (AttrVal($devName, $attrName, 0) != 0) {
  152. MEDIAPORTAL_Log($devName, 5, 'Deleted-Disabled');
  153. $disableChange = 1;
  154. $attrValue = 0;
  155. }
  156. }
  157. }
  158. if ($disableChange) {
  159. # Wenn die Verbindung beendet werden muss...
  160. if ($attrValue) {
  161. MEDIAPORTAL_Log $devName, 5, 'Call AttributeFn: Stop Connection...';
  162. DevIo_CloseDev($hash);
  163. }
  164. # Wenn die Verbindung gestartet werden muss...
  165. if (!$attrValue) {
  166. MEDIAPORTAL_Log $devName, 5, 'Call AttributeFn: Start Connection...';
  167. DevIo_OpenDev($hash, 1, 'MEDIAPORTAL_DoInit');
  168. }
  169. }
  170. return undef;
  171. }
  172. ########################################################################################
  173. #
  174. # MEDIAPORTAL_DoInit
  175. #
  176. ########################################################################################
  177. sub MEDIAPORTAL_DoInit($) {
  178. my ($hash) = @_;
  179. readingsSingleUpdate($hash, 'state', 'Connecting...', 1);
  180. $hash->{helper}{buffer} = '';
  181. $hash->{helper}{LastStatusTimestamp} = time();
  182. $hash->{GraceRetries} = 0;
  183. # Versuch, die MAC-Adresse des Ziels selber herauszufinden...
  184. if (AttrVal($hash->{NAME}, 'macaddress', '') eq '') {
  185. my $newmac = MEDIAPORTAL_GetMAC($hash);
  186. if (defined($newmac)) {
  187. CommandAttr(undef, $hash->{NAME}.' macaddress '.$newmac);
  188. }
  189. }
  190. #RemoveInternalTimer($hash);
  191. #InternalTimer(gettimeofday() + AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval), 'MEDIAPORTAL_GetIntervalStatus', $hash, 0) if AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval);
  192. return undef;
  193. }
  194. ########################################################################################
  195. #
  196. # MEDIAPORTAL_Ready
  197. #
  198. ########################################################################################
  199. sub MEDIAPORTAL_Ready($) {
  200. my ($hash) = @_;
  201. MEDIAPORTAL_Log $hash->{NAME}, 4, "Ready-Call";
  202. return DevIo_OpenDev($hash, 1, 'MEDIAPORTAL_DoInit');
  203. }
  204. ########################################################################################
  205. #
  206. # MEDIAPORTAL_Get
  207. #
  208. ########################################################################################
  209. sub MEDIAPORTAL_Get($@) {
  210. my ($hash, @a) = @_;
  211. my $cname = $a[1];
  212. my $cmd = '';
  213. return 'Module disabled!' if AttrVal($hash->{NAME}, 'disable', 0);
  214. if ($cname eq "status") {
  215. $cmd = "{\"Type\":\"requeststatus\"}\r\n";
  216. } elsif ($cname eq "nowplaying") {
  217. $cmd = "{\"Type\":\"requestnowplaying\"}\r\n";
  218. } elsif ($cname eq "notify") {
  219. $cmd = '{"Type":"properties","Properties":["#Play.Current.Title","#TV.View.title"]}'."\r\n";
  220. } elsif ($cname eq "plugins") {
  221. $cmd = "{\"Type\":\"plugins\",\"SendIcons\":false}\r\n";
  222. } else {
  223. return "Unknown command '$cname', choose one of status:noArg nowplaying:noArg plugins:noArg";
  224. }
  225. DevIo_SimpleWrite($hash, $cmd, 0);
  226. return undef;
  227. }
  228. ########################################################################################
  229. #
  230. # MEDIAPORTAL_GetStatus
  231. #
  232. ########################################################################################
  233. sub MEDIAPORTAL_GetStatus($) {
  234. my ($hash) = @_;
  235. MEDIAPORTAL_Get($hash, ($hash->{NAME}, 'status'));
  236. }
  237. ########################################################################################
  238. #
  239. # MEDIAPORTAL_GetIntervalStatus
  240. #
  241. ########################################################################################
  242. sub MEDIAPORTAL_GetIntervalStatus($) {
  243. my ($hash) = @_;
  244. # Heartbeat-Prüfung nur machen, wenn es auch gewünscht wurde...
  245. return undef if (!AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval));
  246. # Ein "Disconnected" wird erst nach einigen Fehlversuchen hingenommen...
  247. if (ReadingsVal($hash->{NAME}, 'state', 'disconnected') eq 'disconnected') {
  248. $hash->{GraceRetries}++;
  249. return undef if ($hash->{GraceRetries} > $MEDIAPORTAL_MaxGraceRetries);
  250. # Reconnect veranlassen...
  251. MEDIAPORTAL_Set($hash, ($hash->{NAME}, 'reconnect'));
  252. InternalTimer(gettimeofday() + AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval), 'MEDIAPORTAL_GetIntervalStatus', $hash, 0);
  253. }
  254. # Prüfen, wann der letzte Status zugestellt wurde...
  255. if (time() - $hash->{helper}{LastStatusTimestamp} > (2 * $MEDIAPORTAL_HeartbeatInterval + 5)) {
  256. MEDIAPORTAL_Log $hash->{NAME}, 3, 'GetIntervalStatus hat festgestellt, dass Mediaportal sich seit '.(time() - $hash->{helper}{LastStatusTimestamp}).'s nicht zurückgemeldet hat. Die Verbindung wird neu aufgebaut!';
  257. MEDIAPORTAL_Set($hash, ($hash->{NAME}, 'reconnect'));
  258. InternalTimer(gettimeofday() + AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval), 'MEDIAPORTAL_GetIntervalStatus', $hash, 0);
  259. return undef;
  260. }
  261. # Status anfordern...
  262. MEDIAPORTAL_Get($hash, ($hash->{NAME}, 'status'));
  263. InternalTimer(gettimeofday() + AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval), 'MEDIAPORTAL_GetIntervalStatus', $hash, 0);
  264. }
  265. ########################################################################################
  266. #
  267. # MEDIAPORTAL_GetNowPlaying
  268. #
  269. ########################################################################################
  270. sub MEDIAPORTAL_GetNowPlaying($) {
  271. my ($hash) = @_;
  272. MEDIAPORTAL_Get($hash, ($hash->{NAME}, 'nowplaying'));
  273. }
  274. ########################################################################################
  275. #
  276. # MEDIAPORTAL_GetPlugins
  277. #
  278. ########################################################################################
  279. sub MEDIAPORTAL_GetPlugins($) {
  280. my ($hash) = @_;
  281. MEDIAPORTAL_Get($hash, ($hash->{NAME}, 'plugins'));
  282. }
  283. ########################################################################################
  284. #
  285. # MEDIAPORTAL_Set
  286. #
  287. ########################################################################################
  288. sub MEDIAPORTAL_Set($@) {
  289. my ($hash, @a) = @_;
  290. my $cname = $a[1];
  291. my $cmd = '';
  292. my $powermodes = 'logoff suspend hibernate reboot shutdown exit';
  293. my $mpcommands = 'stop record pause play rewind forward replay skip back info menu up down left right ok volup voldown volmute chup chdown dvdmenu 0 1 2 3 4 5 6 7 8 9 0 clear enter teletext red blue yellow green home basichome nowplaying tvguide tvrecs dvd playlists first last fullscreen subtitles audiotrack screenshot';
  294. my $playlistcommands = 'play loadlist loadlist_shuffle loadfrompath loadfrompath_shuffle';
  295. # Legacy Volume writing...
  296. $cname = 'Volume' if (lc($cname) eq 'volume');
  297. return 'Module disabled!' if AttrVal($hash->{NAME}, 'disable', 0);
  298. if ($cname eq "command") {
  299. if (!MEDIAPORTAL_isInList($a[2], split(/ /, $mpcommands))) {
  300. return "Unknown command '$a[2]'. Supported commands are: $mpcommands";
  301. }
  302. $cmd = "{\"Type\":\"command\",\"Command\":\"$a[2]\"}\r\n";
  303. } elsif ($cname eq "wakeup") {
  304. my $macaddress = AttrVal($hash->{NAME}, 'macaddress', '');
  305. if ($macaddress ne '') {
  306. MEDIAPORTAL_Wakeup($macaddress);
  307. $hash->{GraceRetries} = 0;
  308. #MEDIAPORTAL_Set($hash, ($hash->{NAME}, 'reconnect'));
  309. #InternalTimer(gettimeofday() + AttrVal($hash->{NAME}, 'HeartbeatInterval', $MEDIAPORTAL_HeartbeatInterval), 'MEDIAPORTAL_GetIntervalStatus', $hash, 0);
  310. return 'WakeUp-Signal sent!';
  311. } else {
  312. return 'No MacAddress set! No WakeUp-Signal sent!';
  313. }
  314. } elsif ($cname eq "sleep") {
  315. return MEDIAPORTAL_Set($hash, ($hash->{NAME}, 'powermode', 'hibernate'));
  316. } elsif ($cname eq "key") {
  317. $cmd = "{\"Type\":\"key\",\"Key\":\"$a[2]\"}\r\n";
  318. } elsif ($cname eq "Volume") {
  319. if (($a[2] ne $a[2]+0) || ($a[2]<0) || ($a[2]>100)) {
  320. return "the volume must be in the range 0..100";
  321. }
  322. $cmd = "{\"Type\":\"volume\",\"Volume\":$a[2]}\r\n";
  323. } elsif ($cname eq "powermode") {
  324. if (!MEDIAPORTAL_isInList($a[2], split(/ /, $powermodes))) {
  325. return "Unknown powermode '$a[2]'. Supported powermodes are: $powermodes";
  326. }
  327. $cmd = "{\"Type\":\"powermode\",\"PowerMode\":\"$a[2]\"}\r\n";
  328. } elsif ($cname eq "playfile") {
  329. $cmd = "{\"Type\":\"playfile\",\"FileType\":\"$a[2]\",\"Filepath\":\"$a[3]\"}\r\n";
  330. } elsif ($cname eq "playchannel") {
  331. if ($a[2] ne $a[2]+0) {
  332. return "playchannel needs a valid channelid of type int";
  333. }
  334. $cmd = "{\"Type\":\"playchannel\",\"ChannelId\":$a[2]}\r\n";
  335. } elsif ($cname eq "playradiochannel") {
  336. if ($a[2] ne $a[2]+0) {
  337. return "playradiochannel needs a valid channelid of type int";
  338. }
  339. $cmd = "{\"Type\":\"playradiochannel\",\"ChannelId\":$a[2]}\r\n";
  340. } elsif ($cname eq "playlist") {
  341. if (!MEDIAPORTAL_isInList($a[2], split(/ /, $playlistcommands))) {
  342. return "Unknown playlist command '$a[2]'. Supported commands are: $playlistcommands";
  343. }
  344. if ($a[2] eq "play") {
  345. if ($a[3] ne $a[3]+0) {
  346. return "playlist play needs a valid index to start of type int";
  347. }
  348. $cmd = "{\"Type\":\"playlist\",\"PlaylistAction\":\"play\",\"Index\":$a[3]}\r\n";
  349. } elsif ($a[2] eq "loadlist") {
  350. $cmd = "{\"Type\":\"playlist\",\"PlaylistAction\":\"load\",\"PlaylistName\":\"$a[3]\"}\r\n";
  351. } elsif ($a[2] eq "loadlist_shuffle") {
  352. $cmd = "{\"Type\":\"playlist\",\"PlaylistAction\":\"load\",\"PlaylistName\":\"$a[3]\",\"Shuffle\":true}\r\n";
  353. } elsif ($a[2] eq "loadfrompath") {
  354. $cmd = "{\"Type\":\"playlist\",\"PlaylistAction\":\"load\",\"PlaylistPath\":\"$a[3]\"}\r\n";
  355. } elsif ($a[2] eq "loadfrompath_shuffle") {
  356. $cmd = "{\"Type\":\"playlist\",\"PlaylistAction\":\"load\",\"PlaylistPath\":\"$a[3]\",\"Shuffle\":true}\r\n";
  357. }
  358. } elsif ($cname eq "connect") {
  359. $hash->{NEXT_OPEN} = 0; # force NEXT_OPEN used in DevIO
  360. return undef;
  361. } elsif ($cname eq "reconnect") {
  362. DevIo_CloseDev($hash);
  363. select(undef, undef, undef, 0.2);
  364. DevIo_OpenDev($hash, 1, 'MEDIAPORTAL_DoInit');
  365. return undef;
  366. } elsif ($cname eq "window") {
  367. my $param = $a[2];
  368. if (!looks_like_number($param)) {
  369. my %plugins = %{eval(ReadingsVal($hash->{NAME}, 'Plugins', '()'))};
  370. $param =~ s/\%20/ /g;
  371. $param = $plugins{$param};
  372. }
  373. $cmd = "{\"Type\":\"window\",\"Window\":$param}\r\n";
  374. } else {
  375. my %plugins = ();
  376. eval {
  377. %plugins = %{eval(ReadingsVal($hash->{NAME}, 'Plugins', '()'))};
  378. };
  379. return "Unknown command '$cname', choose one of wakeup:noArg sleep:noArg connect:noArg reconnect:noArg command:".join(',', split(/ /, $mpcommands))." key Volume:slider,0,1,100 powermode:".join(',', split(/ /, $powermodes))." playfile playchannel playradiochannel playlist window".((scalar(keys(%plugins)) != 0) ? ':'.join(',', map { s/ /%20/g; $_; } sort(keys(%plugins))) : '');
  380. }
  381. DevIo_SimpleWrite($hash, $cmd, 0);
  382. return undef;
  383. }
  384. ########################################################################################
  385. #
  386. # MEDIAPORTAL_Read
  387. # Receives an event and creates several readings for event triggering
  388. #
  389. ########################################################################################
  390. sub MEDIAPORTAL_Read($) {
  391. my ($hash) = @_;
  392. my $buf = DevIo_SimpleRead($hash);
  393. if(!defined($buf)) {
  394. MEDIAPORTAL_Log $hash->{NAME}, 3, 'DevIo_SimpleRead hat keine Daten geliefert, obwohl Read aufgerufen wurde! Setze Buffer und einige Readings zurück. Aktueller Buffer: '.$hash->{helper}{buffer};
  395. $hash->{helper}{buffer} = '';
  396. return undef;
  397. }
  398. return undef if AttrVal($hash->{NAME}, 'disable', 0);
  399. $hash->{GraceRetries} = 0;
  400. MEDIAPORTAL_Log $hash->{NAME}, 5, "RAW MSG: $buf";
  401. # Zum Buffer hinzufügen
  402. $hash->{helper}{buffer} .= $buf;
  403. # Bereits vollständige JSON-Strings verarbeiten...
  404. my @groups = $hash->{helper}{buffer} =~ m/({(?:[^{}]++|(?1))*})/xg;
  405. for my $elem (@groups) {
  406. MEDIAPORTAL_ProcessMessage($hash, $elem);
  407. }
  408. # Bereits verarbeitetes aus dem Buffer wieder entfernen...
  409. $hash->{helper}{buffer} =~ s/[ \r\n]*({(?:[^{}]++|(?1))*})[ \r\n]*//xg;
  410. return undef;
  411. }
  412. ########################################################################################
  413. #
  414. # MEDIAPORTAL_ProcessMessage
  415. #
  416. ########################################################################################
  417. sub MEDIAPORTAL_ProcessMessage($$) {
  418. my ($hash, $msg) = @_;
  419. MEDIAPORTAL_Log $hash->{NAME}, 5, "Message received: $msg";
  420. my $json = {};
  421. eval {
  422. $json = from_json($msg);
  423. };
  424. if ($@) {
  425. MEDIAPORTAL_Log $hash->{NAME}, 5, "Error during JSON-Parser with 'from_json()'-call (but just keep trying another way): $@";
  426. eval {
  427. $json = decode_json(decode('iso8859-1', $msg));
  428. };
  429. if ($@) {
  430. MEDIAPORTAL_Log $hash->{NAME}, 1, "Final Error during JSON-Parser: $@";
  431. return;
  432. }
  433. }
  434. if (defined($json->{Type})) {
  435. if ($json->{Type} eq "welcome") {
  436. MEDIAPORTAL_Log $hash->{NAME}, 4, 'WELCOME received. Sending identify message.';
  437. DevIo_SimpleWrite($hash, MEDIAPORTAL_GetMSG_identify($hash), 0);
  438. } elsif ($json->{Type} eq "authenticationresponse") {
  439. MEDIAPORTAL_Log $hash->{NAME}, 4, "AUTHRESPONSE received. SUCCESS=$json->{Success}";
  440. #readingsSingleUpdate($hash, 'state', 'Authenticated. Processing messages.', 1);
  441. readingsSingleUpdate($hash, 'state', 'opened', 1);
  442. InternalTimer(gettimeofday() + 1, 'MEDIAPORTAL_GetPlugins', $hash, 0);
  443. } elsif ($json->{Type} eq "status") {
  444. MEDIAPORTAL_Log $hash->{NAME}, 4, 'STATUS received.';
  445. my $playStatus = 'Stopped';
  446. $playStatus = 'Playing' if ($json->{IsPlaying});
  447. $playStatus = 'Paused' if ($json->{IsPaused});
  448. my $title = '';
  449. $title = $json->{Title} if (defined($json->{Title}) && $json->{Title});
  450. if (defined($json->{SelectedItem}) && $json->{SelectedItem} ne '' && $title eq '') {
  451. $title = 'Auswahl: '.$json->{SelectedItem};
  452. # Wenn der Titel während des Abspielens nicht mitgeliefert wurde, dann für später nochmal anfordern...
  453. # Das ist ein Bug in Wifiremote, das den Titel beim Start nicht immer mitliefert.
  454. if ($json->{IsPlaying}) {
  455. InternalTimer(gettimeofday() + 5, 'MEDIAPORTAL_GetNowPlaying', $hash, 0);
  456. }
  457. }
  458. readingsBeginUpdate($hash);
  459. readingsBulkUpdate($hash, 'IsPlaying', $json->{IsPlaying});
  460. readingsBulkUpdate($hash, 'IsPaused', $json->{IsPaused});
  461. readingsBulkUpdate($hash, 'playStatus', $playStatus);
  462. readingsBulkUpdate($hash, 'CurrentModule', $json->{CurrentModule});
  463. readingsBulkUpdate($hash, 'Title', $title);
  464. # Wenn der Abspielstatus auf Stopped gewechselt hat, dann einige Readings löschen...
  465. if ($json->{IsPlaying} eq 'false' && $json->{IsPaused} eq 'false') {
  466. readingsBulkUpdate($hash, 'Title', '');
  467. readingsBulkUpdate($hash, 'Description', '');
  468. readingsBulkUpdate($hash, 'nextTitle', '');
  469. readingsBulkUpdate($hash, 'nextDescription', '');
  470. readingsBulkUpdate($hash, 'mediaType', '');
  471. readingsBulkUpdate($hash, 'tvChannel', '');
  472. readingsBulkUpdate($hash, 'tvCurrentProgramName', '');
  473. readingsBulkUpdate($hash, 'tvNextProgramName', '');
  474. readingsBulkUpdate($hash, 'movieTitle', '');
  475. readingsBulkUpdate($hash, 'seriesName', '');
  476. readingsBulkUpdate($hash, 'seriesSeason', '');
  477. readingsBulkUpdate($hash, 'seriesEpisode', '');
  478. readingsBulkUpdate($hash, 'seriesTitle', '');
  479. readingsBulkUpdate($hash, 'recordingChannel', '');
  480. readingsBulkUpdate($hash, 'recordingProgramName', '');
  481. readingsBulkUpdate($hash, 'Position', '0:00:00');
  482. readingsBulkUpdate($hash, 'PositionPercent', 0);
  483. readingsBulkUpdate($hash, 'File', '');
  484. readingsBulkUpdate($hash, 'Duration', '0:00:00');
  485. }
  486. readingsEndUpdate($hash, 1);
  487. $hash->{helper}{LastStatusTitle} = $title;
  488. $hash->{helper}{LastStatusTimestamp} = time();
  489. } elsif ($json->{Type} eq "volume") {
  490. MEDIAPORTAL_Log $hash->{NAME}, 4, 'VOLUME received.';
  491. readingsBeginUpdate($hash);
  492. readingsBulkUpdate($hash, 'Volume', $json->{Volume});
  493. readingsBulkUpdate($hash, 'IsMuted', $json->{IsMuted});
  494. readingsEndUpdate($hash, 1);
  495. } elsif ($json->{Type} eq "nowplaying") {
  496. MEDIAPORTAL_Log $hash->{NAME}, 4, 'NOWPLAYING received.';
  497. readingsBeginUpdate($hash);
  498. readingsBulkUpdate($hash, 'Duration', MEDIAPORTAL_ConvertSecondsToTime($json->{Duration}));
  499. readingsBulkUpdate($hash, 'Position', MEDIAPORTAL_ConvertSecondsToTime($json->{Position}));
  500. if ($json->{Duration}) {
  501. readingsBulkUpdate($hash, 'PositionPercent', sprintf(AttrVal($hash->{NAME}, 'PositionPercentFormat', '%.1f'), 100 * $json->{Position} / $json->{Duration}));
  502. } else {
  503. readingsBulkUpdate($hash, 'PositionPercent', 0);
  504. }
  505. readingsBulkUpdate($hash, 'File', $json->{File});
  506. readingsBulkUpdate($hash, 'Title', '');
  507. readingsBulkUpdate($hash, 'Description', '');
  508. readingsBulkUpdate($hash, 'nextTitle', '');
  509. readingsBulkUpdate($hash, 'nextDescription', '');
  510. # Special MediaInformations...
  511. if ($json->{IsTv}) {
  512. readingsBulkUpdate($hash, 'mediaType', 'tv');
  513. } else {
  514. readingsBulkUpdate($hash, 'mediaType', '');
  515. }
  516. readingsBulkUpdate($hash, 'tvChannel', '');
  517. readingsBulkUpdate($hash, 'tvCurrentProgramName', '');
  518. readingsBulkUpdate($hash, 'tvNextProgramName', '');
  519. readingsBulkUpdate($hash, 'movieTitle', '');
  520. readingsBulkUpdate($hash, 'seriesName', '');
  521. readingsBulkUpdate($hash, 'seriesSeason', '');
  522. readingsBulkUpdate($hash, 'seriesEpisode', '');
  523. readingsBulkUpdate($hash, 'seriesTitle', '');
  524. readingsBulkUpdate($hash, 'recordingChannel', '');
  525. readingsBulkUpdate($hash, 'recordingProgramName', '');
  526. if (defined($json->{MediaInfo})) {
  527. readingsBulkUpdate($hash, 'mediaType', $json->{MediaInfo}{MediaType}) if ($json->{MediaInfo}{MediaType});
  528. if ($json->{MediaInfo}{MediaType} eq 'tv') {
  529. readingsBulkUpdate($hash, 'Title', $json->{MediaInfo}{ChannelName}.' - '.$json->{MediaInfo}{CurrentProgramName});
  530. readingsBulkUpdate($hash, 'Description', $json->{MediaInfo}{CurrentProgramDescription});
  531. readingsBulkUpdate($hash, 'tvChannel', $json->{MediaInfo}{ChannelName});
  532. readingsBulkUpdate($hash, 'tvCurrentProgramName', $json->{MediaInfo}{CurrentProgramName});
  533. if (defined($json->{MediaInfo}{NextProgramName})) {
  534. readingsBulkUpdate($hash, 'nextTitle', $json->{MediaInfo}{ChannelName}.' - '.$json->{MediaInfo}{NextProgramName});
  535. readingsBulkUpdate($hash, 'nextDescription', $json->{MediaInfo}{NextProgramDescription});
  536. readingsBulkUpdate($hash, 'tvNextProgramName', $json->{MediaInfo}{NextProgramName});
  537. }
  538. } elsif ($json->{MediaInfo}{MediaType} eq 'movie') {
  539. readingsBulkUpdate($hash, 'Title', $json->{MediaInfo}{Title});
  540. readingsBulkUpdate($hash, 'Description', $json->{MediaInfo}{Summary});
  541. readingsBulkUpdate($hash, 'movieTitle', $json->{MediaInfo}{Title});
  542. } elsif ($json->{MediaInfo}{MediaType} eq 'series') {
  543. readingsBulkUpdate($hash, 'Title', $json->{MediaInfo}{Series}.' S'.sprintf("%02d", $json->{MediaInfo}{Season}).'E'.sprintf("%02d", $json->{MediaInfo}{Episode}).' - '.$json->{MediaInfo}{Title});
  544. readingsBulkUpdate($hash, 'Description', $json->{MediaInfo}{Plot});
  545. readingsBulkUpdate($hash, 'seriesName', $json->{MediaInfo}{Series});
  546. readingsBulkUpdate($hash, 'seriesSeason', $json->{MediaInfo}{Season});
  547. readingsBulkUpdate($hash, 'seriesEpisode', $json->{MediaInfo}{Episode});
  548. readingsBulkUpdate($hash, 'seriesTitle', $json->{MediaInfo}{Title});
  549. } elsif ($json->{MediaInfo}{MediaType} eq 'recording') {
  550. readingsBulkUpdate($hash, 'Title', $json->{MediaInfo}{ChannelName}.' - '.$json->{MediaInfo}{ProgramName});
  551. readingsBulkUpdate($hash, 'Description', $json->{MediaInfo}{ProgramDescription});
  552. readingsBulkUpdate($hash, 'recordingChannel', $json->{MediaInfo}{ChannelName});
  553. readingsBulkUpdate($hash, 'recordingProgramName', $json->{MediaInfo}{ProgramName});
  554. } else {
  555. MEDIAPORTAL_Log $hash->{NAME}, 0, 'Unbekannte MediaInfo für "'.$json->{MediaInfo}{MediaType}.'" geliefert, aber nicht verarbeitet. Bitte diese komplette Information ins Forum einstellen: '.Dumper($json->{MediaInfo});
  556. }
  557. } else {
  558. # Die MediaInfos wurden nicht mitgeliefert...
  559. # Hier nochmal versuchen, den Titel zu extrahieren...
  560. my $title = '';
  561. $title = $json->{Title} if (defined($json->{Title}) && $json->{Title});
  562. if ($title eq '') {
  563. readingsBulkUpdate($hash, 'Title', $hash->{helper}{LastStatusTitle});
  564. } else {
  565. readingsBulkUpdate($hash, 'Title', $title);
  566. }
  567. }
  568. readingsEndUpdate($hash, 1);
  569. } elsif ($json->{Type} eq "nowplayingupdate") {
  570. MEDIAPORTAL_Log $hash->{NAME}, 4, 'NOWPLAYINGUPDATE received.';
  571. readingsBeginUpdate($hash);
  572. readingsBulkUpdate($hash, 'Duration', MEDIAPORTAL_ConvertSecondsToTime($json->{Duration}));
  573. readingsBulkUpdate($hash, 'Position', MEDIAPORTAL_ConvertSecondsToTime($json->{Position}));
  574. if ($json->{Duration}) {
  575. readingsBulkUpdate($hash, 'PositionPercent', sprintf(AttrVal($hash->{NAME}, 'PositionPercentFormat', '%.1f'), 100 * $json->{Position} / $json->{Duration}));
  576. } else {
  577. readingsBulkUpdate($hash, 'PositionPercent', 0);
  578. }
  579. readingsEndUpdate($hash, AttrVal($hash->{NAME}, 'generateNowPlayingUpdateEvents', 0));
  580. } elsif ($json->{Type} eq "properties") {
  581. MEDIAPORTAL_Log $hash->{NAME}, 4, 'PROPERTIES received.';
  582. MEDIAPORTAL_Log undef, 4, 'JSON: '.Dumper($json);
  583. } elsif ($json->{Type} eq "facadeinfo") {
  584. MEDIAPORTAL_Log $hash->{NAME}, 4, 'FACADEINFO received.';
  585. } elsif ($json->{Type} eq "dialog") {
  586. MEDIAPORTAL_Log $hash->{NAME}, 4, 'DIALOG received.';
  587. } elsif ($json->{Type} eq "plugins") {
  588. MEDIAPORTAL_Log $hash->{NAME}, 1, 'Plugins received.';
  589. eval {
  590. my %plugins = ();
  591. foreach (@{$json->{Plugins}}) {
  592. $plugins{$_->{Name}} = $_->{WindowId};
  593. }
  594. readingsSingleUpdate($hash, 'Plugins', MEDIAPORTAL_Dumper(\%plugins), 1);
  595. };
  596. if ($@) {
  597. MEDIAPORTAL_Log $hash->{NAME}, 1, "Error during processing of plugins: $@";
  598. }
  599. } else {
  600. MEDIAPORTAL_Log $hash->{NAME}, 1, "Unhandled message received: MessageType '$json->{Type}'";
  601. }
  602. } else {
  603. MEDIAPORTAL_Log $hash->{NAME}, 1, 'Unhandled message received without any Messagetype: '.$msg;
  604. }
  605. }
  606. ########################################################################################
  607. #
  608. # MEDIAPORTAL_GetMSG_identify
  609. #
  610. ########################################################################################
  611. sub MEDIAPORTAL_GetMSG_identify($) {
  612. my ($hash) = @_;
  613. my $authmethod=AttrVal($hash->{NAME}, 'authmethod', 'none');
  614. my $uid = AttrVal($hash->{NAME}, 'username', '');
  615. my $pwd = AttrVal($hash->{NAME}, 'password', '');
  616. my $cmd = {
  617. Type => 'identify',
  618. Name => 'MP_Connector',
  619. Application => 'FHEM',
  620. Version => '1.0'
  621. };
  622. if ($authmethod ne "none") {
  623. $cmd->{Authenticate}{AuthMethod} = $authmethod;
  624. $cmd->{Authenticate}{User} = $uid;
  625. $cmd->{Authenticate}{Password} = $pwd;
  626. }
  627. my $strcmd = encode_json($cmd)."\r\n";
  628. return $strcmd;
  629. }
  630. ########################################################################################
  631. #
  632. # MEDIAPORTAL_GetMAC
  633. #
  634. ########################################################################################
  635. sub MEDIAPORTAL_GetMAC($) {
  636. my ($hash) = @_;
  637. my $mac = undef;
  638. eval {
  639. my ($host, $port) = split(/:/, $hash->{DeviceName});
  640. my $result = qx/arp -a $host/;
  641. MEDIAPORTAL_Log undef, 5, 'ARP-SysCall: '.$result;
  642. $mac = uc($1) if ($result =~ m/([0-9a-fA-F]{2}(:|-)[0-9a-fA-F]{2}(:|-)[0-9a-fA-F]{2}(:|-)[0-9a-fA-F]{2}(:|-)[0-9a-fA-F]{2}(:|-)[0-9a-fA-F]{2})/s);
  643. $mac =~ s/-/:/g if (defined($mac)); # Korrektur für Windows-Rechner
  644. if (defined($mac)) {
  645. MEDIAPORTAL_Log undef, 5, 'Found Mac: '.$mac;
  646. } else {
  647. MEDIAPORTAL_Log undef, 5, 'No Mac Found!';
  648. }
  649. };
  650. if ($@) {
  651. return undef;
  652. }
  653. return undef if (defined($mac) && ($mac eq '00:00:00:00:00:00')); # Unter Windows wird im Fehlerfall diese Adresse zurückgegeben.
  654. return $mac;
  655. }
  656. ########################################################################################
  657. #
  658. # MEDIAPORTAL_Wakeup
  659. #
  660. ########################################################################################
  661. sub MEDIAPORTAL_Wakeup($;$$) {
  662. my ($hwaddr, $ipaddr, $port) = @_;
  663. $ipaddr = '255.255.255.255' if (!defined($ipaddr));
  664. $port = getservbyname('discard', 'udp') if (!defined($port));
  665. # Zur Sicherheit zweimal senden...
  666. return MEDIAPORTAL_DoWakeup($hwaddr, $ipaddr, $port) || MEDIAPORTAL_DoWakeup($hwaddr, $ipaddr, $port);
  667. }
  668. ########################################################################################
  669. #
  670. # MEDIAPORTAL_DoWakeup
  671. #
  672. ########################################################################################
  673. sub MEDIAPORTAL_DoWakeup($;$$) {
  674. my ($hwaddr, $ipaddr, $port) = @_;
  675. $ipaddr = '255.255.255.255' if (!defined($ipaddr));
  676. $port = getservbyname('discard', 'udp') if (!defined($port));
  677. # Validate hardware address (ethernet address)
  678. my $hwaddr_re = join(':', ('[0-9A-Fa-f]{1,2}') x 6);
  679. if ($hwaddr !~ m/^$hwaddr_re$/) {
  680. warn "Invalid hardware address: $hwaddr\n";
  681. return undef;
  682. }
  683. # Generate magic sequence
  684. my $pkt = '';
  685. foreach (split /:/, $hwaddr) {
  686. $pkt .= chr(hex($_));
  687. }
  688. $pkt = chr(0xFF) x 6 . $pkt x 16;
  689. # Allocate socket and send packet
  690. my $raddr = gethostbyname($ipaddr);
  691. my $them = pack_sockaddr_in($port, $raddr);
  692. my $proto = getprotobyname('udp');
  693. socket(S, AF_INET, SOCK_DGRAM, $proto) or die "socket : $!";
  694. setsockopt(S, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
  695. send(S, $pkt, 0, $them) or die "send : $!";
  696. close S;
  697. return 1;
  698. }
  699. ########################################################################################
  700. #
  701. # MEDIAPORTAL_GetTimeSeconds
  702. #
  703. ########################################################################################
  704. sub MEDIAPORTAL_GetTimeSeconds($) {
  705. my ($timeStr) = @_;
  706. return MEDIAPORTAL_Max(int($1)*3600 + int($2)*60 + int($3), 1) if ($timeStr =~ m/(\d+):(\d+):(\d+)/);
  707. return 0;
  708. }
  709. ########################################################################################
  710. #
  711. # MEDIAPORTAL_ConvertSecondsToTime
  712. #
  713. ########################################################################################
  714. sub MEDIAPORTAL_ConvertSecondsToTime($) {
  715. my ($seconds) = @_;
  716. return sprintf('%01d:%02d:%02d', $seconds / 3600, ($seconds%3600) / 60, $seconds%60) if ($seconds > 0);
  717. return '0:00:00';
  718. }
  719. ########################################################################################
  720. #
  721. # MEDIAPORTAL_Max
  722. #
  723. ########################################################################################
  724. sub MEDIAPORTAL_Max($$) {
  725. $_[$_[0] < $_[1]]
  726. }
  727. ########################################################################################
  728. #
  729. # MEDIAPORTAL_isInList
  730. #
  731. ########################################################################################
  732. sub MEDIAPORTAL_isInList($@) {
  733. my($search, @list) = @_;
  734. return 1 if MEDIAPORTAL_posInList($search, @list) >= 0;
  735. return 0;
  736. }
  737. ########################################################################################
  738. #
  739. # MEDIAPORTAL_posInList
  740. #
  741. ########################################################################################
  742. sub MEDIAPORTAL_posInList($@) {
  743. my($search, @list) = @_;
  744. for (my $i = 0; $i <= $#list; $i++) {
  745. return $i if ($list[$i] && $search eq $list[$i]);
  746. }
  747. return -1;
  748. }
  749. ########################################################################################
  750. #
  751. # MEDIAPORTAL_Dumper - Returns the 'Dumpered' Output of the given Datastructure-Reference
  752. #
  753. ########################################################################################
  754. sub MEDIAPORTAL_Dumper($) {
  755. my ($varRef) = @_;
  756. $Data::Dumper::Indent = 0;
  757. my $text = Dumper($varRef);
  758. $Data::Dumper::Indent = 2;
  759. return $text;
  760. }
  761. ########################################################################################
  762. #
  763. # MEDIAPORTAL_Log - Log to the normal Log-command with the prefix 'MEDIAPORTAL'
  764. #
  765. ########################################################################################
  766. sub MEDIAPORTAL_Log($$$) {
  767. my ($devicename, $level, $text) = @_;
  768. Log3 $devicename, $level, 'MEDIAPORTAL: '.$text;
  769. }
  770. 1;
  771. =pod
  772. =item summary Connects to a running MediaPortal instance via the WifiRemote plugin.
  773. =item summary_DE Verbindet sich über das Wifiremote-Plugin mit einer Mediaportal-Instanz.
  774. =begin html
  775. <a name="MEDIAPORTAL"></a>
  776. <h3>MEDIAPORTAL</h3>
  777. <p>Connects to a running MediaPortal instance via the WifiRemote plugin</p>
  778. <h4>Example</h4>
  779. <p>
  780. <code>define wohnzimmer_Mediaportal MEDIAPORTAL 192.168.0.47:8017</code>
  781. </p>
  782. <a name="MEDIAPORTALdefine"></a>
  783. <h4>Define</h4>
  784. <b><code>define &lt;name&gt; MEDIAPORTAL host[:port]</code></b>
  785. <br /><br /> Define a Mediaportal interface to communicate with a Wifiremote-Plugin of a Mediaportal-System.<br />
  786. <p>
  787. <b><code>host[:port]</code></b><br />The name and port of the Mediaportal-Wifiremote-Plugin. If Port is not given, the default of <code>8017</code> will be used.</p>
  788. <a name="MEDIAPORTALset"></a>
  789. <h4>Set</h4>
  790. <ul>
  791. <li><b>Common Tasks</b><ul>
  792. <li><a name="MEDIAPORTAL_setter_connect">
  793. <b><code>connect</code></b></a>
  794. <br />Connects to Mediaportal immediately without waiting for the normal Fhem-Timeout for reconnect (30s).</li>
  795. <li><a name="MEDIAPORTAL_setter_powermode">
  796. <b><code>powermode &lt;mode&gt;</code></b></a>
  797. <br />One of (logoff, suspend, hibernate, reboot, shutdown, exit). Sets the powermode, e.g. shutdown, for shutdown the computersystem of the Mediaportal-System.</li>
  798. <li><a name="MEDIAPORTAL_setter_reconnect">
  799. <b><code>reconnect</code></b></a>
  800. <br />Re-Connects to Mediaportal immediately.</li>
  801. </ul></li>
  802. <li><b>Control-Commands</b><ul>
  803. <li><a name="MEDIAPORTAL_setter_command">
  804. <b><code>command &lt;command&gt;</code></b></a>
  805. <br />One of (stop, record, pause, play, rewind, forward, replay, skip, back, info, menu, up, down, left, right, ok, volup, voldown, volmute, chup, chdown, dvdmenu, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, clear, enter, teletext, red, blue, yellow, green, home, basichome, nowplaying, tvguide, tvrecs, dvd, playlists, first, last, fullscreen, subtitles, audiotrack, screenshot). Sends the given command to the player.</li>
  806. <li><a name="MEDIAPORTAL_setter_key">
  807. <b><code>key &lt;keyvalue&gt;</code></b></a>
  808. <br />Sends the given key to the player.</li>
  809. <li><a name="MEDIAPORTAL_setter_sleep">
  810. <b><code>sleep</code></b></a>
  811. <br />Sends the hinernate-signal to Mediaportal. This command is a shortcut for "powermode hibernate"</li>
  812. <li><a name="MEDIAPORTAL_setter_wakeup">
  813. <b><code>wakeup</code></b></a>
  814. <br />Wakes the Mediaportal-System up (WakeUp-On-LAN).</li>
  815. </ul></li>
  816. <li><b>Play-Commands</b><ul>
  817. <li><a name="MEDIAPORTAL_setter_playchannel">
  818. <b><code>playchannel &lt;channelID&gt;</code></b></a>
  819. <br />Plays the channel with the given ID.</li>
  820. <li><a name="MEDIAPORTAL_setter_playfile">
  821. <b><code>playfile &lt;fileType&gt; &lt;filePath&gt;</code></b></a>
  822. <br />Plays the given file with the given type. FileType can be one of (audio, video).</li>
  823. <li><a name="MEDIAPORTAL_setter_playlist">
  824. <b><code>playlist &lt;command&gt; &lt;param&gt;</code></b></a>
  825. <br />Sends the given playlistcommand with the given parameter. Command can be one of (play, loadlist, loadlist_shuffle, loadfrompath, loadfrompath_shuffle).</li>
  826. <li><a name="MEDIAPORTAL_setter_Volume">
  827. <b><code>Volume &lt;volumelevel&gt;</code></b></a>
  828. <br />Sets the Volume to the given value.</li>
  829. </ul></li>
  830. </ul>
  831. <a name="MEDIAPORTALget"></a>
  832. <h4>Get</h4>
  833. <ul>
  834. <li><b>Common Tasks</b><ul>
  835. <li><a name="MEDIAPORTAL_getter_status">
  836. <b><code>status</code></b></a>
  837. <br />Call for the answer of a <code>status</code>-Message. e.g. Asynchronously retrieves the information of "Title" and "PlayStatus".</li>
  838. <li><a name="MEDIAPORTAL_getter_nowplaying">
  839. <b><code>nowplaying</code></b></a>
  840. <br />Call for the answer of a <code>nowplaying</code>-Message. e.g. Asynchronously retrieves the information of "Duration", "Position" and "File"".</li>
  841. </ul></li>
  842. </ul>
  843. <a name="MEDIAPORTALattr"></a>
  844. <h4>Attributes</h4>
  845. <ul>
  846. <li><b>Common</b><ul>
  847. <li><a name="MEDIAPORTAL_attribut_disable"><b><code>disable &lt;value&gt;</code></b>
  848. </a><br />One of (0, 1). With this attribute you can disable the module.</li>
  849. <li><a name="MEDIAPORTAL_attribut_generateNowPlayingUpdateEvents"><b><code>generateNowPlayingUpdateEvents &lt;value&gt;</code></b>
  850. </a><br />One of (0, 1). With this value you can disable (or enable) the generation of <code>NowPlayingUpdate</code>-Events. If set, Fhem generates an event per second with the updated time-values for the current playing. Defaults to "0".</li>
  851. <li><a name="MEDIAPORTAL_attribut_HeartbeatInterval"><b><code>HeartbeatInterval &lt;interval&gt;</code></b>
  852. </a><br />In seconds. Defines the heartbeat interval in seconds which is used for testing the correct work of the connection to Mediaportal. A value of 0 deactivate the heartbeat-check. Defaults to "15".</li>
  853. <li><a name="MEDIAPORTAL_attribut_macaddress"><b><code>macaddress &lt;address&gt;</code></b>
  854. </a><br />Sets the MAC-Address for the Player. This is needed for WakeUp-Function. e.g. "90:E6:BA:C2:96:15"</li>
  855. </ul></li>
  856. <li><b>Authentication</b><ul>
  857. <li><a name="MEDIAPORTAL_attribut_authmethod"><b><code>authmethod &lt;value&gt;</code></b>
  858. </a><br />One of (none, userpassword, passcode, both). With this value you can set the authentication-mode.</li>
  859. <li><a name="MEDIAPORTAL_attribut_password"><b><code>password &lt;value&gt;</code></b>
  860. </a><br />With this value you can set the password for authentication.</li>
  861. <li><a name="MEDIAPORTAL_attribut_username"><b><code>username &lt;value&gt;</code></b>
  862. </a><br />With this value you can set the username for authentication.</li>
  863. </ul></li>
  864. </ul>
  865. =end html
  866. =begin html_DE
  867. <a name="MEDIAPORTAL"></a>
  868. <h3>MEDIAPORTAL</h3>
  869. <p>Verbindet sich über das Wifiremote-Plugin mit einer laufenden Mediaportal-Instanz.</p>
  870. <h4>Beispiel</h4>
  871. <p>
  872. <code>define wohnzimmer_Mediaportal MEDIAPORTAL 192.168.0.47:8017</code>
  873. </p>
  874. <a name="MEDIAPORTALdefine"></a>
  875. <h4>Define</h4>
  876. <b><code>define &lt;name&gt; MEDIAPORTAL host[:port]</code></b>
  877. <br /><br />Definiert ein Mediaportal Interface für die Kommunikation mit einem Wifiremote-Plugin einer Mediaportal Installation.<br />
  878. <p>
  879. <b><code>host[:port]</code></b><br />Der Hostname und der Port eines laufenden Mediaportal-Wifiremote-Plugins. Wenn der Port nicht angegeben wurde, wird <code>8017</code> als Standard verwendet.</p>
  880. <a name="MEDIAPORTALset"></a>
  881. <h4>Set</h4>
  882. <ul>
  883. <li><b>Grundsätzliches</b><ul>
  884. <li><a name="MEDIAPORTAL_setter_connect">
  885. <b><code>connect</code></b></a>
  886. <br />Erzwingt eine sofortige Verbindung zu Mediaportal. Normalerweise würde die normale Verbindungswiederholung von Fhem (30s) abgewartet werden. </li>
  887. <li><a name="MEDIAPORTAL_setter_powermode">
  888. <b><code>powermode &lt;mode&gt;</code></b></a>
  889. <br />Eins aus (logoff, suspend, hibernate, reboot, shutdown, exit). Setzt den powermode, z.B. shutdown, zum Herunterfahren des Computers des Mediaportal-Systems.</li>
  890. <li><a name="MEDIAPORTAL_setter_reconnect">
  891. <b><code>reconnect</code></b></a>
  892. <br />Erzwingt eine sofortige Trennung und Neuverbindung zu Mediaportal.</li>
  893. </ul></li>
  894. <li><b>Control-Befehle</b><ul>
  895. <li><a name="MEDIAPORTAL_setter_command">
  896. <b><code>command &lt;command&gt;</code></b></a>
  897. <br />Eins aus (stop, record, pause, play, rewind, forward, replay, skip, back, info, menu, up, down, left, right, ok, volup, voldown, volmute, chup, chdown, dvdmenu, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, clear, enter, teletext, red, blue, yellow, green, home, basichome, nowplaying, tvguide, tvrecs, dvd, playlists, first, last, fullscreen, subtitles, audiotrack, screenshot). Sendet das entsprechende Kommando an den Player.</li>
  898. <li><a name="MEDIAPORTAL_setter_key">
  899. <b><code>key &lt;keyvalue&gt;</code></b></a>
  900. <br />Sendet die entsprechende Taste an den Player.</li>
  901. <li><a name="MEDIAPORTAL_setter_sleep">
  902. <b><code>sleep</code></b></a>
  903. <br />Startet den Hibernate-Modus. Dieser Befehl ist ein Shortcut für "powermode hibernate"</li>
  904. <li><a name="MEDIAPORTAL_setter_wakeup">
  905. <b><code>wakeup</code></b></a>
  906. <br />Weckt den Mediaportal-Rechner auf (WakeUp-On-LAN).</li>
  907. </ul></li>
  908. <li><b>Abspielbefehle</b><ul>
  909. <li><a name="MEDIAPORTAL_setter_playchannel">
  910. <b><code>playchannel &lt;channelID&gt;</code></b></a>
  911. <br />Spielt den Kanal mit der entsprechenden ID ab.</li>
  912. <li><a name="MEDIAPORTAL_setter_playfile">
  913. <b><code>playfile &lt;fileType&gt; &lt;filePath&gt;</code></b></a>
  914. <br />Spielt die entsprechende Datei mit dem angegebenen Typ ab. FileType kann (audio, video) sein.</li>
  915. <li><a name="MEDIAPORTAL_setter_playlist">
  916. <b><code>playlist &lt;command&gt; &lt;param&gt;</code></b></a>
  917. <br />Sendet das entsprechende Playlist-Kommando mit dem gegebenen Parameter. Das Kommando kann (play, loadlist, loadlist_shuffle, loadfrompath, loadfrompath_shuffle) sein.</li>
  918. <li><a name="MEDIAPORTAL_setter_Volume">
  919. <b><code>Volume &lt;volumelevel&gt;</code></b></a>
  920. <br />Setzt die angegebene Lautstärke.</li>
  921. </ul></li>
  922. </ul>
  923. <a name="MEDIAPORTALget"></a>
  924. <h4>Get</h4>
  925. <ul>
  926. <li><b>Grundsätzliches</b><ul>
  927. <li><a name="MEDIAPORTAL_getter_status">
  928. <b><code>status</code></b></a>
  929. <br />Sendet eine Aufforderung für das Senden einer <code>status</code>-Nachricht. Liefert dann asynchron die Informationen "Title" und "PlayStatus".</li>
  930. <li><a name="MEDIAPORTAL_getter_nowplaying">
  931. <b><code>nowplaying</code></b></a>
  932. <br />Sendet eine Aufforderung für das Senden einer <code>nowplaying</code>-Nachricht. Liefert dann asynchron die Informationen "Duration", "Position" und "File"".</li>
  933. </ul></li>
  934. </ul>
  935. <a name="MEDIAPORTALattr"></a>
  936. <h4>Attribute</h4>
  937. <ul>
  938. <li><b>Grundsätzliches</b><ul>
  939. <li><a name="MEDIAPORTAL_attribut_disable"><b><code>disable &lt;value&gt;</code></b>
  940. </a><br />Eins aus (0, 1). Mit diesem Attribut kann das Modul deaktiviert werden.</li>
  941. <li><a name="MEDIAPORTAL_attribut_generateNowPlayingUpdateEvents"><b><code>generateNowPlayingUpdateEvents &lt;value&gt;</code></b>
  942. </a><br />Eins aus (0, 1). Mit diesem Attribut kann die Erzeugung eines <code>NowPlayingUpdate</code>-Events an- oder abgeschaltet werden. Wenn auf "1" gesetzt, generiert Fhem ein Event pro Sekunde mit den angepassten Zeitangaben. Standard ist "0".</li>
  943. <li><a name="MEDIAPORTAL_attribut_HeartbeatInterval"><b><code>HeartbeatInterval &lt;intervall&gt;</code></b>
  944. </a><br />In Sekunden. Legt das Intervall für die Prüfung der Verbindung zu Mediaportal fest. Mit "0" kann die Prüfung deaktiviert werden. Wenn kein Wert angeggeben wird, wird "15" verwendet.</li>
  945. <li><a name="MEDIAPORTAL_attribut_macaddress"><b><code>macaddress &lt;address&gt;</code></b>
  946. </a><br />Gibt die Mac-Adresse des Mediaportal-Rechners an. Das wird für die WakeUp-Funktionalität benötigt. z.B. "90:E6:BA:C2:96:15"</li>
  947. </ul></li>
  948. <li><b>Authentifizierung</b><ul>
  949. <li><a name="MEDIAPORTAL_attribut_authmethod"><b><code>authmethod &lt;value&gt;</code></b>
  950. </a><br />Eins aus (none, userpassword, passcode, both). Hiermit wird der Authentifizierungsmodus festgelegt.</li>
  951. <li><a name="MEDIAPORTAL_attribut_password"><b><code>password &lt;value&gt;</code></b>
  952. </a><br />Hiermit wird das Passwort für die Authentifzierung festgelegt.</li>
  953. <li><a name="MEDIAPORTAL_attribut_username"><b><code>username &lt;value&gt;</code></b>
  954. </a><br />Hiermit wird der Benutzername für die Authentifizerung festgelegt.</li>
  955. </ul></li>
  956. </ul>
  957. =end html_DE
  958. =cut