Hi All,
I have been using Volumio for a while in headless mode. I wanted to have the touch screen as well so for Christmas I was brought the official Raspberry Pi 7" touch screen. I made/modified a stand for it to go in and also had a button to be able to control the backlight level of the display. I used a number of posts/sites to get the screen working how I wanted so I made a guide to help me in the future. I thought I would share if anyone else would find it useful. If you don’t want the button for backlight control stop at the “Install Python GPIO” section and reboot device!
Hardware
https://www.thingiverse.com/thing:3318343
The button is connected to pins 37 and 39 and the LED in the button is connected between pins 33 and 39 with a 2k2ohmn resistor (draws a max of about 0.4mA with that resistor - the LED has a forward voltage of 2.5V). I chose such a high value as I only wanted the LED ring to glow and not illuminate, an annoyance of mine with many “proper” products with their blinding LEDs!

Install Volumio as normal
Install and activate touchscreen plugin in Volumio Plugins
Enable SSH:
goto http://VOLUMIOIP/dev in your browser
Click ENABLE button for SSH
Load PuTTY (or other SSH client) and log into Volumio
(default username: volumio - default password: volumio)
Update Packages:
sudo apt-get update
Remove mouse pointer
[spoiler]
sudo nano /lib/systemd/system/volumio-kiosk.service
find line:
ExecStart=/usr/bin/startx /etc/X11/Xsession /opt/volumiokiosk.sh
change to:
ExecStart=/usr/bin/startx /etc/X11/Xsession /opt/volumiokiosk.sh -- -nocursor
[/spoiler]
Stop screen blanking and crashed message
[spoiler]
sudo nano /opt/volumiokiosk.sh
change lines:
xset +dpms
xset s blank
xset 0 0 120
to:
xset -dpms
xset s off
#xset 0 0 120
When you reboot sometimes the browser doesn’t quit properly and you end up with the request box asking to restore session. To stop that happening also change the line:
    --user-data-dir='/data/volumiokiosk'        --no-sandbox     http://localhost:3000to
    --user-data-dir='/data/volumiokiosk'        --no-sandbox     --app=http://localhost:3000
[/code][/spoiler]
[b][i]Install and activate Matchbox onscreen keyboard[/i][/b]
[spoiler]First install the software:
[code]
sudo apt-get install matchbox-window-manager matchbox-keyboard
[/code]
Edit volumiokiosk.sh to activate keyboard
[code]
sudo nano /opt/volumiokiosk.sh
[/code]
Add the following after the "xset" commands:
[code]matchbox-keyboard -d &
matchbox-window-manager -use_titlebar no &[/code]
Then comment out the line:
[code]
openbox-session &
[/code]
to
[code]
#openbox-session &
[/code]
Exit and save [CTRL]+X and then press Y to save.
Next update the keyboard.xml for something more touch friendly for our needs (thanks to Xoliul for this! - it gives a simple QWERTY layout with numbers but nothing more and should be enough for most needs on this. Of course you can edit it and make your own!)
Backup and edit the keyboard.xml with:
[code]cd /usr/share/matchbox-keyboard/
sudo mv keyboard.xml keyboard.xml_old
sudo nano keyboard.xml[/code]
In nano copy the following:
[code]<?xml version="1.0" encoding="UTF-8"?>
<keyboard>
<layout id="default keyboard">
  <row>
    <key>
     <default display="Q" action="q"/>               
    </key>
    <key>
     <default display="W"  action="w"/>               
    </key>
    <key>
     <default display="E"  action="e"/>               
    </key>
    <key>
     <default display="R"  action="r"/>
    </key>
    <key>
     <default display="T"  action="t"/>
    </key>
    <key>
     <default display="Y"  action="y"/>
    </key>
    <key>
     <default display="U"  action="u"/>
    </key>
    <key>
     <default display="I"  action="i"/>
    </key>
    <key>
     <default display="O"  action="o"/>
    </key>
    <key>
     <default display="P"  action="p"/>
    </key>
    <key>
     <default display="1"/>               
    </key>
    <key>
     <default display="2"/>               
    </key>
    <key fill="true">
    <default display="⌫" action="backspace"/>
     <!-- <default display="Bksp" action="backspace"/> -->
    </key>
  </row>
  <row>
    <key>
     <default display="A"   action="a"/>               
    </key>
    <key>
     <default display="S"   action="s"/>
    </key>
    <key>
     <default display="D"   action="d"/>
    </key>
    <key>
     <default display="F"   action="f"/>
    </key>
    <key>
     <default display="G"   action="g"/>
    </key>
    <key>
     <default display="H"   action="h"/>
    </key>
    <key>
     <default display="J"   action="j"/>
    </key>
    <key>
     <default display="K"   action="k"/>
    </key>
    <key>
     <default display="L"   action="l"/>
    </key>
    <key>
     <default display="3" />
    </key>
    <key>
     <default display="4" />
    </key>
    <key>
     <default display="5" />
    </key>
    <key fill="true">
     <default display="⏎" action="return"/>
    </key>
  </row>
  <row>
    <key>
     <default display="Z"   action="z"/>
    </key>
    <key>
     <default display="X"   action="x"/>
    </key>
    <key>
     <default display="C"   action="c"/>
    </key>
    <key>
     <default display="V"   action="v"/>
    </key>
    <key>
     <default display="B"   action="b"/>
    </key>
    <key>
     <default display="N"   action="n"/>
    </key>
    <key>
     <default display="M"   action="m"/>
    </key>
    <key>
     <default display="6" />
    </key>
    <key>
     <default display="7" />
    </key>
    <key>
     <default display="8" />
    </key>
    <key>
     <default display="9" />
    </key>
    <key>
     <default display="0" />
    </key>
    <key fill="true">
     <default display="␣" action="space" />               
    </key>
 </row>
