openHAB: Aktuelle Radio-Nachrichten auf Knopfdruck am Beispiel Deutschlandfunk

Kennt ihr das? Man wäre gern am aktuellen Stand der Dinge, aber genau dann, wenn man das Radio einschaltet, sind die Nachrichten gerade vorbei.

Daher habe ich mein openHAB befähigt, die neuesten Nachrichten – im Beispiel vom Sender Deutschlandfunk – automatisch zu beziehen und auf meinem Raspberry Pi 3 mit HifiBerry AMP+ abzuspielen. Über diese Kombination habe ich hier ja eh schon gebloggt und seit längerer Zeit dient mir diese Kombi als ideales Webradio, als Klingelanlage, Ansage, wer anruft usw.

Zusätzlich greife ich auf mein streampi-Script zurück, welches ich bereits in diesem Blogartikel genau beschrieben habe.

Allerdings erweitern wir es nun,es erhält ein Plugin-System und ein Plugin für Deutschlandfunk, welches automatisch den neuesten Podcast an die Abspielstation übergibt.

1. Schritt: streampi erweitern um Pluginsystem.

Vielleicht gibt es ja noch weitere Möglickeiten der Erweiterung in der Zukunft und alles in die streampi.php zu packen, fände ich da eher ungeschickt. Daher erweitern wir die streampi.php so, dass diese auf einen Parameter „plugin“ hört und wenn dieser übergeben wurde, dann prüft es, ob in einem Unterordner Namens „plugins“ eine Datei mit dem Pluginnamen und der Endung „.php“ liegt. Ist dem so, wird die geladen und eine feste Methode wird ausgeführt, welche ggf. bestimmte Variablen zurückliefert, die dann in streampi weiterverwendet werden können. So werden die file, volumen, prio, … Parameter durch das Plugin belegbar:

<?php

// Some configuration
$ttsScript = '/usr/bin/php ' . realpath(dirname(__FILE__)) . '/includes/tts.php';
$volumeFile = 'streampi.volume';
$amixer = '/usr/bin/amixer';
$mpv = '/usr/bin/mpv --really-quiet ';
$dbFile = 'streampi.db';
$pluginFolder = 'plugins';
$telUrl = 'http://localhost/fritzpi/lookup.php?nr=';

// Handle input
$prio = (int) $_REQUEST['prio'];
$file = $_REQUEST['file'];
$base64 = (int) $_REQUEST['base64'];
$type = strtolower($_REQUEST['type']);
$plugin = $_REQUEST['plugin'];
$text = $_REQUEST['text'];
$tel = $_REQUEST['tel']; // addon for fritz box. replaces %NR% with looked up number that is passed via "tel" parameter
if (isset($tel) && (strlen($tel) > 0)) {
 $name = file_get_contents($telUrl . $tel);
 $text = str_replace('NUMMER', $name, $text);
}

// Handle plugins
if (isset($plugin) && file_exists($pluginFolder . '/' . $plugin . '.php')) {
 include_once($pluginFolder . '/' . $plugin . '.php');
 $pluginResult = getPluginParams();
 $params = array('prio', 'file', 'base64', 'type', 'text', 'tel');
 foreach ($params as $param) {
 if (isset($pluginResult[$param])) {
 $file = $pluginResult [$param];
 }
 }
}

// If URL is passed as filename maybe it was base64decoded.
if ($base64 == 1) {
 $file = base64_decode($file);
}
if (!in_array($type, array('stream', 'stop', 'volume', 'tts'))) {
 $type = 'mp3';
}
if ($type == 'volume') {
 $volume = (int) $_REQUEST['value'];
 if ($volume < 0) {
 $volume = 0;
 } else if ($volums > 200) {
 $volume = 200;
 }
 file_put_contents($volumeFile, $volume);
 setVolume($volume);
} else {
 // TTS service called? Then we will handle this request first
 if ($type == 'tts') {
 if ($text != '') {
 $command = $ttsScript . ' ' . str_replace('ß', 'ss', $text);
 $ttsFile = shell_exec($command);
 // now we will proceed as if the tts file was given via parameter
 $file = $ttsFile;
 $type = 'mp3';
 } else {
 exit;
 }
 } else if ($type == 'stream') {
 // streams have always prio 999 (lowest priority)
 $prio = 999;
 }
 // Check if mpv is running already
 $mpvRunning = (substr_count(shell_exec('ps aux | grep mpv'), "\n") > 2);

// Get Database
 $db = getDB();

// Stop playing if necessary
 if ($type == 'stop') {
 exec('killall mpv');
 $db = array();
 storeDB($db);
 $mpvRunning = false;
 } else if ($file != '') {
 // playing already? cancel, if stream is played, and play then, otherwise queue
 $key = (str_pad($prio, 3, 0, STR_PAD_LEFT) . ( 32483067507 - time() ));
 $playItem = array(
 'file' => $file,
 'type' => $type,
 'prio' => $prio,
 'volume' => (int) $_REQUEST['volume'],
 'key' => $key
 );
 if ((($mpvRunning) && ($db['last']['type'] == 'stream')) || !$mpvRunning) {
 if ($mpvRunning) {
 exec('killall mpv');
 $lastItem = $db['last'];
 $db['queue'][$lastItem['key']] = $lastItem;
 }
 $db['last'] = $playItem;
 $mpvRunning = false;
 }
 // add to Queue. Play Method does sorting later...
 $db['queue'][$playItem['key']] = $playItem;
 storeDB($db);
 if (!$mpvRunning) {
 playNext();
 }
 }
}

