Die folgende Anleitung beschreibt den Umbau eines alten Küchenradios in einen vollwertigen /wiki/spaces/LOXBERRY/pages/1191313649 für das Logitech Media Center. Verwendet werden die Lautsprecher des alten Radios sowie die Bedienelemente. Für einen guten WAF (Woman Acceptance Faktor) kann der Client über 6 Taster und einen Drehimpulsgeber vor Ort ohne App, Handy, etc. bedient werden. Über den Drehimpulsgeber wird die Lautstärke geregelt, die 6 Taster dienen zur Belegung mit Radiosender-Favoriten und zum Ausschalten. Je nach Ausstattung eures Radios kann man selbstverständlich mehr oder weniger Tasten verwenden oder auch nachträglich Taster und/oder Drehimpulsgeber hinzufügen. Die Belegung der Taster erfolgt rein softwareseitig und kann natürlich dem eigenen Bedarf angepasst werden.
...
Ihr müsst unbedingt darauf achten, dass ihr die GPIOs bzw. PINs nicht verwendet, die der HifiBerry selbst belegt. Weitere Informationen findet ihr hier: https://www.hifiberry.com/docs/hardware/gpio-usage-of-hifiberry-boards/ Beim HiFiBerry MiniAMP sind das: GPIO 16, 18-21 und 26 (PINs 36, 12, 35, 38, 40 und 37). Die Belegung des Headers findet ihr in der Raspberry Dokumentation: https://www.raspberrypi.org/documentation/usage/gpio/
Zunächst steckt man den Stacking Header auf den RaspPi und biegt sich die PINs, die man als GPIO verwenden möchte, nach außen. Daran kann man dann die Jumperkabel seitlich anschließen. So kann man die Taster und den Drehimpulsgeber anschließen und gleichzeitig später den HiFiBerry MiniAMP ebenfalls auf den Header stecken.
Ich benutze die folgenden GPIOs:
- GPIO 17 (PIN 11): Drehimpulsgeber
- GPIO 27 (PIN 13): Drehimpulsgeber
- GPIO 23 (PIN 16): Button 1
- GPIO 24 (PIN 18): Button 2
- GPIO 25 (PIN 22): Button 3
- GPIO 8 (PIN 24): Button 4
- GPIO 7 (PIN 26): Button 5
- GPIO 6 (PIN 31): Button 6
- PIN 20: Ground
- PIN 17: +3.3V
Installation
Das Pythoskript zur Abfrage der Taster und es Drehimpulsgebers könnt ihr hier herunterladen: https://github.com/mschlenstedt/squeezelite_radiotasten
Damit das Skript auf meinem Raspi läuft, müssen zunächst noch die Development-Librarys der Distribution installiert werden:
apt-get install python3-dev
Anschließend müssen ich über pip noch folgende Pakete nachinstallieren:
pip install setuptools
pip install wheel
pip install RPi.GPIO
Das eigentliche Skript zur Abfrage der Taster kann irgendwo im Filesystem installiert werden. Auf dem LoxBerry bietet sich das Verzeichnis /opt/loxberry/bin/plugins/legacy/radiotasten
an. Das wird bei einem update nicht überschrieben.
Alle Einstellungen erfolgen am Anfang des Skriptes. Die Einstellungen sollten selbsterklärend sein.
Codeblock | ||||||
---|---|---|---|---|---|---|
| ||||||
#!/usr/bin/env python2
import RPi.GPIO as GPIO
from encoder import Encoder
import time
import os
#
# Einstellungen
#
# GPIO-Bezeichnungien (BCM) im Skript verwenden
GPIO.setmode(GPIO.BCM)
# LMS Einstellungen
# Player, de rmit den Tasten gesteuert werden soll
player = "02:a7:37:bc:bd:1d"
# Host Deines Logitech Media Server (oder IP-Adresse)
server = "192.168.3.213"
# Port asm LMS für CLI KOmmandos
port = "9000"
# GPIO-Pins Drehimpulsgeber - gemeinsamer PIN auf +3.3V
in_a = 17
in_b = 27
# GPIO-Pins Pushbutton - wahlweise gegen GND oder +3.3V
in_c = 23
in_d = 24
in_e = 25
in_f = 8
in_g = 7
in_h = 6
# LMS Kommandos Drehimpulsgeber
# Links: Vol -5%
cmd_a = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"mixer\",\"volume\",\"+5\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Rechts: Vol +5%
cmd_b = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"mixer\",\"volume\",\"-5\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# LMS Kommandos Pushbuttons
# Play Favorit 1
cmd_c = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"favorites\",\"playlist\",\"play\",\"item_id:0\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Play Favorit 2
cmd_d = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"favorites\",\"playlist\",\"play\",\"item_id:2\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Play Favorit 3
cmd_e = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"favorites\",\"playlist\",\"play\",\"item_id:1\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Play Favorit 4
cmd_f = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"favorites\",\"playlist\",\"play\",\"item_id:9\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Play Favorit 5
cmd_g = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"favorites\",\"playlist\",\"play\",\"item_id:8\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Stop
cmd_h = "curl -s -H \"Content-Type: application/json\" -X POST -d '{\"id\":1,\"method\":\"slim.request\",\"params\":[\"" + player + "\", [\"mode\",\"stop\"]]}' http://" + server + ":" + port + "/jsonrpc.js"
# Pullup-/Pulldown-Widerstand einschalten
# Bei Verschaltung gegen GND: GPIO.PUD_UP
# Bei Verschaltung gegen +3.3V: GPIO.PUD_DOWN
pullupdown_in_c = GPIO.PUD_UP
pullupdown_in_d = GPIO.PUD_UP
pullupdown_in_e = GPIO.PUD_UP
pullupdown_in_f = GPIO.PUD_UP
pullupdown_in_g = GPIO.PUD_UP
pullupdown_in_h = GPIO.PUD_UP
# Bounce-Zeit in ms
bouncetime = 250
#
# Einstellungen Ende
#
# GPIO Settings
GPIO.setup(in_c, GPIO.IN, pull_up_down = pullupdown_in_c)
GPIO.setup(in_d, GPIO.IN, pull_up_down = pullupdown_in_d)
GPIO.setup(in_e, GPIO.IN, pull_up_down = pullupdown_in_e)
GPIO.setup(in_f, GPIO.IN, pull_up_down = pullupdown_in_f)
GPIO.setup(in_g, GPIO.IN, pull_up_down = pullupdown_in_g)
GPIO.setup(in_h, GPIO.IN, pull_up_down = pullupdown_in_h)
if pullupdown_in_c == GPIO.PUD_UP:
edge_in_c = GPIO.FALLING
else:
edge_in_c = GPIO.RISING
if pullupdown_in_d == GPIO.PUD_UP:
edge_in_d = GPIO.FALLING
else:
edge_in_d = GPIO.RISING
if pullupdown_in_e == GPIO.PUD_UP:
edge_in_e = GPIO.FALLING
else:
edge_in_e = GPIO.RISING
if pullupdown_in_f == GPIO.PUD_UP:
edge_in_f = GPIO.FALLING
else:
edge_in_f = GPIO.RISING
if pullupdown_in_g == GPIO.PUD_UP:
edge_in_g = GPIO.FALLING
else:
edge_in_g = GPIO.RISING
if pullupdown_in_h == GPIO.PUD_UP:
edge_in_h = GPIO.FALLING
else:
edge_in_h = GPIO.RISING
# Drehimpulsgeber
oldvalue = 0
def DIG1(value):
global oldvalue
if value > oldvalue:
print str(value) + " -> Richtung ist rechts. Sende: "
os.system(cmd_a)
print ""
if value < oldvalue:
print str(value) + " -> Richtung ist links. Sende: "
os.system(cmd_b)
print ""
oldvalue = value
# Button 1
def Button1(channel):
print "Button 1 aktiviert. Sende:"
os.system(cmd_c)
print ""
# Button 2
def Button2(channel):
print "Button 2 aktiviert. Sende:"
os.system(cmd_d)
print ""
# Button 3
def Button3(channel):
print "Button 3 aktiviert. Sende:"
os.system(cmd_e)
print ""
# Button 4
def Button4(channel):
print "Button 4 aktiviert. Sende:"
os.system(cmd_f)
print ""
# Button 5
def Button5(channel):
print "Button 5 aktiviert. Sende:"
os.system(cmd_g)
print ""
# Button 6
def Button6(channel):
print "Button 6 aktiviert. Sende:"
os.system(cmd_h)
print ""
# Interrupts
e1 = Encoder(in_a, in_b, callback = DIG1)
GPIO.add_event_detect(in_c, edge_in_c, callback = Button1, bouncetime = bouncetime)
GPIO.add_event_detect(in_d, edge_in_d, callback = Button2, bouncetime = bouncetime)
GPIO.add_event_detect(in_e, edge_in_e, callback = Button3, bouncetime = bouncetime)
GPIO.add_event_detect(in_f, edge_in_f, callback = Button4, bouncetime = bouncetime)
GPIO.add_event_detect(in_g, edge_in_g, callback = Button5, bouncetime = bouncetime)
GPIO.add_event_detect(in_h, edge_in_h, callback = Button6, bouncetime = bouncetime)
# Schleife
try:
while True:
time.sleep(1)
except:
GPIO.cleanup()
print "\nBye" |
Ein kleines "Watchdog" Skript überwacht, ob das eigentliche Pythonskript noch läuft und startet es bei einem Problem gegebenenfalls neu.
Codeblock | ||||||
---|---|---|---|---|---|---|
| ||||||
#!/bin/bash
pgrep -f radiotasten.py >/dev/null 2>&1
if [[ $? -eq 1 ]]
then
./radiotasten.py &
else
echo "Skript läuft noch"
fi |
Das Watchdog-Skript startet man regelmäßig per Cron (z. B. alle 5 Minuten). Dazu legt man auf dem Loxberry eine neue crontab unter /opt/loxberry/system/cron/cron.d/radiotasten an. Der Inhalt muss wie folgt aussehen:
Codeblock | ||||
---|---|---|---|---|
| ||||
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=""
#
# m h dom mon dow user command
*/5 * * * * loxberry cd / && /opt/loxberry/bin/plugins/radiotasten/watchdog.sh >/dev/null 2>&1 |
Das war's auch schon. Ab sofort kannst Du Dein WLAN-Radio über die Tasten und natürlich auch direkt als vollwertigen Netzwerk-Player steuern.