Projekt: PlayBox per RFID, MQTT, FHEM und Spotify
Du kennst eventuell diese kleinen Lautsprecher für Kinder, auf welche Figuren aufgesteckt werden können und dann die damit verknüpfte Musik oder das Hörbuch abgespielt wird. Genau soetwas wollte ich gerne super günstig nachbauen. Ziel ist es, dass man RFID-Tags in Figuren versteckt, diese dann auf eine Box stellt und dann über Spotify die Geschichte dazu abspielt. Quelle der Audio-Dateien ist dabei ganz einfach Spotify. Dort gibt es unendlich viele Inhalte von Benjamin Blümchen bis Bibi Blocksberg. Als Ausgabegerät kann zum Beispiel ein Amazon Echo dienen. Angesteuert und verwaltet wird alles über FHEM.
Was Du brauchst?
- Eine FHEM-Installation (inkl. Spotify-Integration) + MQTT-Broker
- Eine NodeMCU
- Einen RFID-Reader und ein paar Tags
- Am besten einen 3D-Drucker
Video
Produkte
Schaltplan
»PlayBox«
Befehle und Code
Die NodeMCU musst Du mit dem folgenden Programm bespielen. Vorher natürlich ein paar Punkte anpassen:
- WLAN SSID und Passwort
- MQTT Host, Benutzer und Passwort
- ggf. MQTT-Topics
der Rest sollte genau so funktionieren. Natürlich brauchst Du diese beiden Libraries damit alles baut:
#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define SS_PIN D8
#define RST_PIN D1
MFRC522 mfrc522(SS_PIN, RST_PIN);
unsigned long cardId = 0;
WiFiClient net;
PubSubClient client(net);
const char* mqtt_server = "192.168.44.11";
const char* ssid = "...";
const char* password = "...";
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
client.setServer(mqtt_server, 1883);
}
void reconnect() {
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
WiFi.begin(ssid, password);
}
while (!client.connected()) {
String clientId = "NodeMCUClient-";
clientId += String(random(0xffff), HEX);
if (!client.connect(clientId.c_str(), "sonoff", "...")) {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void loop() {
reconnect();
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
cardId = getCardId();
Serial.print("New ");
Serial.println(cardId);
char buffer[10];
sprintf(buffer, "%lu", cardId);
client.publish("/SmartHome/Interface/PlayBox/Play", buffer);
uint8_t control = 0x00;
do {
control = 0;
for (int i = 0; i < 3; i++) {
if (!mfrc522.PICC_IsNewCardPresent()) {
if (mfrc522.PICC_ReadCardSerial()) {
control |= 0x16;
}
if (mfrc522.PICC_ReadCardSerial()) {
control |= 0x16;
}
control += 0x1;
}
control += 0x4;
}
delay(0);
} while (control == 13 || control == 14);
reconnect();
Serial.println("Removed");
client.publish("/SmartHome/Interface/PlayBox/Stop", "1");
delay(500);
mfrc522.PICC_HaltA();
mfrc522.PCD_StopCrypto1();
}
unsigned long getCardId() {
byte readCard[4];
for (int i = 0; i < 4; i++) {
readCard[i] = mfrc522.uid.uidByte[i];
}
return (unsigned long)readCard[0] << 24
| (unsigned long)readCard[1] << 16
| (unsigned long)readCard[2] << 8
| (unsigned long)readCard[3];
}
Weiter geht es in FHEM. Als erstes das Gerät, welches uns die Topics aus MQTT zu Readings macht.
define PlayBox MQTT_DEVICE
attr PlayBox userattr subscribeReading_play subscribeReading_stop
attr PlayBox IODev Mosquitto
attr PlayBox event-on-update-reading play,stop
attr PlayBox icon rc_VOLUP
attr PlayBox stateFormat play
attr PlayBox subscribeReading_play /SmartHome/Interface/PlayBox/Play
attr PlayBox subscribeReading_stop /SmartHome/Interface/PlayBox/Stop
Jetzt fehlt nur noch die Logik zum Abspielen und Pausieren. Wie immer: Erst das Gerät anlegen ohne Logik, dann auf DEF klicken und den Perl-Code einfügen.
define n_PlayBox notify PlayBox:play:.* {}
PlayBox:play:.* {
my $spotifyTrack = ReadingsVal($NAME, 'card_' . $EVTPART1, 'undef');
if ($spotifyTrack ne 'undef') {
my $lastPlayedTrackURI = ReadingsVal($NAME, 'lastPlayedTrackURI', 'unknown');
if ($lastPlayedTrackURI eq $spotifyTrack && ReadingsVal('Spotify', 'track_uri', '-') eq $lastPlayedTrackURI) {
fhem("set Spotify resume");
} else {
fhem("set Spotify playTrackByURI " . $spotifyTrack);
fhem("setreading $NAME lastPlayedTrackURI " . $spotifyTrack);
}
} else {
fhem("setreading $NAME card_$EVTPART1 undef");
# Nachricht, dass Song nicht gefunden
}
}
Für Pause genau das gleiche:
defmod n_PlayBox_Stop notify PlayBox:stop:.* {}
PlayBox:stop:.* {
fhem("set Spotify pause");
}
Danach die erste Karte auflegen. Dadurch wird ein Reading mit dem Namen card_XXXXXXXXX angelegt. Dieses wird nun ein Spotify-Track zugewiesen. Dazu einfach mit setreading direkt in fhem arbeiten.
setreading PlayBox card_XXXXXXXXX spotify:track:2QAdBcz5MeMal98m13bsTg
So dann mit allen Karten verfahren und fertig.
Nun entweder die Tags in Figuren packen, oder nur auf die Karten schreiben / drucken was genau gespielt wird. Da sind der Kreativität keine Grenzen gesetzt.