Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GPIO Buttons over USB Encoder #1249

Merged
merged 2 commits into from
Jan 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added components/controls/__init__.py
Empty file.
19 changes: 19 additions & 0 deletions components/controls/buttons_usb_encoder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Buttons USB Encoder

Taken from [issue 1156](https://github.com/MiczFlor/RPi-Jukebox-RFID/issues/1156).

Supports functionality of buttons which are connected via USB Encoder. The USB Encoder is the easy solution for anyone
who doesn't want to solder, but also wants arcade buttons.

Tested Devices:

* [IGames Zero Verzögerung USB Encoder](https://www.amazon.de/gp/product/B01N0GZQZI)
* [EG STARTS Nullverzögerung USB Encoder](https://www.amazon.de/gp/product/B075DFNK24)

## Usage

1. Plug in your USB Encoder. You don't need to install any drivers. After plugging in, the USB encoder acts like an
input device.
2. Run the script `setup-buttons-usb-encoder.sh` to set up your usb encoder (choose the device and map the buttons).
jeripeierSBB marked this conversation as resolved.
Show resolved Hide resolved

![USB Encoder schematics](buttons-usb-encoder.jpg)
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions components/controls/buttons_usb_encoder/buttons_usb_encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python3

import sys

sys.path.append(".")

import logging
from evdev import categorize, ecodes, KeyEvent
import components.gpio_control.function_calls
from io_buttons_usb_encoder import button_map, current_device

logger = logging.getLogger(__name__)

try:
button_map = button_map()
for event in current_device().read_loop():
if event.type == ecodes.EV_KEY:
keyevent = categorize(event)
if keyevent.keystate == KeyEvent.key_down:
try:
function_name = button_map[keyevent.keycode]
try:
getattr(components.gpio_control.function_calls, function_name)()
except:
logger.warning(
"Function " + function_name + " not found in function_calls.py (mapped from button: " + keyevent.keycode + ")")
except KeyError:
logger.warning("Button " + keyevent.keycode + " not mapped to any function.")
except:
logger.error("An error with Buttons USB Encoder occurred.")
56 changes: 56 additions & 0 deletions components/controls/buttons_usb_encoder/io_buttons_usb_encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#!/usr/bin/env python3

import os.path
import sys
import json

from evdev import InputDevice, list_devices

path = os.path.dirname(os.path.realpath(__file__))
device_name_path = path + '/deviceName.txt'
button_map_path = path + '/buttonMap.json'


def all_devices():
return [InputDevice(fn) for fn in list_devices()]


def current_device():
if not os.path.isfile(device_name_path):
sys.exit('Please run register_buttons_usb_encoder.py first')
else:
with open(device_name_path, 'r') as f:
device_name = f.read()
devices = all_devices()
for device in devices:
if device.name == device_name:
_current_device = device
break
try:
_current_device
except:
sys.exit('Could not find the device %s\n. Make sure it is connected' % device_name)
return _current_device


def write_current_device(name):
with open(device_name_path, 'w') as f:
f.write(name)
f.close()


def button_map():
if not os.path.isfile(button_map_path):
sys.exit('Please run map_buttons_usb_encoder.py first')
else:
with open(button_map_path, 'r') as json_file:
button_map = json.load(json_file)
if (len(button_map) == 0):
sys.exit("No buttons mapped to a function")
return button_map


def write_button_map(button_map):
with open(button_map_path, 'w') as fp:
json.dump(button_map, fp)
fp.close()
43 changes: 43 additions & 0 deletions components/controls/buttons_usb_encoder/map_buttons_usb_encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python3

import sys

sys.path.append(".")

from evdev import categorize, ecodes, KeyEvent
from io_buttons_usb_encoder import current_device, write_button_map
import components.gpio_control.function_calls

try:
functions = list(
filter(lambda function_name: function_name.startswith("functionCall"),
dir(components.gpio_control.function_calls)))
button_map = {}

print("")
print("During the next step you can map your buttons to one of the following available functions:")
print(list(map(lambda function_name: function_name.replace("functionCall", ""), functions)))
print("")
if input('Ready to continue? (y/n)') != 'y':
sys.exit("Aborted mapping buttons to functions")

for function_name in functions:
function_name_short = function_name.replace("functionCall", "")
print("")
print("Press button to map " + function_name_short + " or press ctrl+c to skip this function")
try:
for event in current_device().read_loop():
if event.type == ecodes.EV_KEY:
keyevent = categorize(event)
if keyevent.keystate == KeyEvent.key_down:
button_map[keyevent.keycode] = function_name
print("Button " + keyevent.keycode + " is now mapped to " + function_name_short)
break
except KeyboardInterrupt:
continue
if len(button_map) == 0:
print("Warning: No buttons mapped to a function!")
else:
write_button_map(button_map)
except KeyboardInterrupt:
sys.exit("Aborted mapping buttons to functions")
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Unit]
Description=Phoniebox Buttons USB Encoder Service
After=network.target iptables.service firewalld.service

[Service]
User=pi
Group=pi
Restart=always
RestartSec=10
WorkingDirectory=/home/pi/RPi-Jukebox-RFID
ExecStart=/home/pi/RPi-Jukebox-RFID/components/controls/buttons_usb_encoder/buttons_usb_encoder.py

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env python3
import sys

from io_buttons_usb_encoder import all_devices, write_current_device

try:
devices = all_devices()
i = 0
print("")
print("Choose the Buttons USB Encoder device from the list")
for dev in devices:
print(i, dev.name)
i += 1

dev_id = int(input('Device Number: '))

write_current_device(devices[dev_id].name)
except KeyboardInterrupt:
sys.exit("Aborted to register Buttons USB Encoder.")
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash

HOME_DIR="/home/pi"
JUKEBOX_HOME_DIR="${HOME_DIR}/RPi-Jukebox-RFID"
BUTTONS_USB_ENCODER_DIR="${JUKEBOX_HOME_DIR}/components/controls/buttons_usb_encoder"

question() {
local question=$1
read -p "${question} (y/n)? " choice
case "$choice" in
y|Y ) ;;
n|N ) exit 0;;
* ) echo "Error: invalid" ; question ${question};;
esac
}

