Record player is going to be re-printed at a higher quality.
Put a printed image on the player, and it plays the album
Move the arm, and the next track will be played
Press upper white button, and the music will pause/resume
Press lower button … ??? Don’t know yet
Updated python client (see previous posts)
import paho.mqtt.client as mqtt
import urllib.request
from time import sleep
def on_connect(client, userdata, flags, rc): # The callback for when the client connects to the broker
print("Connected with result code {0}".format(str(rc)))
client.subscribe("spotify/rfid/idlms")
client.subscribe("spotify/rfid/but1")
client.subscribe("spotify/rfid/but2")
client.subscribe("spotify/rfid/arm")
def on_message(client, userdata, msg): # The callback for when a PUBLISH message is received from the server.
print("Message received-> " + msg.topic + " " + str(msg.payload)) # Print a received msg
if msg.topic == "spotify/rfid/idlms":
urllib.request.urlopen("http://LMS-SERVER-IP:9000/anyurl?p0=playlistcontrol&p1=album_id:" + msg.payload.decode() + "&p2=cmd:load&player=00:04:20:16:d9:04")
if msg.topic == "spotify/rfid/but1":
urllib.request.urlopen("http://LMS-SERVER-IP:9000/anyurl?p0=pause&player=00:04:20:16:d9:04")
sleep(1)
if msg.topic == "spotify/rfid/but2":
urllib.request.urlopen("http://LMS-SERVER-IP:9000/anyurl?p0=pause&pt=1&player=00:04:20:16:d9:04")
sleep(1)
if msg.topic == "spotify/rfid/arm":
urllib.request.urlopen("http://LMS-SERVER-IP:9000/status.html?p0=button&p1=jump_fwd&player=00:04:20:16:d9:04")
sleep(1)
client = mqtt.Client("lmsclient") # Create instance of client with client ID “digi_mqtt_test”
client.on_connect = on_connect # Define callback function for successful connection
client.on_message = on_message # Define callback function for receipt of a message
client.connect('MQTTSERVER', 1883)
client.loop_forever() # Start daemon
Wemos INO file
#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define SS_PIN 15
#define RST_PIN 0
const int buttonPin1 = D1;
const int buttonPin2 = D2;
int buttonState1 = 0;
int buttonState2 = 0;
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::StatusCode status; //variable to get card status
byte buffer[18]; //data transfer buffer (16+2 bytes data+CRC)
byte size = sizeof(buffer);
uint8_t pageAddr = 0x06; //In this example we will write/read 16 bytes (page 6,7,8 and 9).
//Ultraligth mem = 16 pages. 4 bytes per page.
//Pages 0 to 4 are for special functions.
unsigned long cardId = 0;
WiFiClient net;
PubSubClient client(net);
const char* mqtt_server = "MQTTBROKER";
const char* ssid = "MYSSID";
const char* password = "MYWIFIPASWORD";
String topicStr = "";
byte buffer2[8];
boolean Rflag=false;
int r_len;
char payload[5];
byte value[5];
void setup() {
Serial.begin(9600);
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(buttonPin2, INPUT_PULLUP );
SPI.begin();
mfrc522.PCD_Init();
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
client.setServer(mqtt_server, 1883);
delay(100);
client.setCallback(callback);
delay(100);
client.subscribe("spotify/rfid/in/#");
}
void reconnect() {
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
}
while (!client.connected()) {
String clientId = "rfid-";
clientId += String(random(0xffff), HEX);
if (!client.connect(clientId.c_str(), "rfidclient", "...")) {
delay(5000);
}
}
client.subscribe("spotify/rfid/in/#");
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print(F("Called"));
Rflag=true; //will use in main loop
r_len=length; //will use in main loop
int j=0;
for (j;j<length;j++) {
buffer2[j]=payload[j];
//Serial.print((char)payload[j]);
}
if (r_len < 3) {
Rflag=false;
Serial.print(F("Set false"));
}
buffer2[j]='\0'; //terminate string
}
void loop() {
if (!client.connected()) {
reconnect();
}
buttonState1 = digitalRead(buttonPin1);
//Serial.print(buttonState1);
if (buttonState1 == 0 ) {
client.publish("spotify/rfid/but1", "0");
}
buttonState2 = digitalRead(buttonPin2);
//Serial.println(buttonState2);
if (buttonState2 == 0 ) {
client.publish("spotify/rfid/but2", "0");
}
int reading = analogRead(0);
//Serial.println(reading);
if (reading > 500 ) {
client.publish("spotify/rfid/arm", "0");
}
client.loop();
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
if (Rflag) {
for (int i=0; i < 4; i++) {
//data is writen in blocks of 4 bytes (4 bytes per page)
status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer2[i*4], 4);
if (status != MFRC522::STATUS_OK) {
return;
}
}
Rflag=false;
}
cardId = getCardId();
char buffer3[10];
sprintf(buffer3, "%lu", cardId);
client.publish("spotify/rfid/id", buffer3);
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.println(F("MIFARE_Read() failed: (R)"));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
Serial.println(F("Read data: "));
for (byte i = 0; i < 5; i++) {
Serial.write(buffer[i]);
buffer2[i]=buffer[i];
}
client.publish("spotify/rfid/idlms", buffer,5);
delay(1000);
mfrc522.PICC_HaltA();
}
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];
}
Niccolò (or Nicolò) Paganini. October 1782 – 27 May 1840) was an Italian violinist and composer. He was the most celebrated violin virtuoso of his time, and left his mark as one of the pillars of modern violin technique. His 24 Caprices for Solo Violin Op. 1 are among the best known of his compositions and have served as an inspiration for many prominent composers.
I love listening to Paganini. The man was a beast. Extreme technical, a pop star in his time. But also because of that, he was seen as a demon.
Like the master bagpipers Stuart Liddell or the late Gordon Duncan.
Listening to Paganini’s caprices was wonderful.
A capriccio or caprice (sometimes plural: caprices, capri or, in Italian, capricci), is a piece of music, usually fairly free in form and of a lively character. The typical capriccio is one that is fast, intense, and often virtuosic in nature.
My top selection :
1,4,5,3
Why difficult?
Because of the advanced techniques, including parallel octaves, rapid interval shifts, extremely fast scales and arpeggios (including minor scales), left-hand pizzicato, high positions, and fast string crossings. Additionally, it features many double stops, such as thirds and tenths.
An arpeggio is a type of broken chord in which the notes that compose a chord are individually sounded in a progressive rising or descending order.
Pizzicato is a playing technique that involves plucking the strings of a string instrument.
Double stops are a fundamental technique in which two notes are played simultaneously on a stringed instrument. In the context of the violin, this entails using the bow to sound two adjacent strings at the same time.
On another note:
I finally got hold of the last missing Audio CD from Martyn Bennett! I was looking for this for ages!
The next iteration of my Rfid controller will have a write function for the RFID tags.
Stick a tag on a cover art piece of cardboard. (see below)
Read path from data sector.
Send path to player automation
Send path to program using MQTT or website if needed.
Not sure yet, also want to implement a wifi manager on the wemos.
Changes on above idea:
Paths are too long, I could not work out how to create a working program using this.
I stopped using paths, instead I’m using the Logitech media server album IDs.
Using two python scripts, I can use one for programming the card, and another script to control LMS.
How does it work
RFid device is connected to the network.
Start query.py on your LMS server. Search for an album name, it will present an ID and Album name in a list. Enter the ID you want to program, or 0 to exit. (This will also reset the programming mode)
Place an empty or previously programmed tag on the device. It will write the album ID on the tag.
Then it will start the album. Changing the tags will also just change the album playing.
(NOTE: My genre spotify player still works using this method, using the same device)
A second python script will read the Mqtt topic and control the Squeezebox player.
Python Code DB Query
import sqlite3
#paho-mqtt
import paho.mqtt.publish as publish
host = "IPMQTTBROKER"
port = 1883
topic = "spotify/rfid/in/write"
auth = {'username': 'xxxx','password': 'xxxxx'}
client_id = "spotithing"
def readSqliteTable(albumname):
try:
sqliteConnection = sqlite3.connect('/var/lib/squeezeboxserver/cache/library.db')
cursor = sqliteConnection.cursor()
albumname = "%" + albumname + "%"
cursor.execute("select * from albums where title Like ?",
(albumname,))
records = cursor.fetchall()
for row in records:
print("Id: ", row[0],row[1])
cursor.close()
except sqlite3.Error as error:
print("Failed to read data from sqlite table", error)
finally:
if sqliteConnection:
sqliteConnection.close()
album = input("Album name ? ")
readSqliteTable(album)
number = input("Enter ID or 0 to quit : ")
publish.single(topic, "00000" , qos=1, hostname=host, port=port,
auth=auth, client_id=client_id)
if number == 0:
exit()
publish.single(topic, number, qos=1, hostname=host, port=port,
auth=auth, client_id=client_id)
print("Program your tag")
print("Reset/disable writing using exit with 0!")
Python Code Controller (this one needs to be running at all times)
import paho.mqtt.client as mqtt
import urllib.request
def on_connect(client, userdata, flags, rc):
print("Connected with result code {0}".format(str(rc)))
client.subscribe("spotify/rfid/idlms")
def on_message(client, userdata, msg):
print("Message received-> " + msg.topic + " " + str(msg.payload)) # Print a received msg
urllib.request.urlopen("http://IPADDRESLMS:9000/anyurl?p0=playlistcontrol&p1=album_id:" + msg.payload.decode() + "&p2=cmd:load&player=b8:27:eb:11:16:ab")
#NOTE also change b8:27:eb:11:16:ab into you players MACAddress!
client = mqtt.Client("digi_mqtt_test")
client.on_connect = on_connect
client.on_message = on_message
client.connect('IPMQTTBROKER', 1883)
client.loop_forever()
Arduino Code (see schematic in other post)
#include <Arduino.h>
#include <SPI.h>
#include <MFRC522.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#define SS_PIN 15
#define RST_PIN 0
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::StatusCode status; //variable to get card status
byte buffer[18]; //data transfer buffer (16+2 bytes data+CRC)
byte size = sizeof(buffer);
uint8_t pageAddr = 0x06; //In this example we will write/read 16 bytes (page 6,7,8 and 9).
//Ultraligth mem = 16 pages. 4 bytes per page.
//Pages 0 to 4 are for special functions.
unsigned long cardId = 0;
WiFiClient net;
PubSubClient client(net);
const char* mqtt_server = "IPMQTTBROKER";
const char* ssid = "MYSSID";
const char* password = "MYSSIDPASS";
String topicStr = "";
byte buffer2[8];
boolean Rflag=false;
int r_len;
char payload[5];
byte value[5];
void setup() {
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
client.setServer(mqtt_server, 1883);
delay(100);
client.setCallback(callback);
delay(100);
client.subscribe("spotify/rfid/in/#");
}
void reconnect() {
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
}
while (!client.connected()) {
String clientId = "rfid-";
clientId += String(random(0xffff), HEX);
if (!client.connect(clientId.c_str(), "rfidclient", "...")) {
Serial.print("failed, rc=");
Serial.print(client.state());
delay(5000);
}
}
client.subscribe("spotify/rfid/in/#");
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print(F("Called"));
Rflag=true; //will use in main loop
r_len=length; //will use in main loop
Serial.print("length message received in callback= ");
Serial.println(length);
int j=0;
for (j;j<length;j++) {
buffer2[j]=payload[j];
}
if (r_len < 3) {
Rflag=false;
Serial.print(F("Set false"));
}
buffer2[j]='\0'; //terminate string
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
if (Rflag) {
for (int i=0; i < 4; i++) {
//data is writen in blocks of 4 bytes (4 bytes per page)
status = (MFRC522::StatusCode) mfrc522.MIFARE_Ultralight_Write(pageAddr+i, &buffer2[i*4], 4);
if (status != MFRC522::STATUS_OK) {
Serial.print(F("MIFARE_Read() failed: (W) "));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
}
Serial.println(F("MIFARE_Ultralight_Write() OK "));
Serial.println();
Rflag=false;
}
cardId = getCardId();
char buffer3[10];
sprintf(buffer3, "%lu", cardId);
client.publish("spotify/rfid/id", buffer3);
// Read data ***************************************************
Serial.println(F("Reading data ... "));
//data in 4 block is readed at once.
status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
if (status != MFRC522::STATUS_OK) {
Serial.println(F("MIFARE_Read() failed: (R)"));
Serial.println(mfrc522.GetStatusCodeName(status));
return;
}
Serial.println(F("Read data: "));
//Dump a byte array to Serial
for (byte i = 0; i < 5; i++) {
Serial.write(buffer[i]);
buffer2[i]=buffer[i];
}
client.publish("spotify/rfid/idlms", buffer,5);
delay(1000);
mfrc522.PICC_HaltA();
}
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];
}
Do you know any other good recordings? Let me know.
Uilleann CDs (no order)
Liam O’Flynn – The Pipers Call
Davy Spillane – Atlantic Bridge, Pipedreams, Out of the Air
Paddy Keenan – The Long Grazing Acre
Sean McKeon – The Dusty Miller ( Multiple players playing harmony)
Calum Stewart (I know him from his Flute playing) I play “Am Monadh Ruadh” from this CD, also Randolph’s Leap is awesome. Look up “Randolph’s Leap”. I’ve been there, beautiful. (A better name should be Cummings Leap)
Brian McNamara
He plays a ‘flat’ set pitched in ‘C’ made by Geoff Wooff in 1997 and a ‘concert-pitched’ set of pipes made by Peter Maguire, I was lucky enough to have him as my teacher in Drumshanbo.
Single tracks I like
High energy playing of Blackie O’Connoll. He was my tutor when I attended Tionol 2011
Fred Morrison‘s Kansas City Hornpipe
Paddy Keenan – Harvest Home & Boys of blue hill (Check The Pipering Of Willie Clancy Vol II)
Doinna by John McSherry (I play this one also, but it is nothing compared to his pipe-sound, melodic virtuosity and feeling he puts in this relatively easy piece of music)
Another often played CD with Uileann, Borderpipes and Low Whistles is:
Partners in Crime by Jarlath Henderson and Ross Ainslie. A very nice combination of two different pipes together. Coline and I try to have at least one set with both instruments.
Some others:
Some tracks of Bad Shepherds
Some tracks of Afro Celt Sound System
Some tracks of Enya (See Sun in the stream post)
List of Artist i’ve got recordings from:
Cillian Vallely, Finbar Furey, Ronan Browne, Willie Clancy, Seamus Ennis, Johnny Doran, Leo Rowsome, Liam O’Flynn,Davy Spillane, Paddy Keenan, Finbar Furey, Brian McNamara, Paddy Moloney, Jerry O’Sullivan, Gay Conor, Sean McKeon, Declan Masterson, Michael McGoldrick I probably missed several
Below is a test with different methods. I like reading the booklets, so a CD i cool, and I don’t need a CD player. (The RFID tag is in the case) The little cards are for bought audio files I don’t have a physical CD for.
Wooden case with RFID reader being powered by external powerbank
What am I gonna do? Cube as I had? Wooden playlist selectors as in above movies? The cards I’ve printed? Maybe a small record player with an RFID reader inside?
3D printed like this? https://makerworld.com/en/models/66671
UPDATE: 20240327 – Little Record I 3D printed with little groves.
Home Assistant code for Playlist and Album automations (B.t.w. The method is still using an Arduino and MQTT topics, as mentioned before)
# ALBUM PLAYER
alias: SpotifyAlbum
description: ""
trigger:
- platform: mqtt
topic: spotify/rfid/id
condition:
- condition: template
value_template: "{{ trigger.payload in playlistkeys.keys() }}"
action:
- service: media_player.play_media
target:
entity_id: media_player.spotify_fashice
data:
media_content_type: album
media_content_id: spotify:album:{{ playlistkeys.get(trigger.payload) }}
mode: single
variables:
playlistkeys:
"71719674": 20TANs4iXVeLp387zjgmec
"71260666": 5325ECcBhnIysoqyENGCYi
"71457530": 7wyOeD9HcUuMFMO8pTflap
In the past, Aloha and I made a simple solution like this using barcodes in < 2000s. Due to the many obscure recordings I have, I am thinking about creating something like this for Picore player and my local Squeezebox server.
Now, I’ve moved it to Home Assistant using a single automation. (Maybe the Arduino sketch can be made with Esphome also. But I don’t have time for that) It still uses the Arduino sketch as before, which uses Mqtt to post the RFID code to Mosquitto.
Google-Fu : (informal) Skill in using search engines (especially Google) to quickly find useful information on the Internet.
I was thinking of a famous piece of music, but what was it?
Whistling it, while using Shazam or Tunepal, didn’t work.
So I googled “well known classical part repeats sped up and transposes”
The second link was a Reddit link named : “Need help finding a song that starts very slow and builds to be frantic!”
First YT link in there: In the Hall of the Mountain King (Peer Gynt) by Edvard Grieg
Epic tune!
“In the Hall of the Mountain King” is a piece of orchestral music composed by Edvard Grieg in 1875 as incidental music for the sixth scene of act 2 in Henrik Ibsen’s 1867 play Peer Gynt. It was originally part of Opus 23 but was later extracted as the final piece of Peer Gynt, Suite No. 1, Op. 46.
I’ve used Tunepal many times, it’s great for folkies!
Sometimes it works also on classical pieces, because they were arranged into folk music.
I bought the Android app, because I liked it so much.
Tunepal is a search-by-playing search engine for traditional Irish, Welsh, Scottish, Breton, American marching band and Canadian tunes. By playing a 12-second extract from a traditional tune on an instrument such as the flute or fiddle, you can:
Retrieve score matches from a database of over 24,000 music scores
View and playback, share and download the score
Find and play other recordings of the tune from a collection of over 30 million recordings
Tunepal is a search-by-playing search engine for traditional Irish, Welsh, Scottish, Breton, American marching band and Canadian tunes.
On the Record page, click the Tunepal logo or tap the screen if your computer has a touch screen. Start playing straight away. Don’t wait for the countdown to complete. Tunepal works best if there is no silence at the start of the recording.
Tunepal works best with “legato” style instruments such as the tin-whistle, flute, concertina, accordion, pipes and fiddle. It doesn’t work very well with “plucked string” instruments such as the banjo and harp.
To find a tune using Tunepal, first make sure you have a PC microphone connected to your computer or use the phone app
If your instrument uses a different “fundamental note” to the usual D (for example you are playing a C flute) or you are playing a tune in an unusual key, then you can adjust the transcription algorithm by choosing a different “fundamental” from the settings page.
You can filter the search results from the settings page to limit searches to certain tunebooks or time signatures.
Record pageMy tunesPlaying pageYou can even edit the ABC score!
"If something is worth doing, it's worth overdoing."