I have created a scripted menu to enable me to quickly update a new Venus OS SD image installed on an SD card. I thought the community might find it useful.
What's the use case?
If I am going to test new release or intermediate version of Venus OS on my RPI 3B+ I want to be able to quickly configure the touch screen and other interfaces when I set up a new card. It is possible to store changes you want on the /data partition of a Venus OS Rpi SD card but getting at SD cards mounted in the touch screen case is tricky as it involves disassembling the Rpi and screen case. So I wanted to do this using an USB memory stick which is easy to insert and remove.
Also I'm dreadful at typing accurately when I'm eager to try out a new feature so this script does all the typing for me and checks the errors that might occur and tells me about them.
What does this do ?
It enables quick configuration of a new Venus OS install to support:
- 7" Touch screen (800x480 or 480x272)
- Screen rotation dependent on how you are going to mount it
- Headless on and off (needed for calibration)
- Calibrate touch screen
- Enable mcp3208 analogue interface on Sio (as per Venus GX)
- Screen backlight dimming
- Screen auto power off
- Enable i2c interface
- Enable the inbuilt Venus OS Web server to serve python scripts
The script is interactive and incorporates everything I have gleaned from other posts in this forum and in other places on the internet. I have written most of the logic out long hand and using if-then-else and case statements without too many obscure code contractions - it could easily be significantly reduced in size but would probably be less readable or maintainable by others if It was.
Here's an example of what it looks like:

