I got the file to run Ok, and I’m getting codes when I press the up, down, left , right, and OK. Nothing happens though when I press the media keys on the left side of the keyboard? This min keyboard is branded Cana Kit but I got the same ID codes as the Rii used in that tutorial. This keyboard is identical with identical layout. I’d really like to use the media keys if possible?
I’m guessing the media keys are on a different endpoint.
If you edit the line that looks like a family of owls, you might be able to find them. If I remember correctly, there are methods available for enumerating endpoints, too.
I got codes from my FLIRC that I think I can use. I’m struggling to figure out how to edit the file for the explorer pHat to work with my pHat Beat though. Here is what I have. Are there code tags I should be using? I ran it once as sudo from command line and one whole bar of LED’s light up on the pHat Beat. Didn’t seem too work, hard to tell things went funcky and now all I get is very low scratchy sounds from the speakers. I’m reimaging my SD card as I type this to start all over again. I’m getting close to throwing in the towel on this one. Is there a python file that starts the Pirate radio on boot up? Is that maybe the file I should be editing instead of creating a new one?
#!/usr/bin/env python
import usb.core
import usb.util
import phatbeat
import time
USB_VENDOR = 0x20a0
USB_PRODUCT = 0x0001
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in MS
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
endpoint = dev[0][(0,0)][0]
if dev.is_kernel_driver_active(USB_IF) is True:
dev.detach_kernel_driver(USB_IF)
usb.util.claim_interface(dev, USB_IF)
while True:
control = None
try:
control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
print(control)
except:
pass
if control != None:
if BTN_VOLUMEDN in control:
phatbeat.BTN_VOLDN()
if BTN_VOLUMEUP in control:
phatbeat.BTN_VOLUP()
if BTN_CHANDN in control:
phatbeat.BTN_REWIND()
if BTN_CHANUP in control:
phatbeat.BTN_FASTFWD()
if BTN_POWER in control:
phatbeat.BTN_ONOFF()
#if BTN_EXIT in control:
#exit()
time.sleep(0.02)
It’s best left as-is, though, since it’s a fairly obtuse script not meant to be an editable example.
The relevant parts to understand are the socket interface for controlling VLC, which you can build into your script. Importing the phatbeat library wont work, since that’s just for reading buttons and doesn’t provide control over any of the software on your Pi.
import socket
import re
VLC_HOST = "127.0.0.1"
VLC_PORT = 9294
class VLC():
def __init__(self, host="127.0.0.1", port=9294):
self.host = host
self.port = port
self.current_stream = None
self.current_state = None
self.connecting = False
self.socket = None
def send(self, command):
if self.connecting:
return False
print("Sending command: {}".format(command))
command_string = command + "\n"
if sys.version_info[0] >= 3:
command_string = command_string.encode("utf-8")
try:
self.socket.send(command_string)
except socket.error:
print("Failed to send command to VLC")
if self.connect():
self.send(command)
def recv(self, length):
value = self.socket.recv(8192)
if sys.version_info[0] >= 3:
value = value.decode("utf-8")
return value
def communicate(self, command, response_length=8192):
self.send(command)
return self.recv(response_length)
def get_current_stream(self):
self.send("status")
status = self.recv(8192)
result = re.search("input:\ (.*)\ ", status)
state = re.search("state\ (.*)\ ", status)
if state is not None:
self.current_state = state.group(1)
if result is not None:
self.current_stream = result.group(1)
else:
self.current_stream = None
return self.current_stream
def connect(self):
if self.connecting:
return
self.connecting = True
if self.socket is not None:
self.socket.close()
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for attempt in range(10):
try:
print("Attempting to connect to VLC on {host}:{port}".format(host=self.host, port=self.port))
self.socket.connect((self.host, self.port))
print("Connection successful!")
self.connecting = False
return True
except socket.error:
time.sleep(1)
print("Connection failed!")
self.connecting = False
return False
vlc = VLC(host=VLC_HOST, port=VLC_PORT)
if vlc.connect():
# Your setup code here
And once all of the above has set up a connection to VLC, you can use the following commands to control it:
vlc.communicate("voldown") # Turn the volume down one step
vlc.communicate("volup") # Turn the volume up one step
vlc.communicate("next") # Next track
vlc.communicate("prev") # Prev track
vlc.communicate("pause") # Pause/Play
Note: To paste indented code, surround it with three backticks:
Just sat down with a cup of Java to have a go at it. Making a backup image of my SD card first though. Not knowing what I’m doing hasn’t stopped me before. ;)
Ok this is what I have so far. For now I just do a sudo python3 etc from the command line to run it. I’m seeing the key codes on screen so I’m thinking that’s because of the “print (control)” line, and I can remove it to stop that. After a couple of key presses, that don’t seem to be doing anything, I get a “sys not defined” error which I think is the " if sys.version_info[0] >= 3:" line?
import socket
import re
VLC_HOST = "127.0.0.1"
VLC_PORT = 9294
class VLC():
def __init__(self, host="127.0.0.1", port=9294):
self.host = host
self.port = port
self.current_stream = None
self.current_state = None
self.connecting = False
self.socket = None
def send(self, command):
if self.connecting:
return False
print("Sending command: {}".format(command))
command_string = command + "\n"
if sys.version_info[0] >= 3:
command_string = command_string.encode("utf-8")
try:
self.socket.send(command_string)
except socket.error:
print("Failed to send command to VLC")
if self.connect():
self.send(command)
def recv(self, length):
value = self.socket.recv(8192)
if sys.version_info[0] >= 3:
value = value.decode("utf-8")
return value
def communicate(self, command, response_length=8192):
self.send(command)
return self.recv(response_length)
def get_current_stream(self):
self.send("status")
status = self.recv(8192)
result = re.search("input:\ (.*)\ ", status)
state = re.search("state\ (.*)\ ", status)
if state is not None:
self.current_state = state.group(1)
if result is not None:
self.current_stream = result.group(1)
else:
self.current_stream = None
return self.current_stream
def connect(self):
if self.connecting:
return
self.connecting = True
if self.socket is not None:
self.socket.close()
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for attempt in range(10):
try:
print("Attempting to connect to VLC on {host}:{port}".format(host=self.host, port=self.port))
self.socket.connect((self.host, self.port))
print("Connection successful!")
self.connecting = False
return True
except socket.error:
time.sleep(1)
print("Connection failed!")
self.connecting = False
return False
vlc = VLC(host=VLC_HOST, port=VLC_PORT)
if vlc.connect():
import usb.core
import usb.util
import time
USB_VENDOR = 0x20a0
USB_PRODUCT = 0x0001
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in MS
BTN_FASTFWD = 181
BTN_REWIND = 182
BTN_PLAYPAUSE = 205
BTN_VOLUP = 223
BTN_VOLDN = 234
BTN_ONOFF = 1
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
endpoint = dev[0][(0,0)][0]
if dev.is_kernel_driver_active(USB_IF) is True:
dev.detach_kernel_driver(USB_IF)
usb.util.claim_interface(dev, USB_IF)
while True:
control = None
try:
control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
print(control)
except:
pass
if control != None:
if BTN_FASTFWD in control:
vlc.communicate("next") # Next track
if BTN_REWIND in control:
vlc.communicate("prev") # Prev track
if BTN_PLAYPAUSE in control:
vlc.communicate("pause") # Pause/Play
if BTN_VOLUP in control:
vlc.communicate("volup") # Turn the volume up one step
if BTN_VOLDN in control:
vlc.communicate("voldown") # Turn the volume down one step
if BTN_ONOFF in control:
vlc.communicate("power") # Turn Off
time.sleep(0.02)
Not too bad! This is looking incredibly close to being functional from what I can tell at a glance :D
Note that if vlc.connect() fails then the code from if dev.is_kernel_driver_active onwards will still be run and the program will fail when a button is pressed.
It looks like you need to import sys at the top of your code too, I missed that when I was skimming through looking for the imports that the VLC class needed.
Got it working woot. I can even shut down when I press the power button on the remote. Here is my code. What is the best way to launch this on boot up?
import os
import socket
import re
import sys
VLC_HOST = "127.0.0.1"
VLC_PORT = 9294
class VLC():
def __init__(self, host="127.0.0.1", port=9294):
self.host = host
self.port = port
self.current_stream = None
self.current_state = None
self.connecting = False
self.socket = None
def send(self, command):
if self.connecting:
return False
print("Sending command: {}".format(command))
command_string = command + "\n"
if sys.version_info[0] >= 3:
command_string = command_string.encode("utf-8")
try:
self.socket.send(command_string)
except socket.error:
print("Failed to send command to VLC")
if self.connect():
self.send(command)
def recv(self, length):
value = self.socket.recv(8192)
if sys.version_info[0] >= 3:
value = value.decode("utf-8")
return value
def communicate(self, command, response_length=8192):
self.send(command)
return self.recv(response_length)
def get_current_stream(self):
self.send("status")
status = self.recv(8192)
result = re.search("input:\ (.*)\ ", status)
state = re.search("state\ (.*)\ ", status)
if state is not None:
self.current_state = state.group(1)
if result is not None:
self.current_stream = result.group(1)
else:
self.current_stream = None
return self.current_stream
def connect(self):
if self.connecting:
return
self.connecting = True
if self.socket is not None:
self.socket.close()
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
for attempt in range(10):
try:
print("Attempting to connect to VLC on {host}:{port}".format(host=self.host, port=self.port))
self.socket.connect((self.host, self.port))
print("Connection successful!")
self.connecting = False
return True
except socket.error:
time.sleep(1)
print("Connection failed!")
self.connecting = False
return False
vlc = VLC(host=VLC_HOST, port=VLC_PORT)
if vlc.connect():
import usb.core
import usb.util
import time
USB_VENDOR = 0x20a0
USB_PRODUCT = 0x0001
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in MS
BTN_FASTFWD = 181
BTN_REWIND = 182
BTN_PLAYPAUSE = 205
BTN_VOLUP = 233
BTN_VOLDN = 234
BTN_ONOFF = 1
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
endpoint = dev[0][(0,0)][0]
if dev.is_kernel_driver_active(USB_IF) is True:
dev.detach_kernel_driver(USB_IF)
usb.util.claim_interface(dev, USB_IF)
while True:
control = None
try:
control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
#print(control)
except:
pass
if control != None:
if BTN_FASTFWD in control:
vlc.communicate("next") # Next track
if BTN_REWIND in control:
vlc.communicate("prev") # Prev track
if BTN_PLAYPAUSE in control:
vlc.communicate("pause") # Pause/Play
if BTN_VOLUP in control:
vlc.communicate("volup") # Turn the volume up one step
if BTN_VOLDN in control:
vlc.communicate("voldown") # Turn the volume down one step
if BTN_ONOFF in control:
os.system("sudo shutdown now -P")
time.sleep(0.02)
OK, crontab -e is how I usually do it, but in this case it didn’t work? My remote didn’t work.
I tried @reboot sudo python3 /home/pi/PRRC.py &
and just @reboot python3 /home/pi/PRRC.py &
sudo python3 /home/pi/PRRC.py is what I run from command line and that works. If I don’t do sudo I get all kinds of error messages.
I’ll have another try in an hour or so after my morning walk with my dog Ginger. Maybe I had a typo and didn’t see it?
Sorted it out, I had to add a delay, 15 seconds seems to work OK @reboot sleep 15;sudo python3 /home/pi/PRRC.py &
Something I noticed is when I use the play pause on my remote, the LED matrix freezes with what ever LED’s where on when I pressed the button. Pressing the physical button on the phat beat though and they all turn off. I guess that’s because My remote is talking to VLC Radio and not the phat beat directly?
One solution to this, is to merge your code for controlling via a remote into phatbeatd. It’s not a very straight forward procedure, but it’s certainly possible.