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.