# Inspired by https://pimylifeup.com/raspberry-pi-kiosk/ # Start with a raspberry pi "full" installation that boots to desktop and # can run chromium browser. # # Follow braincraft setup instructions sections: # - raspberry pi setup # - blinka setup # - audio setup # - fan service setup (optional) # # Now run this script, restart, and satisfy yourself that the player works # properly using a HDMI monitor. Troubleshooting is easier at this point! # # Now run the braincraft setup setps: # - display module install # - enable "overlay mode" in raspi-config so that it's safe to just power off # the pi anytime # # Before working with the system, remember to # - disable "overlay mode" # - optionally disable the display module to get a regular desktop back cd $HOME sudo apt-get install -y xdotool unclutter sed cat > kiosk.sh < braincraftKeys.py <<"EOF" #!/usr/bin/env python3 # Credit to Pimoroni for Picade HAT scripts as starting point. import time import signal import os import sys from datetime import datetime from collections import deque import re import fileinput try: from evdev import uinput, UInput, ecodes as e except ImportError: exit("This library requires the evdev module\nInstall with: sudo pip install evdev") import digitalio import board def detect_rotation(): rotation_pattern = "^dtoverlay=drm-minipitft13,rotation=([0-9]+)" hdmi_pattern = "^display_hdmi_rotate=([0-9])" param_rotation = None param_hdmi = None for line in fileinput.FileInput("/boot/config.txt"): rotation_match = re.search(rotation_pattern, line) hdmi_match = re.search(hdmi_pattern, line) if rotation_match: param_rotation = int(rotation_match.group(1)) if hdmi_match: param_hdmi = int(hdmi_match.group(1)) if param_rotation is not None and param_hdmi is not None: break if param_hdmi == 3: return 180 if param_hdmi == 2: return 270 if param_hdmi == 1: return 0 return param_rotation arrow_pins = deque(( board.D23, # up board.D24, # right board.D27, # down board.D22, # left )) arrow_pins.rotate((detect_rotation() // 90) - 1) DEBUG = False BOUNCE_TIME = 0.01 # Debounce time in seconds POWEROFF_TIMEOUT = 5 KEYS= [ # EDIT KEYCODES IN THIS TABLE TO YOUR PREFERENCES: # See /usr/include/linux/input.h for keycode names # Keyboard Action (tuple = press together, no repeat) (board.D17, (e.KEY_K,)), # button - play/pause (board.D16, (e.KEY_LEFTCTRL, e.KEY_R)), # push stick - reload (arrow_pins[3], (e.KEY_LEFTSHIFT, e.KEY_P)), # left - previous in playlist (arrow_pins[1], (e.KEY_LEFTSHIFT, e.KEY_N)), # right - next in playlist (arrow_pins[0], e.KEY_EQUAL), # up - volume up (arrow_pins[2], e.KEY_MINUS), # down - volume down ] key_values = set() for pin, action in KEYS: if isinstance(action, int): key_values.add(action) else: key_values.update(action) class KeyManager: def __init__(self, pin, action): self.pin = digitalio.DigitalInOut(pin) self.pin.switch_to_output(digitalio.Pull.UP) self.action = action self.old_value = False @property def value(self): return not self.pin.value # buttons are active-low def tick(self): value = self.value if value != self.old_value: if isinstance(self.action, int): ui.write(e.EV_KEY, self.action, value) ui.syn() elif value: for key in self.action: ui.write(e.EV_KEY, key, 1) ui.syn() for key in self.action[::-1]: ui.write(e.EV_KEY, key, 0) ui.syn() self.old_value = value class ShutdownManager: def __init__(self, manager): self.manager = manager self.old_value = False self.press_start = 0 @property def value(self): return self.manager.value def tick(self): now = time.time() value = self.value if value: if self.old_value: if now > self.press_start + POWEROFF_TIMEOUT: os.system("env DISPLAY=:0 XAUTHORITY=/home/pi/.Xauthority xset dpms force off") os.system("sudo poweroff") else: self.press_start = now self.old_value = value managers = [KeyManager(k, v) for k, v in KEYS] managers.append(ShutdownManager(managers[0])) os.system("sudo modprobe uinput") try: ui = UInput({e.EV_KEY: key_values}, name="braincraft-hat", bustype=e.BUS_USB) except uinput.UInputError as e: sys.stdout.write(repr(e)) sys.stdout.write("Have you tried running as root? sudo {}".format(sys.argv[0])) sys.exit(0) def log(msg): sys.stdout.write(str(datetime.now())) sys.stdout.write(": ") sys.stdout.write(msg) sys.stdout.write("\n") sys.stdout.flush() while True: for manager in managers: manager.tick() time.sleep(BOUNCE_TIME) EOF chmod +x braincraftKeys.py cat > kiosk.service < kioskvideo.html <<"EOF" Braincraft Hat - lofi hip hop radio - betas to relax/study to
NOTE: Chromium must be launched with --autoplay-policy=no-user-gesture-required or the video will not autoplay and the play/pause keystrokes will not work properly. Clicking in the video will also affect keystroke functionality! EOF