function storeDB($db) {
 global $dbFile;
 file_put_contents($dbFile, serialize($db));
}

function getDB() {
 global $dbFile;
 $dbSource = unserialize(file_get_contents($dbFile));
 if (!is_array($dbSource)) {
 $db = array('last' => array(), 'queue' => array());
 } else {
 return $dbSource;
 }
 return $db;
}

function playNext() {
 global $mpv;
 $db = getDB();
 $queue = $db['queue'];
 // sort queue
 ksort($queue);
 $playItem = array_shift($queue);
 if ($playItem['key'] != '') {
 // Set volume level
 if ($playItem['volume'] > 0) {
 setVolume($playItem['volume']);
 } else {
 setVolume(getVolume(false));
 }
 // Modify database
 $db = array(
 'last' => $playItem,
 'queue' => $queue
 );
 storeDB($db);
 // stream? play in background!
 if ($playItem['type'] == 'stream') {
 exec($mpv . ' ' . $playItem['file'] . ' > /dev/null 2>/dev/null &');
 } else {
 exec($mpv . ' ' . $playItem['file']);
 playNext();
 }
 }
}

function getVolume($fromFileOnly = false) {
 global $volumeFile;
 if (isset($_REQUEST['volume']) && $fromFileOnly) {
 $volume = $_REQUEST['volume'];
 } else {
 $volume = file_get_contents($volumeFile);
 }
 if (!($volume >= 0) && !($volume <= 200)) {
 $volume = 100;
 }
 return $volume;
}

function setVolume($value) {
 global $amixer;
 $cmd = $amixer . ' sset Master ' . $value . ' unmute';
 exec($cmd);
}

2. Schritt: Deutschlandfunk-Plugin

Das Plugin schnappt sich die URL vom Radiosender und holt darauf den aktuellsten Eintrag, also die neuesten Nachrichten. Die URL wird als file-Parameter zurückgegeben:

Datei: „plugins/news-dlf-php“

<?php
/**
 * Dieses Plugin lädt die aktuellsten Nachrichten des Radiosenders
 * Deutschlandfunk und setzt entsprechende Parameter so, dass diese 
 * abgespielt werden
 * 
 * Betroffene Parameter: $file
 * 
 * @return array
 */

function getPluginParams() {
 // Podcast-Stream vom Deutschlandfunk
 $url = 'http://www.deutschlandfunk.de/podcast-nachrichten.1257.de.podcast.xml';

// letzter Podcast auswerten, URL des MP3 extrahieren
 $xml = new SimpleXMLElement(file_get_contents($url));
 $file = $xml->channel->item[0]->link;
 return array('file' => (string) $file);
}

Ein Test ist möglich, indem das Streampi-PHP-Script einfach im Browser aufgerufen wird: http://<SERVER>/streampi.php?plugin=news-dlf

Weitere Parameter wie volume usw. natürlich möglich. Die mp3-Datei wird dann an das Abspielprogramm übergeben und abgespielt. Die Nachrichten sind zu hören.

3. Schritt: Einbindung in openHAB User-Interface

Zuletzt wollen wir das ja irgendwie triggern können. D.h. wir brauchen ein openhab-Item, das dann den Aufruf des Streampi-Skriptes mit dem entsprechendem Plugin triggered:

Items-Datei:

Switch webradioNachrichten "Nachrichten anhören" <switch>

Rules-Datei:

Variable TTS_URL entweder mit streampi-URL belegen oder direkt entsprechend austauschen.

rule "Nachrichten abspielen"
when Item webradioNachrichten changed from OFF to ON
then
 logInfo('rules','Nachrichten abspielen')
 sendHttpPostRequest(TTS_URL,'application/x-www-form-urlencoded','&prio=2&volume=80&plugin=news-dlf')
end

Sitemap-Datei:

An entsprechender Stelle in Sitemap einfügen

 Switch item=webradioNachrichten

4. Schritt: Nachrichten hören per Knopfdruck

Nun muss man nur noch in der Oberfläche von openHAB den Schalter drücken und die Nachrichten werden am Player abgespielt.

Eine Antwort auf „openHAB: Aktuelle Radio-Nachrichten auf Knopfdruck am Beispiel Deutschlandfunk“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.