The full script is included below. Quite a bit of it works stand alone and uses the necessary wget and opkg installs to pull the right modules and packages from the internet. There are some items I have not been able to find on the internet and these need to be in a directory called 'restore' in the same directory as the script.
These resources are:
/restore/mcp3208-overlay.dtb
/restore/rpi-backlight-overlay.dtb
/restore/dbus-adc
/restore/start-gui-800x480.sh
/restore/start-gui-480x272.sh
The script has been tested as I use it, so I have confirmed that no other lines, programmes, commands or resources are needed for this work on a Venus OS Rpi.
I have created a zip file with these resources and including the script file, the zip file is available on my own web server here. (the version of the script in the zip image is out of date the version in the article her is up to date (5/5/2020).
How to use it:
Download the zip file put it on a USB memory stick.
Plug this into your Venus OS RPi and locate the memory stick which will be something like : /run/media/sda1
the exact device will depend on where you plug it in.
Open the storage device:
cd /run/media/sda1
unzip venus-rpi.zip
Unzipping on the target machine (not on a MAC or windows PC) should preserve the file setting and attributes well enough for the purpose here.
cd venus-rpi-setup
Run the script
./setup-menu.sh
#!/bin/sh
# sample.mnu
# Menu to allow selected setup of rasperry pi features on Venus os install.
# This currently assumes you want to use the official Raspberry pi 7" screen
#
# this is written in a structured manner but is written long hand
# without fancy lopps, arrays, or constructions the rational for this is
# to enable others to extend, modify and debug it without too much obscure code
#
#------------------------------------------------------
# MENU FUNCTION DEFINITIONS
#------------------------------------------------------
# define a function to highlight the choice
#
# funtion defined to mark the chosen function in the menu display
mark () {
if [ "${answer^}" = "$1" ] ; then echo -n "* " ; marked=1 ; else echo -n " " ; fi }
#
# Define a function for invalid menu picks
# The function loads an error message into a variable
badchoice () { MSG="Invalid Selection ... Please Try Again" ; }
# For each prompt displayed, there is a list of
# commands to execute in response to the user picking the
# associated letter. Each is defined as a function.
# Eech function defines the list of actions to be executed,
# and attempts to catch possible common errors.
execute () {
#echo "execute entered with" $1
case $1 in
H) headless;;
O) headlessoff;;
D) displayDrivers;;
U) upsidedown ;;
8) changeto800;;
4) changeto480;;
S) dimming;;
T) timer;;
A) analogue;;
I) i2c;;
R) systemreboot;;
P) webpython ;;
C) calibrate;;
Q) exit;;
*) badchoice;;
esac
echo "action complete press any key to continue"
read -rsn 1 jim
MSG=""
}
headless () {
if [ -f /etc/venus/headless.off ]; then
echo "headless is off - switching to headless"
mv /etc/venus/headless.off /etc/venus/headless
REBOOT=1
else
if [ -f /etc/venus/headless ]; then
echo "headless already configured - no change made"
else
echo "no headless configuration found - enabling headless"
touch /etc/venus/headless
REBOOT=1
fi
fi ; }
headlessoff () {
if [ -f /etc/venus/headless ]; then
echo "headless is enabled - switching to headless off"
mv /etc/venus/headless /etc/venus/headless.off
REBOOT=1
else
if [ -f /etc/venus/headless.off ]; then
echo "headless already off - no change made"
else
echo "no headless configuration found - switching headless off"
touch /etc/venus/headless.off
REBOOT=1
fi
fi ; }
displayDrivers () {
echo "This will execute opkg commands, an internet connection is required do you have one (y/n)?"
read -s -N 1 key
case $key in
y|Y)
echo "Package install will continue"
echo "opkg update"
opkg update 2>&1
echo "install mousedriver"
opkg install qt4-embedded-plugin-mousedriver-tslib 2>&1
echo "install-tslib-calibrate"
opkg install tslib-calibrate 2>&1
echo "install tslib-conf"
opkg install tslib-conf 2>&1
echo "install tslib-tests"
opkg install tslib-tests 2>&1
# update config.txt
echo "Upating config.txt"
grep -q 'framebuffer_width=[0-9][0-9][0-9]' /u-boot/config.txt
if [ $? -eq 0 ] ; then
echo "Frame buffer already configured in config.txt no change made"
else
echo 'framebuffer_width=800' >> /u-boot/config.txt
echo 'framebuffer_height=480' >> /u-boot/config.txt
echo "Config.txt file updated"
fi
REBOOT=1
;;
*)
echo "Cannot proceed without internet connection"
;;
esac ; }
changeto800 () {
echo "install replacement start GUI file"
cp -p $dir/restore/start-gui-800x480.sh /opt/victronenergy/gui/start-gui.sh 2>&1
if [ $? -eq 0 ] ; then
echo "installed modified strat-gui.sh file"
else
echo "failed to install modified start-gui.sh file"
fi
echo "Upating config.txt"
grep -q 'framebuffer_width=[0-9][0-9][0-9]' /u-boot/config.txt
if [ $? -eq 0 ] ; then
sed -i 's/framebuffer_width=[0-9][0-9][0-9]/framebuffer_width=800/' /u-boot/config.txt
sed -i 's/framebuffer_height=[0-9][0-9][0-9]/framebuffer_height=480/' /u-boot/config.txt
echo "Config.txt file updated"
else
echo "Frame buffer config not found in config.txt no change made"
fi
echo "remember to recalibrate the touch screen if you have changed screen size"
REBOOT=1 ; }
changeto480 () {
echo "install replacement start GUI file"
cp -p $dir/restore/start-gui-480x272.sh /opt/victronenergy/gui/start-gui.sh 2>&1
if [ $? -eq 0 ] ; then
echo "Installed modified start-gui.sh file"
else
echo "failed to install modified start-gui.sh file"
fi
echo "Upating config.txt"
grep -q 'framebuffer_width=[0-9][0-9][0-9]' /u-boot/config.txt
if [ $? -eq 0 ] ; then
sed -i 's/framebuffer_width=[0-9][0-9][0-9]/framebuffer_width=480/' /u-boot/config.txt
sed -i 's/framebuffer_height=[0-9][0-9][0-9]/framebuffer_height=272/' /u-boot/config.txt
echo "Config.txt file updated"
else
echo "Frame buffer configuration not found in config.txt no change made"
fi
echo "remember to recalibrate the touch screen if you have changed screen size"
REBOOT=1 ; }
calibrate () {
echo "Make sure headless is enable and the system rebooted - you can't calibrate a screen with the GUI on"
echo "If the screen blanking time has switched off the screen."
echo "You can still change this by accessing the Venus OS GUI remote console with a browser"
echo "ready to start calbration (y/n)?"
read -s -N 1 key
case $key in
y|Y)
TSLIB_FBDEVICE=/dev/fb1
TSLIB_TSDEVICE=/dev/input/touchscreen0 ts_calibrate
;;
*)
echo "Calibration aborted - no changes made"
;;
esac ; }
dimming () {
echo "This will execute wget and opkg commands, an internet connection is required do you have one (y/n)?"
read -s -N 1 key
case $key in
y|Y)
echo "Overlay install will continue"
echo "/sys/class/backlight/rpi_backlight" > /etc/venus/backlight_device
if [ -f /u-boot/overlays/rpi-backlight-overlay.dtb ] ; then
echo "backlight dtb overlay already exists - this will not be replaced"
else
echo "fetching overlay file"
wget https://github.com/PiNet/PiNet-Boot/raw/master/boot/overlays/rpi-backlight-overlay.dtb 2>&1
echo $dir/rpi-backlight-overlay.dtb
mv $dir/rpi-backlight-overlay.dtb /u-boot/overlays
fi
echo "fetching kernel module"
opkg install kernel-module-rpi-backlight 2>&1
REBOOT=1
;;
*)
echo "No changes made without internet connection"
# an alternatie might be to install a copy of the overlay from the /data/recover directory
;;
esac ; }
timer () {
echo "/sys/class/backlight/rpi_backlight/bl_power" > /etc/venus/blank_display_device
}
analogue () {
if [ -f /u-boot/overlays/mcp3208-overlay.dtb ]; then
echo "mcp3208 overlay file already exists no change made"
else
cp -p $dir/restore/mcp3208-overlay.dtb /u-boot/overlays
if [ $? -eq 0 ] ; then
echo "mcp3208 overlay file installed"
else
echo "Failed to install mcp3208 overlay file"
fi
REBOOT=1
fi
if [ -d //opt/victronenergy/dbus-adc ]; then
echo "dbus-adc device interfaces already exist no changes made to drivers"
else
cp -pr $dir/restore/dbus-adc /opt/victronenergy
if [ $? -eq 0 ] ; then
echo "dbus-adc service files installed in /opt/victronenergy"
else
echo "Failed install dbus-service files"
fi
REBOOT=1
fi
grep -q 'dtoverlay=mcp3208:spi0-0-present' /u-boot/config.txt
if [ $? -eq 0 ] ; then
echo "config.txt alread configured for MCP3208 analogue interface no changes made to config.txt"
else
echo 'dtoverlay=mcp3208:spi0-0-present' >> /u-boot/config.txt
echo "Config.txt updated for analogue interface"
fi
touch /var/log/dbus-adc
ln -s /opt/victronenergy/dbus-adc/service /service/dbus-adc
REBOOT=1 ; }
i2c () {
grep -q 'dtparam=i2c_arm=on' /u-boot/config.txt
if [ $? -eq 0 ] ; then
echo "config.txt alread configured for i2c interface no changes made to config.txt"
else
echo 'dtparam=i2c_arm=on' >> /u-boot/config.txt
echo "Config.txt updated for i2c interface"
REBOOT=1
fi
grep -q 'modprobe i2c-dev' /data/rc.local
if [ $? -eq 0 ] ; then
echo "rc.local already configured to start i2c interface no changes made to rc.local"
else
echo 'modprobe i2c-dev' >> /data/rc.local
chmod +x /data/rc.local
echo "/data/rc.local updated for i2c interface"
REBOOT=1
fi ; }
systemreboot () {
#crafty way of shutting down the script while rebooting
exec reboot
}
upsidedown () {
grep -q "lcd_rotate=2" /u-boot/config.txt
if [ $? -eq 0 ] ; then
echo "Screen is already inverted reverto no normal (y/n)"
read -s -N 1 key
case $key in
y|Y)
sed -i 's/lcd_rotate=2//' /u-boot/config.txt
;;
*)
echo "No change made"
;;
esac
else
echo "Configureing /u-boot/config.txt to invert screen"
echo "lcd_rotate=2" >> /u-boot/config.txt
fi ; }
webpython () {
grep -q "CGIhandler = /usr/bin/python:py" /etc/hiawatha/hiawatha.conf
if [ $? -eq 0 ] ; then
sed -i 's%#CGIhandler = /usr/bin/python:py%CGIhandler = /usr/bin/python:py%' /etc/hiawatha/hiawatha.conf
echo "/usr/bin/python:py updated to enable python"
else
echo "File or CGIhandler configuration missing in /etc/hiawatha/hiawatha.conf - no changes made"
fi
REBOOT=1 ; }
#------------------------------------------------------
# DISPLAY MENU
#------------------------------------------------------
# This function displays the menu.
# The routine clears the screen, echoes
# the menu prompts and any additional messages.
# Note that this definition does not cause the menu to
# be executed, it just defines, it ready to be executed.
themenu () {
# clear the screen
clear
echo `date`
echo
echo -e "\t Venus os Raspberry pi configure functions"
echo
echo -e "\t\t\t Please Select"
echo -e $(dirname $0)
marked=0
#
# this line is a placeholder for a function which calls most of the other functions - not yet implemented
#echo -en "\t\t\t" ; mark E ; echo "(E)verything (i2c, Analogue, Headless, 800x400, except calibrate screen) " ;
#
echo -en "\t\t\t" ; mark H ; echo "(H)eadless - used when calibrating ";
echo -en "\t\t\t" ; mark O ; echo "(O) Headless (O)ff - enable RPI Screen ";
echo -en "\t\t\t" ; mark D ; echo "(D)isplay drivers 800x480 ";
echo -en "\t\t\t" ; mark C ; echo "(C)alibrate touch screen ";
echo -en "\t\t\t" ; mark U ; echo "(U)pside down touch screen ";
echo -en "\t\t\t" ; mark 8 ; echo "(8) change to 800x480 resolution ";
echo -en "\t\t\t" ; mark 4 ; echo "(4) change to 480x272 resolution ";
echo -en "\t\t\t" ; mark S ; echo "(S)creen dimming interface ";
echo -en "\t\t\t" ; mark T ; echo "(T)imer display shut off ";
echo -en "\t\t\t" ; mark A ; echo "(A)nalogue mcp3208 spi interface drivers ";
echo -en "\t\t\t" ; mark I ; echo "(I)2c enable i2c interfaces ";
echo -en "\t\t\t" ; mark R ; echo "(R)eboot Venus OS ";
echo -en "\t\t\t" ; mark P ; echo "(P) Web server: enable (P)ython scripts ";
echo -en "\t\t\t" ; mark Q ; echo "(Q)uit ";
echo
((!marked)) && badchoice # flag up bad selections
echo $MSG
((REBOOT)) && echo "A reboot will be required to implement changes" || echo
echo
echo "Select by pressing the letter and then ENTER to execute commands";
}
#------------------------------------------------------
# MAIN EXECUTION
#------------------------------------------------------
# Clear out the error
MSG=
# changes to true iff we do somthoing that needs a reboot
REBOOT=0
# find out where we are
dir=$(dirname $0)
# Repeat the menu over and over
# Steps are:
# 1. Display the menu
# 2. 'read' a key of input from the key board
# 3. Clear the error message
# 4. if the user pressed return dispatch valid entries for execution
# to the appropriate function or exit
# 5. Set error message for invalid options
while true
do
# 1. display the menu by calling the function
# this includes display the last error mesaage if ther is one
themenu
# 2. read a character of input from the keyboard by a command
read -s -N 1 key
# 3. Clear any error message
MSG=
#
#if they press [ENTER] then go and do it
if [[ "$key" == $'\x0a' ]] ; then
execute "$answer"
else
#
# They did not press return so remember the key they pressed
#
answer=${key^} # make sure answer is upper case to aid case statements
# Do it again until the user selects the exit option
fi
done
This was developed against Venus OS 2.42 and test against Venus OS 2.51 today 2nd March 2020.

Version 2.60