printf "Please make sure that the Buttons USB Encoder and the buttons are connected before continuing...\n"
question "Continue"

jeripeierSBB marked this conversation as resolved.
Show resolved Hide resolved
# make files executable
sudo chmod +x "${BUTTONS_USB_ENCODER_DIR}"/register_buttons_usb_encoder.py
sudo chmod +x "${BUTTONS_USB_ENCODER_DIR}"/buttons_usb_encoder.py
sudo chmod +x "${BUTTONS_USB_ENCODER_DIR}"/map_buttons_usb_encoder.py

# choose buttons usb encoder device
"${BUTTONS_USB_ENCODER_DIR}"/register_buttons_usb_encoder.py

# setup buttons
"${BUTTONS_USB_ENCODER_DIR}"/map_buttons_usb_encoder.py

printf "\nStart phoniebox-buttons-usb-encoder service...\n"
sudo cp -v "${BUTTONS_USB_ENCODER_DIR}"/phoniebox-buttons-usb-encoder.service.sample /etc/systemd/system/phoniebox-buttons-usb-encoder.service
sudo systemctl start phoniebox-buttons-usb-encoder.service
sudo systemctl enable phoniebox-buttons-usb-encoder.service
s-martin marked this conversation as resolved.
Show resolved Hide resolved

printf "Done.\n"
5 changes: 3 additions & 2 deletions components/gpio_control/function_calls.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import logging
import sys
from subprocess import Popen as function_call
import os
import pathlib

logger = logging.getLogger(__name__)

playout_control = "../../scripts/playout_controls.sh"

playout_control = os.path.abspath(os.path.join(pathlib.Path(__file__).parent.absolute(), "../../scripts/playout_controls.sh"))
s-martin marked this conversation as resolved.
Show resolved Hide resolved

def functionCallShutdown(*args):
function_call("{command} -c=shutdown".format(command=playout_control), shell=True)
Expand Down