</layout>
</keyboard>[/code]
Again close and save the file then reboot to see your work![/spoiler]
[b][i]Move track and volume controls up (stops them clipping on the bottom of the screen)[/i][/b]
[b][size=150]CAUTION [/size][/b]- You are editing Volumio's Files which will prevent updating. To update you will need to restore the file using the Factory Reset in the System settings
[spoiler][code]
	cd /volumio/http/www/styles	sudo nano app-013f2d5c5e.csspress [CTRL]+W to search and type in "volumeManager{margin-top"
this should show the line:
	[code]
@media (max-width:767px){#trackManagerWrapper{left:-30px;right:-30px}}#trackManager,.volumeManager{margin-top:110px}
[/code]
change margin-top:110px to margin-top:55px
You can also search for:
		webkit-scrollbar{width:10px;height:10px}:and change the width to a larger number to make the scroll bar more finger friendly (40px should be fine)[/spoiler]
Install Python GPIO
[spoiler]Download:
		wget https://sourceforge.net/projects/raspberry-gpio-python/files/raspbian-wheezy/python-rpi.gpio_0.6.2~wheezy-1_armhf.deb		(check version here: [url]https://sourceforge.net/projects/raspberry-gpio-python/files/raspbian-wheezy/[/url] and replace "python-rpi.gpio_0.6.2~wheezy-1_armhf.deb" with current version)
Install:
		sudo dpkg -i python-rpi.gpio_0.6.2~wheezy-1_armhf.deb
[/spoiler]
Install Python backlight library:
[spoiler]Install PIP:
		sudo apt install python-pipInstall backlight library:
		sudo pip install rpi_backlight
[/spoiler]
Setup button script:
[spoiler]Note: When updating just copy new code over old (or edit lines) and reboot machine
	mkdir scripts
	cd scripts
	nano bl-control.py
Paste following:
[code]#!/bin/python
########################## User Variables ###########################
screenDelay = 30 # number of minutes before turning off the screen	#
blState = 2      # default brightness of the backlight (1-3)		#
LOWBRIGHT = 32	 # lowest brightness level	# Set these between		#
MIDBRIGHT = 64	 # medium brightness level	# 11-255 for custom		#
HIGBRIGHT = 192	 # highest brightness level	# brightness levels		#
#####################################################################
import RPi.GPIO as GPIO
import time
import rpi_backlight as bl
import subprocess
import os
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.setup(13, GPIO.OUT)
led = GPIO.PWM(13, 2000)
led.start(100)
ledLvl = 100
ledDir = 0
buttonState = 0 		#current button state
lastButtonState = 0		#previous button state
timePressed = 0			#when was button pressed
stateChange = “”		#holds command when changing bl state
lastStatus = “”			#stores playback state when turning off bl
lastBlState = blState	#previous backlight state (primed with default
lastPlayState = “play”	#what was volumio doing when bl turned off
pausedTime = 0 			#when was unit paused
gamma = 2.8				#gamma adjust for LED (makes breathing smooth)
max_in = 100.0			#the maximum level to call for adjustment
max_out = 100.0			#the maximum level for PWM (100 for RPi)
levelOutput = 0.0		#variable to hold the adjusted level output
screenDelay = screenDelay * 60 # change from minutes to seconds for timer
bl.set_power(True)		#turn on bl
bl.set_brightness(64, smooth = True, duration = 1) #set bl level
while 1: #repeat continously
buttonState = 1 - GPIO.input(26) #invert state due to pullup
try: #trys to open volumio and if it hasn't loaded waits 5 seconds to try again - this is as the script loads befor volumio and was causing the script to fail to load
	
	status = subprocess.check_output("volumio status | sed -e 's/true/True/g' -e 's/false/False/g' -e 's/null/False/g'", shell=True) #find out current status of volumio
	status = eval(status)
	
	if (status["status"] == "pause" and lastPlayState == "play"): # checks if volumio has just paused
		pausedTime = time.time() # store the time volumio paused
	elif (status["status"] == "stop" and lastPlayState == "play"): # checks if volumio has just stopped
		pausedTime = time.time()
	elif (status["status"] == "play" and lastPlayState <> "play" and blState == 0): # has volumio started playing and is the backlight off
		stateChange = "resume" 									# restore backlight
		
		
	if (time.time() - pausedTime > screenDelay and status["status"] <> "play" and blState <> 0): # check if paused for longer than "screenDelay" seconds, volumio is not playing and backlight is on
		stateChange = "blOff" 									# turn off backlight
		
	
	if (buttonState == 1 and lastButtonState == 0):
		timePressed = time.time() 								#store time button pressed
		
	elif (buttonState == 1 and lastButtonState == 1): 			#button held
		if (time.time() - timePressed > 2): 					#if held for more than two seconds turn off bl
			stateChange = "blOff"
			
	elif (buttonState == 0 and lastButtonState == 1): 			#button released
		if (time.time() - timePressed <= 2): 					#if button released before two seconds passed change brightness
			pausedTime = time.time() 							# update pause time to reset the timer
			if (lastStatus == "play"): 							# checks to see if unit was previously paused by using the button to turn off backlight and resumes again
				stateChange = "resume" 							# resume screen brightness and playback
			else: 												# otherwise just move to next brightness level
				stateChange = "nextBL" 
			
	elif (buttonState == 0 and lastButtonState == 0): 			#button not pressed
		if (blState == 0):										#backlight if off, 'breath' the LED
			levelOutput = ((ledLvl/max_in) ** gamma) * max_out	#gamma calculation
			if (levelOutput > 100): levelOutput = 100			#clamp output to max PWM level (100 for RPi)
			
			if (ledDir == 0):									#ramp intensity down
				led.ChangeDutyCycle(levelOutput)				#set PWM output from gamma corrected level
				ledLvl = ledLvl - 1								#reduce brightness for next pass
				if (ledLvl == 1):								#when brightness at lowest point (not 0 as LED goes off and looks odd)
					ledDir = 1									#switch brightness direction to increase
			else:												#ramp intensity up
				led.ChangeDutyCycle(levelOutput)
				ledLvl = ledLvl + 1
				if (ledLvl == 100):								#switch direction when at max brightness
					ledDir = 0
					
		time.sleep(0.05)										#if no button being pressed sleep for 50mSec - prevents loading a thread
	
	if (stateChange == "blOff"):
		os.system("volumio volume mute")						#mute volume 
		if (status["status"] == "play"):						#check if currently playing
			os.system("volumio pause")							#pause playback
			lastStatus = "play"									#store that the unit was playing when backlight turned off
		lastBlState = blState									#store the current backlight level
		blState = 0												#set to backlight off
		stateChange = ""
		bl.set_brightness(11, smooth = True, duration = 1)		#reduce brightness to min
		bl.set_power(False)										#then turn off completly.
	
	elif (stateChange == "nextBL" or stateChange == "resume"):
		led.ChangeDutyCycle(100)								#turn on led
		
		if (stateChange == "nextBL"):							#chang to next bl level
			
			if (blState == 0):									#restore bl level if previously off
				blState = lastBlState
			else: 
				blState = blState - 1							#next bl level
				
			if (blState < 1): 									#roll-over
				blState = 3
		elif (stateChange == "resume"):							#restore bl level and start playing (if paused when turning off bl)
			os.system("volumio volume unmute")					#unmute volume
			blState = lastBlState
			if (lastStatus == "play"):
				os.system("volumio play")
				lastStatus = ""
			
			
		# next section sets current brightness level. Change the first number in bl.set_brightness 
		# between 11-255 if other brightness levels required.
		if (blState == 1):
			bl.set_power(True)
			bl.set_brightness(LOWBRIGHT, smooth = True, duration = 1)
		elif (blState == 2):
			bl.set_power(True)
			bl.set_brightness(MIDBRIGHT, smooth = True, duration = 1)
		elif (blState == 3):
			bl.set_power(True)
			bl.set_brightness(HIGBRIGHT, smooth = True, duration = 1)
			
		stateChange = ""
	lastPlayState = status["status"]
	lastButtonState = buttonState #store current button state to determine if button still being pressed or not.
except: #wait five seconds for volumio to load
	time.sleep(5)[/code]
At the top of the script there are the user variable. These allow the default settings to be changed for the backlight time delay and the default backlight level as well as the backlight brightness for each level
########################## User Variables ###########################
screenDelay = 30 # number of minutes before turning off the screen	#
blState = 2      # default brightness of the backlight (1-3)		#
LOWBRIGHT = 32	 # lowest brightness level	# Set these between		#
MIDBRIGHT = 64	 # medium brightness level	# 11-255 for custom		#
HIGBRIGHT = 192	 # highest brightness level	# brightness levels		#
#####################################################################
Press [CTRL]+X and save file.
Set bl-control.py to boot on startup:
sudo nano /etc/rc.localbefore the final “exit 0” paste:
python /home/volumio/scripts/bl-control.py &(the “&” is important to allow the script to run in the background!)[/spoiler]
Reboot device!
sudo rebootIf all goes to plan you should reboot and pressing the button will change the backlight level and holding should turn it off, with the LED “breathing”.
Sites and posts that helped me with this
[spoiler]https://volumio.org/forum/volumio-touchscreen-mouse-cursor-t6629.html
https://volumio.org/forum/screentimeout-rpi-touchscreen-t5059.html#p23854
https://volumio.org/forum/installing-rpi-gpio-volumio-t3544.html#p15591
https://github.com/linusg/rpi-backlight
https://www.hackster.io/glowascii/raspberry-pi-shutdown-restart-button-d5fd07
https://stackoverflow.com/questions/48133509/python-2-7-9-subprocess-convert-check-output-to-dictionary-volumio
https://learn.adafruit.com/led-tricks-gamma-correction/the-longer-fix
https://raspberrypi.stackexchange.com/questions/68734/how-do-i-disable-restore-pages-chromium-didnt-shut-down-correctly-prompt
https://volumio.org/forum/virtual-keyboard-kiosk-mode-t4995.html[/spoiler]
Updates:
2018/12/29: updated python script to pause music (if playing) when turning off backlight and resume when turning back on
2019/01/01: added gamma correction for LED brightness to make it look smoother
2019/01/02: warning about changing positions of volume and track
2019/01/06: Updated to remove Chromium restore pages dialog if it doesn’t get closed correctly on shutdown/reboot
2019/01/11: Added section to install the on screen keyboard “matchbox-keyboard”
2019/01/12: Updated python script to turn off screen when paused for a given amount.
2019/02/02: Removed bug where playback didn’t resume after turning off the backlight manually (thanks to ReM.2311for finding it). Added ability to easy change the backlight levels with the “User Variables” section. All 3 settings can be adjust to what ever is preferred. Mutes audio on pause and un-mutes on playback (again thanks to ReM.2311 for the suggestion!)
Old Script
[spoiler][code][code]#!/bin/python
import RPi.GPIO as GPIO
import time
import rpi_backlight as bl
import subprocess
import os
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.setup(13, GPIO.OUT)
led = GPIO.PWM(13, 2000)
led.start(100)
ledLvl = 100
ledDir = 0
buttonState = 0 		#current button state
lastButtonState = 0		#previous button state
timePressed = 0			#when was button pressed
lastBrightness = 0		#brightness when backlight turned off
lastStatus = “”			#was the volumio playing when turning off screen
blState = 2				#current bl level
bl.set_power(True)		#turn on bl
bl.set_brightness(64, smooth = True, duration = 1) #set bl level
gamma = 2.8				#gamma adjust for LED (makes breathing more consistant)
max_in = 100.0			#the maximum level to call for adjustment
max_out = 100.0			#the maximum level for PWM (100 for RPi)
levelOutput = 0.0		#variable to hold the adjusted level output
while 1: #repeat continously
buttonState = 1 - GPIO.input(26) #invert state due to pullup
if (buttonState == 1 and lastButtonState == 0): #button pressed
	timePressed = time.time() #store time button pressed
	
elif (buttonState == 1 and lastButtonState == 1): #button held
	if (time.time() - timePressed > 2): #if held for more than two seconds turn off bl
		status = subprocess.check_output("volumio status | sed -e 's/true/True/g' -e 's/false/False/g' -e 's/null/False/g'", shell=True)
		status = eval(status)
		if (status["status"] == "play"):
			os.system("volumio pause")
			lastStatus = "play"
		lastBrightness = blState #store current bl level
		blState = 0 #set bl level to off
		bl.set_brightness(11, smooth = True, duration = 1) #reduce bl down
		bl.set_power(False) #turn bl off
		ledLvl = 100
		ledDir = 0
		
elif (buttonState == 0 and lastButtonState == 1): #button released
	if (time.time() - timePressed <= 2): #if button released before two seconds passed change brightness
		if (lastBrightness > 0): #determines if bl was off and reset to bl level before turning off
			blState = lastBrightness
			lastBrightness = 0 #reset
			if (lastStatus == "play"):
				os.system("volumio play")
				lastStatus = ""
		else: #other wise go to next bl level
			blState = blState - 1
	
		if (blState < 1): #roll-over
			blState = 3
		
		#next section sets current level. Change the first number in bl.set_brightness between 11-255 if
		#other brightness levels required. Ignore the blState == 0.
		if (blState == 0):
			bl.set_brightness(11, smooth = True, duration = 1)
			bl.set_power(False)
		elif (blState == 1):
			bl.set_power(True)
			bl.set_brightness(32, smooth = True, duration = 1)
		elif (blState == 2):
			bl.set_power(True)
			bl.set_brightness(64, smooth = True, duration = 1)
		elif (blState == 3):
			bl.set_power(True)
			bl.set_brightness(192, smooth = True, duration = 1)
elif (buttonState == 0 and lastButtonState == 0): #button not pressed
	if (blState == 0):										#backlight if off, 'breath' the LED
		levelOutput = ((ledLvl/max_in) ** gamma) * max_out	#gamma calculation
		if (levelOutput > 100): levelOutput = 100			#clamp output to max PWM level (100 for RPi)
		
		if (ledDir == 0):									#ramp intensity down
			led.ChangeDutyCycle(levelOutput)				#set PWM output from gamma corrected level
			ledLvl = ledLvl - 1								#reduce brightness for next pass
			if (ledLvl == 1):								#when brightness at lowest point (not 0 as LED goes off and looks odd)
				ledDir = 1									#switch brightness direction to increase
		else:												#ramp intensity up
			led.ChangeDutyCycle(levelOutput)
			ledLvl = ledLvl + 1
			if (ledLvl == 100):								#switch direction when at max brightness
				ledDir = 0
	else:
		led.ChangeDutyCycle(100)
	time.sleep(0.05)										#if no button being pressed sleep for 50mSec - prevents loading a thread
lastButtonState = buttonState #store current button state to determine if button still being pressed or not.
[/code][/code][/spoiler]
 I have left the case naked. Where I have mine you can’t see behind it so looks clean. It also means I didn’t have to waste plastic lol
 I have left the case naked. Where I have mine you can’t see behind it so looks clean. It also means I didn’t have to waste plastic lol




