One of the standing traditions in my household is to get thoroughly immersed in Christmas music during the holiday season. For years, this has involved Pandora streams and Raspberry Pis. This year, I built on that tradition with a little help from some Adafruit gadgets:
The speaker bonnet:
and a membrane matrix pad
This time around, I upgraded the music delivery system from Pandora to a SiriusXM based approach using andrew0’s code on github that creates a SiriusXM server on your RPi. Some tweaks were needed to bring the code up to date and I moved passwords and tokens to a secrets.py file along the lines of this circuitpython tutorial from Adafruit. Then using the matrix pad tutorial I was able to create a script to connect the keypad to different stations, including an on/off button and volume control. Lastly, I 3D printed a wall mount for the pad that allows me to “change” the buttons so that I don’t have to remember which buttons are which.
Now, I’ve got the ability to play Christmas music while I’m baking cookies in the kitchen (I’m up to 8 dozen to date). Here’s the setup (pre 3D printed wall mount.
If you’re interested in reproducing this setup, I start the SiriusXM server using systemctl
and then start the code below manually. If I run that code in a GNU Screen, then I can detach the screen and still keep the code running.
import os
import subprocess
import time
import digitalio
import board
import adafruit_matrixkeypad
cols = [digitalio.DigitalInOut(x) for x in (board.D5, board.D6, board.D12)]
rows = [digitalio.DigitalInOut(x) for x in (board.D27, board.D22, board.D23, board.D24)]
keys = ((1,2,3),(4,5,6),(7,8,9),('vup',0,'vdown'))
keypad = adafruit_matrixkeypad.Matrix_Keypad(rows, cols, keys)
check_keypad = True
def SiriusActiveQ():
'''
Checks systemd to see if siriusxm is active.
systemctl returns 0 if active, or 3 if inactive (presumably other exit codes as well)
'''
r = subprocess.call(['systemctl','is-active','siriusxm'])
return (r == 0)
def killVLC():
'''
Ensures that vlc is not running
'''
os.system('killall vlc')
def SiriusPlay(channel):
'''
Plays a channel, does not check if channel is valid
'''
killVLC()
subprocess.Popen(['cvlc','http://127.0.0.1:8888/{}.m3u8'.format(channel)])
def speak(statement):
os.system('espeak -w /tmp/out.wav -ven+f3 -k5 -s150 -a125 "{}" 2>/dev/null'.format(statement))
os.system('aplay /temp/out.wav')
#subprocess.call(['espeak','-s','125','-a','150',str(statement)])
def constrain(val, min_val, max_val):
return min(max_val, max(min_val, val))
def setvolume(volume):
vol = constrain(volume,0,90) # Just making sure
subprocess.run(['amixer', 'sset','PCM','{}%'.format(vol)])
def process_keypress(key):
global volume
if (key=='vup'):
volume = constrain(volume + 10,0,90)
setvolume(volume)
elif (key=='vdown'):
volume = constrain(volume -10, 0, 90)
setvolume(volume)
elif (key==0):
killVLC()
elif (key==1):
SiriusPlay(9342)
elif (key==2):
SiriusPlay(9483)
elif (key==3):
SiriusPlay(9403)
elif (key==4):
SiriusPlay(9343)
elif (key==5):
SiriusPlay(9521)
elif (key==6):
SiriusPlay(9489)
elif (key==7):
SiriusPlay(9344)
elif (key==8):
SiriusPlay('nprnow')
elif (key==9):
SiriusPlay('symphonyhall')
else:
speak('I do not understand.')
print("Setting default volume to 75%")
volume = 75
setvolume(volume)
print("Do something")
while True:
try:
if check_keypad:
keys = keypad.pressed_keys
if keys:
check_keypad = False
process_keypress(keys[0])
check_keypad = True
time.sleep(0.1)
except (KeyboardInterrupt, EOFError, SystemExit):
break
I’m excited about this platform since it opens up a lot of other streaming services via VLC. I do need to figure out some volume issues, as supposedly I can get much more sound out of the speaker bonnet than I am at the time. For now, I am pretty psyched that this system has introduced me to Dominic the Christmas Donkey.