#!/bin/bash do { #//////////////////////////////////// # DietPi Cloudshell # #//////////////////////////////////// # Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com # #//////////////////////////////////// # # Info: # - System Stats for Cloudshell (or monitor/terminal) # # Usage: # dietpi-cloudshell = Config Menu # dietpi-cloudshell 1 = Run # dietpi-cloudshell 2 = Run + Skip intro #//////////////////////////////////// #Grab Input (valid interger) setglobal INPUT = '0' if [[ $1 =~ ^-?[0-9]+$ ]] { setglobal INPUT = $1 } #Import DietPi-Globals --------------------------------------------------------------- source /DietPi/dietpi/func/dietpi-globals G_CHECK_ROOT_USER export G_PROGRAM_NAME='DietPi-Cloudshell' #Import DietPi-Globals --------------------------------------------------------------- #Version setglobal DIETPI_CLOUDSHELL_VERSION = '9' #/tmp/.* files used throughout this script. setglobal FP_TEMP = '"/tmp/dietpi-cloudshell'" setglobal PROGRAM_NAME = '"DietPi-Cloudshell'" setglobal BLANK_SCREEN_ACTIVE = '0' setglobal BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED = '0' setglobal BLANK_SCREEN_TIME_HOUR_START = '0' setglobal BLANK_SCREEN_TIME_HOUR_END = '0' #This will only work if dietpi-cloudshell was started by autostart (login script), as the setterm power options can only be applied when the command originates from the same terminal (no redirects). proc RUN_BLANK_SCREEN_AT_SPECIFIC_TIME{ local current_hour=$[date +%-H] #Turn screen off if sh-expr ' ! $BLANK_SCREEN_ACTIVE ' { if sh-expr ' $BLANK_SCREEN_TIME_HOUR_START == $current_hour ' { clear echo -e "\n\nScreen will be powered down in under 1 minute\n" setterm --blank 1 --powersave on &> /dev/tty1 #blank after 1 minute as force requires a poke to bring it back up. setglobal BLANK_SCREEN_ACTIVE = '1' } #Turn screen on } elif sh-expr ' $BLANK_SCREEN_TIME_HOUR_END == $current_hour ' { setterm --blank poke &> /dev/tty1 setterm --reset &> /dev/tty1 setterm --blank 0 --powersave off &> /dev/tty1 setglobal BLANK_SCREEN_ACTIVE = '0' } } #BC does not allow for printing leading zeros. proc BC_ADD_LEADING_ZERO{ #$1 = string input local return_value=$1 #BC - Add leading zero to start of .* string. # +0 if test $(return_value:0:1) = "." { setglobal return_value = ""0$return_value"" # -0 } elif test $(return_value:0:2) = "-." { setglobal return_value = $[echo -e $return_value | sed 's/^-./-0./] } echo $return_value } #Converts a byte int to string, in human readable byte format. proc BYTE_PRINT_CONVERSION{ local return_value=0 local decimal_count=1 #$1=byte value # - KB if sh-expr ' $1 < 1048576 ' { #return_value="$(( $1 / 1024 )) KB" setglobal return_value = ""$[echo "scale=$decimal_count; $1 / 1024" | bc -l] KB"" # - MB } elif sh-expr ' $1 < 1073741824 ' { #return_value="$(( $1 / 1024 / 1024 )) MB" setglobal return_value = ""$[echo "scale=$decimal_count; $1 / 1024 / 1024" | bc -l] MB"" # - GB } else { #return_value="$(( $1 / 1024 / 1024 / 1024 )) GB" setglobal return_value = ""$[echo "scale=$decimal_count; $1 / 1024 / 1024 / 1024" | bc -l] GB"" } #BC - Add leading zero to start of .* string. setglobal return_value = $[BC_ADD_LEADING_ZERO $return_value] echo $return_value } #Converts a byte int to string, in human readable bit format. # - for network data transmission rate (LAN, WLAN, ...) # - 1MB = 8Mbit | 1Mbit = 0.125MB proc BIT_PRINT_CONVERSION{ local return_value=0 local decimal_count=1 #$1=byte value # - Kbit if sh-expr ' $1 < 1000000 ' { #return_value="$(( $1 * 8 / 1000 )) Kbit" setglobal return_value = ""$[echo "scale=$decimal_count; $1 * 8 / 1000" | bc -l] Kbit"" # - MBit } elif sh-expr ' $1 < 1000000000 ' { #return_value="$(( $1 * 8 / 1000 / 1000 )) Mbit" setglobal return_value = ""$[echo "scale=$decimal_count; $1 * 8 / 1000 / 1000" | bc -l] Mbit"" # - GBit } else { #return_value="$(( $1 * 8 / 1000 / 1000 / 1000 )) Gbit" setglobal return_value = ""$[echo "scale=$decimal_count; $1 * 8 / 1000 / 1000 / 1000" | bc -l] Gbit"" } #BC - Add leading zero to start of .* string. setglobal return_value = $[BC_ADD_LEADING_ZERO $return_value] echo $return_value } #Apply fonts proc Enable_Term_Options{ # - Set large font 1st (480x320+) setfont /usr/share/consolefonts/Uni3-TerminusBold32x16 # - set small font if insufficent number of lines (320x240) if sh-expr ' $(tput lines) < 10 ' { setfont /usr/share/consolefonts/Uni3-TerminusBold24x12.psf } } #///////////////////////////////////////////////////////////////////////////////////// # Colours #///////////////////////////////////////////////////////////////////////////////////// setglobal C_RESET = '"\e[0m'" setglobal C_REVERSE = '"\e[7m'" #C_BOLD makes normal text "brighter" setglobal C_BOLD = '"\e[1m'" #Colour array #0 WHITE #1 RED #2 GREEN #3 YELLOW #4 BLUE #5 PURPLE #6 CYAN #7 TEST setglobal aCOLOUR = ''( "\e[39m" "\e[31m" "\e[32m" "\e[33m" "\e[34m" "\e[35m" "\e[36m" "\e[93m" ) #user colour setglobal USER_COLOUR_INDEX = '3' setglobal C_PERCENT_GRAPH = '0' proc Percent_To_Graph{ #$1 = int/float 0-100 #$C_PERCENT_GRAPH = return text #Convert to int local input_value=$[echo $1 | cut -d. -f1] #Cap input value if sh-expr ' $input_value > 100 ' { setglobal input_value = '100' } elif sh-expr ' $input_value < 0 ' { setglobal input_value = '0' } #Work out a percentage based graph #18 step split (18 / 100) if sh-expr ' $input_value >= 95 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[1])------WARNING-----$C_RESET]"" } elif sh-expr ' $input_value >= 90 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[1])-----------------$C_RESET-]"" } elif sh-expr ' $input_value >= 88 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[1])----------------$C_RESET--]"" } elif sh-expr ' $input_value >= 82 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[1])---------------$C_RESET---]"" } elif sh-expr ' $input_value >= 76 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[3])--------------$C_RESET----]"" } elif sh-expr ' $input_value >= 70 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[3])-------------$C_RESET-----]"" } elif sh-expr ' $input_value >= 64 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[3])------------$C_RESET------]"" } elif sh-expr ' $input_value >= 56 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[3])-----------$C_RESET-------]"" } elif sh-expr ' $input_value >= 50 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[3])----------$C_RESET--------]"" } elif sh-expr ' $input_value >= 44 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[3])---------$C_RESET---------]"" } elif sh-expr ' $input_value >= 38 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])--------$C_RESET----------]"" } elif sh-expr ' $input_value >= 32 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])-------$C_RESET-----------]"" } elif sh-expr ' $input_value >= 26 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])------$C_RESET------------]"" } elif sh-expr ' $input_value >= 20 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])-----$C_RESET-------------]"" } elif sh-expr ' $input_value >= 15 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])----$C_RESET--------------]"" } elif sh-expr ' $input_value >= 10 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])---$C_RESET---------------]"" } elif sh-expr ' $input_value >= 5 ' { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])--$C_RESET----------------]"" } else { setglobal C_PERCENT_GRAPH = "" $input_value% [$C_REVERSE$(aCOLOUR[2])-$C_RESET-----------------]"" } } #///////////////////////////////////////////////////////////////////////////////////// # Obtain Stat Data #///////////////////////////////////////////////////////////////////////////////////// setglobal TEMPERATURE_CONVERSION_VALUE = '0' proc Obtain_Temperature_Conversion{ if sh-expr ' $TEMPERATURE_OUTPUT_TYPE == 0 ' { setglobal TEMPERATURE_CONVERSION_VALUE = $[awk "BEGIN {printf \"%.0f\",$TEMPERATURE_CONVERSION_VALUE * 1.8 + 32"}] setglobal TEMPERATURE_CONVERSION_VALUE = '"'f'" } else { setglobal TEMPERATURE_CONVERSION_VALUE = '"'c'" } } setglobal DATE_TIME = '0' proc Obtain_DATE_TIME{ setglobal DATE_TIME = $[date +"%a %x - %R] } setglobal UPTIME = '0' proc Obtain_UPTIME{ local fSeconds=$[cat /proc/uptime | awk '{print $1}] local seconds=$(fSeconds%.*) local minutes=0 local hours=0 local days=0 while sh-expr ' $seconds >= 60 ' { sh-expr 'minutes++' setglobal seconds = $shExpr(' $seconds - 60 ') } while sh-expr ' $minutes >= 60 ' { sh-expr 'hours++' setglobal minutes = $shExpr(' $minutes - 60 ') } while sh-expr ' $hours >= 24 ' { sh-expr 'days++' setglobal hours = $shExpr(' $hours - 24 ') } setglobal UPTIME = ""Uptime: $days Day, $hours Hour"" } #CPU setglobal CPU_GOV = '0' setglobal CPU_TEMP = '0' setglobal C_CPUTEMP = '0' setglobal CPU_FREQ_1 = '0' setglobal CPU_FREQ_2 = '0' setglobal CPU_USAGE = '0' setglobal CPU_TOTALPROCESSES = '0' proc Obtain_CPU{ setglobal CPU_TOTALPROCESSES = $shExpr(' $(ps --ppid 2 -p 2 --deselect | wc -l) - 2 ') # - ps process and descriptions. setglobal CPU_GOV = $[cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor] setglobal CPU_TEMP = $[G_OBTAIN_CPU_TEMP] if [[ $CPU_TEMP =~ ^-?[0-9]+$ ]] { #Obtain colour for temps if sh-expr ' $CPU_TEMP >= 65 ' { setglobal C_CPUTEMP = $(aCOLOUR[1]) } elif sh-expr ' $CPU_TEMP >= 50 ' { setglobal C_CPUTEMP = $(aCOLOUR[3]) } elif sh-expr ' $CPU_TEMP >= 35 ' { setglobal C_CPUTEMP = $(aCOLOUR[2]) } else { setglobal C_CPUTEMP = $(aCOLOUR[4]) } #Set 'c or 'f output setglobal TEMPERATURE_CONVERSION_VALUE = $CPU_TEMP Obtain_Temperature_Conversion setglobal CPU_TEMP = $TEMPERATURE_CONVERSION_VALUE } setglobal CPU_FREQ_1 = $shExpr(' $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq) / 1000 ') setglobal CPU_FREQ_2 = '"N/A'" #Unique additional freq readout for Odroid XU4 (octo, 2nd quad set) if sh-expr ' $G_HW_MODEL == 11 ' { setglobal CPU_FREQ_2 = $shExpr(' $(cat /sys/devices/system/cpu/cpu4/cpufreq/scaling_cur_freq) / 1000 ') } setglobal CPU_USAGE = '0' setglobal FP_TEMP = '"/tmp/.cpu_usage'" # PS (inaccurate) ps -axo %cpu | sed '1d' | sed 's/ //' > $FP_TEMP while read -r line { setglobal CPU_USAGE = $[ echo "scale=1;$CPU_USAGE + $line" | bc -l] } < $FP_TEMP #ps returns usage of each core, so we devide the total by #n cores setglobal CPU_USAGE = $[echo "scale=0;$CPU_USAGE / $G_HW_CPU_CORES" | bc -l] # TOP (accurate) # Fails to output in low screen res (https://github.com/Fourdee/DietPi/issues/203#issuecomment-189711968) # CPU_USAGE=$(BC_ADD_LEADING_ZERO "$(echo "scale=1; 100 - $(top -b -n 1 | grep '%Cpu(s):' | awk '{print $8}')" | bc -l)") #convert to interger and graph it Percent_To_Graph $CPU_USAGE setglobal CPU_USAGE = $C_PERCENT_GRAPH } #Storage # - array setglobal MAX_STORAGE = '6' setglobal STORAGE_TOTAL = ''() setglobal STORAGE_USED = ''() setglobal STORAGE_FREE = ''() setglobal STORAGE_PERCENT = ''() setglobal STORAGE_PATH = ''() setglobal STORAGE_NAME = ''() proc Init_STORAGE{ for ((i=0; i<$MAX_STORAGE; i++)) do STORAGE_TOTAL[$i]='N/A' STORAGE_USED[$i]='N/A' STORAGE_FREE[$i]='N/A' STORAGE_PERCENT[$i]=' Not installed' STORAGE_NAME[$i]=0 # 0 reserved for flash storage if (( $i == 0 )); then STORAGE_PATH[$i]='/' STORAGE_NAME[$i]='Flash/RootFS Storage: ' else STORAGE_PATH[$i]="/mnt/usb_$i" STORAGE_NAME[$i]="Storage $i: " fi done } proc Destroy_STORAGE{ unset STORAGE_TOTAL unset STORAGE_USED unset STORAGE_FREE unset STORAGE_PERCENT unset STORAGE_PATH unset STORAGE_NAME } # $1 $2 = Range of indexs to update (eg: 0-1) proc Obtain_STORAGE{ local index_start=$1 local index_end=$2 setglobal FP_TEMP = '"/tmp/.df'" rm $FP_TEMP #df will endless hang when NFS server is down: https://github.com/Fourdee/DietPi/issues/395 # - So lets run it as another thread so we can kill it if it hangs. local df_failed=0 df -Ph > $FP_TEMP & local pid=$[echo $BgPid] # - Wait X seconds before terminating the df thread local max_seconds=4 local current_seconds=0 while (( $(ps aux | awk '{print $2}' | grep -ci -m1 "$pid$") )) # ! -f may exist, but no data at time of scrape, causing 'mount not found'. so lets wait for process to exit. { if sh-expr ' $current_seconds >= $max_seconds ' { #kill G_DIETPI-NOTIFY 1 "DF failed, unable to obtain drive data" sleep 2 kill $pid setglobal df_failed = '1' echo -e "$[date] | df failed to respond" >> /var/log/dietpi-cloudshell.log break } else { sleep 1 sh-expr 'current_seconds++' } } if sh-expr ' $df_failed ' { for ((i=$index_start; i<=$index_end; i++)) do STORAGE_PERCENT[$i]="${STORAGE_PATH[$i]}" STORAGE_FREE[$i]='DF failed' done } else { for ((i=$index_start; i<=$index_end; i++)) do if (( $(cat $FP_TEMP | grep -ci -m1 "${STORAGE_PATH[$i]}$") )); then STORAGE_TOTAL[$i]=$(cat $FP_TEMP | grep -m1 "${STORAGE_PATH[$i]}$" | awk '{print $2}'); STORAGE_TOTAL[$i]+='B' STORAGE_USED[$i]=$(cat $FP_TEMP | grep -m1 "${STORAGE_PATH[$i]}$" | awk '{print $3}'); STORAGE_USED[$i]+='B' STORAGE_FREE[$i]=$(cat $FP_TEMP | grep -m1 "${STORAGE_PATH[$i]}$" | awk '{print $4}'); STORAGE_FREE[$i]+='B' STORAGE_PERCENT[$i]=$(cat $FP_TEMP | grep -m1 "${STORAGE_PATH[$i]}$" | awk '{print $5}' | sed 's/%//g') Percent_To_Graph ${STORAGE_PERCENT[$i]} STORAGE_PERCENT[$i]=$C_PERCENT_GRAPH #DEBUG John: echo -e "Results success:\n" >> /var/log/dietpi-cloudshell.log echo -e " - Index = $i" >> /var/log/dietpi-cloudshell.log echo -e " - Path = ${STORAGE_PATH[$i]}" >> /var/log/dietpi-cloudshell.log echo -e " - Total = ${STORAGE_TOTAL[$i]}" >> /var/log/dietpi-cloudshell.log else STORAGE_PERCENT[$i]="${STORAGE_PATH[$i]}" STORAGE_FREE[$i]='Mount not active' #DEBUG John: echo -e "$(date) | Mount not found:\n" >> /var/log/dietpi-cloudshell.log echo -e " - Index = $i" >> /var/log/dietpi-cloudshell.log echo -e " - Path = ${STORAGE_PATH[$i]}\n" >> /var/log/dietpi-cloudshell.log cat "$FP_TEMP" >> /var/log/dietpi-cloudshell.log echo -e "\n" >> /var/log/dietpi-cloudshell.log fi done } } #DietPi setglobal DIETPI_VERSION_CURRENT = '0' setglobal DIETPI_UPDATE_AVAILABLE = '0' setglobal DIETPI_WEBSITE = ''dietpi.com'' setglobal DIETPI_TWITTER = '"@dietpi_'" setglobal DIETPI_HW_DESCRIPTION = '"N/A'" proc Obtain_DIETPIINFO{ #DietPi version setglobal DIETPI_VERSION_CURRENT = ""$(aCOLOUR[2])$[sed -n 1p /DietPi/dietpi/.version].$[sed -n 2p /DietPi/dietpi/.version]$C_RESET"" #Current HW setglobal DIETPI_HW_DESCRIPTION = $[sed -n 2p /DietPi/dietpi/.hw_model] #DietPi-Update available? setglobal DIETPI_UPDATE_AVAILABLE = '"N/A'" if test -f /DietPi/dietpi/.update_available { #Set current version to red setglobal DIETPI_VERSION_CURRENT = ""$(aCOLOUR[1])$[sed -n 1p /DietPi/dietpi/.version].$[sed -n 2p /DietPi/dietpi/.version]$C_RESET"" local update_version=$[cat /DietPi/dietpi/.update_available] if test $update_version = '-1' { setglobal DIETPI_UPDATE_AVAILABLE = ""$(aCOLOUR[2])New Image$C_RESET"" } else { setglobal DIETPI_UPDATE_AVAILABLE = ""$(aCOLOUR[2])$update_version$C_RESET"" } } } #Network Details setglobal NETWORK_DETAILS_ADAPTER = ''eth0'' setglobal NETWORK_DETAILS_IP_INT = '0' setglobal NETWORK_DETAILS_MAC_ADDRESS = '0' setglobal NETWORK_DETAILS_SIGNAL_STRENGTH = '0' setglobal NETWORK_DETAILS_DUPLEXSPEED = '0' setglobal NETWORK_DETAILS_HOSTNAME = '0' setglobal NETWORK_DETAILS_MODE = '0' #1=dhcp, 0=static proc Obtain_NETWORK_DETAILS{ setglobal FP_TEMP = '"/tmp/.ifconfig'" #Hostname setglobal NETWORK_DETAILS_HOSTNAME = $[hostname] #Active network adapater. setglobal NETWORK_DETAILS_ADAPTER = $[sed -n 3p /DietPi/dietpi/.network] #Mode (dhcp/static) if sh-expr ' $(cat /etc/network/interfaces | grep -ci -m1 "iface $NETWORK_DETAILS_ADAPTER inet dhcp") ' { setglobal NETWORK_DETAILS_MODE = '"Dhcp'" } else { setglobal NETWORK_DETAILS_MODE = '"Static'" } #Ifconfig to /tmp ifconfig $NETWORK_DETAILS_ADAPTER > $FP_TEMP #IP / MAC addresses setglobal NETWORK_DETAILS_IP_INT = $[cat $FP_TEMP | grep -m1 'inet '| cut -d: -f2 | awk '{ print $1}] setglobal NETWORK_DETAILS_MAC_ADDRESS = $[cat /sys/class/net/$NETWORK_DETAILS_ADAPTER/address] #Speed/Strength #Wifi if sh-expr ' $(echo $NETWORK_DETAILS_ADAPTER | grep -ci -m1 'wlan') == 1 ' { setglobal NETWORK_DETAILS_SIGNAL_STRENGTH = ""$[iwconfig $NETWORK_DETAILS_ADAPTER | grep -m1 'Signal level=' | awk '{ print $4 }' | sed 's/level=//g' | cut -f1 -d "/]%"" setglobal NETWORK_DETAILS_DUPLEXSPEED = ""$[iwconfig $NETWORK_DETAILS_ADAPTER | grep -m1 'Bit Rate:' | awk '{ print $2 }' | sed 's/Rate://g]Mbit"" #Lan } else { setglobal NETWORK_DETAILS_DUPLEXSPEED = ""$[cat /sys/class/net/$NETWORK_DETAILS_ADAPTER/speed] Mbit"" #NETWORK_DETAILS_DUPLEXSPEED=$(mii-tool | awk '{print $3}') setglobal NETWORK_DETAILS_SIGNAL_STRENGTH = '"N/A'" } } #Network Usage (all values are in bytes) setglobal NETWORK_USAGE_TOTAL_CURRENT_SENT = '0' setglobal NETWORK_USAGE_TOTAL_CURRENT_RECIEVED = '0' setglobal NETWORK_USAGE_NOW_CURRENT_SENT = '0' setglobal NETWORK_USAGE_NOW_CURRENT_RECIEVED = '0' setglobal NETWORK_USAGE_NOW_INIT = '0' setglobal NETWORK_USAGE_SECONDS_SINCE_LAST_UPDATE = '0' setglobal NETWORK_USAGE_DAY_CURRENT_SENT = '0' setglobal NETWORK_USAGE_DAY_CURRENT_RECIEVED = '0' setglobal NETWORK_USAGE_DAY_PREVIOUS_SENT = '0' setglobal NETWORK_USAGE_DAY_PREVIOUS_RECIEVED = '0' setglobal NETWORK_USAGE_DAY_OF_MONTH = '-1' proc Obtain_NETWORK_USAGE{ #Check for valid integer scrapes from netstat, before running calculations: http://dietpi.com/phpbb/viewtopic.php?f=11&t=441&p=1927#p1927 | https://github.com/Fourdee/DietPi/issues/355 local run_update=1 local mtu_size=$[netstat -N -i | grep $NETWORK_DETAILS_ADAPTER | awk '{print $2}] if [[ ! $mtu_size =~ ^-?[0-9]+$ ]] { setglobal run_update = '0' } local network_usage_current_recieved=$[netstat -N -i | grep $NETWORK_DETAILS_ADAPTER | awk '{print $4}] if [[ ! $network_usage_current_recieved =~ ^-?[0-9]+$ ]] { setglobal run_update = '0' } local network_usage_current_sent=$[netstat -N -i | grep $NETWORK_DETAILS_ADAPTER | awk '{print $8}] if [[ ! $network_usage_current_sent =~ ^-?[0-9]+$ ]] { setglobal run_update = '0' } if sh-expr ' $run_update == 1 ' { #Store previous totals local total_previous_sent=$NETWORK_USAGE_TOTAL_CURRENT_SENT local total_previous_recieved=$NETWORK_USAGE_TOTAL_CURRENT_RECIEVED #Update current totals setglobal NETWORK_USAGE_TOTAL_CURRENT_RECIEVED = $shExpr(' $network_usage_current_recieved * $mtu_size ') setglobal NETWORK_USAGE_TOTAL_CURRENT_SENT = $shExpr(' $network_usage_current_sent * $mtu_size ') #Current usage # - Work out seconds since last update local seconds_since_last_update=$shExpr(' $(date +%s) - $NETWORK_USAGE_SECONDS_SINCE_LAST_UPDATE ') # - Init - Override current usage to 0, on first run of scene. if sh-expr ' $NETWORK_USAGE_NOW_INIT == 0 ' { setglobal NETWORK_USAGE_NOW_CURRENT_SENT = '0' setglobal NETWORK_USAGE_NOW_CURRENT_RECIEVED = '0' setglobal NETWORK_USAGE_NOW_INIT = '1' # - Obtain current usage } else { setglobal NETWORK_USAGE_NOW_CURRENT_SENT = $shExpr(' ( $NETWORK_USAGE_TOTAL_CURRENT_SENT - $total_previous_sent ) / $seconds_since_last_update ') setglobal NETWORK_USAGE_NOW_CURRENT_RECIEVED = $shExpr(' ( $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED - $total_previous_recieved ) / $seconds_since_last_update ') } # - Update timestamp setglobal NETWORK_USAGE_SECONDS_SINCE_LAST_UPDATE = $[date +%s] # - Ifconfig to /tmp #ifconfig $NETWORK_DETAILS_ADAPTER > $FP_TEMP #/sys/class/net/ values are being reset by system/kernel when they reach X size. Some sort of "cap". #NETWORK_USAGE_TOTAL_CURRENT_SENT=$(( $(cat /sys/class/net/$NETWORK_DETAILS_ADAPTER/statistics/tx_bytes) / 1024 / 1024 )) #NETWORK_USAGE_TOTAL_CURRENT_RECIEVED=$(( $(cat /sys/class/net/$NETWORK_DETAILS_ADAPTER/statistics/rx_bytes) / 1024 / 1024 )) #Usage today # - Has the day changed? Also runs on init. # String if statement, to prevent "leading zero integer error" from $(date): https://github.com/Fourdee/DietPi/issues/272 local dayofmonth=$[date +"%d] if test $NETWORK_USAGE_DAY_OF_MONTH != $dayofmonth { #Update previous day values to current setglobal NETWORK_USAGE_DAY_PREVIOUS_SENT = $NETWORK_USAGE_TOTAL_CURRENT_SENT setglobal NETWORK_USAGE_DAY_PREVIOUS_RECIEVED = $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED setglobal NETWORK_USAGE_DAY_OF_MONTH = $dayofmonth } # - Work out todays usage setglobal NETWORK_USAGE_DAY_CURRENT_SENT = $shExpr(' $NETWORK_USAGE_TOTAL_CURRENT_SENT - $NETWORK_USAGE_DAY_PREVIOUS_SENT ') setglobal NETWORK_USAGE_DAY_CURRENT_RECIEVED = $shExpr(' $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED - $NETWORK_USAGE_DAY_PREVIOUS_RECIEVED ') } } #Memory setglobal MEMORY_TOTAL = '0' setglobal MEMORY_FREE = '0' setglobal MEMORY_USED = '0' setglobal MEMORY_CACHED = '0' setglobal MEMORY_PERCENT = '0' setglobal MEMORY_SWAPTOTAL = '0' setglobal MEMORY_SWAPUSED = '0' setglobal MEMORY_SWAPFREE = '0' setglobal MEMORY_SWAPERCENT = '0' proc Obtain_MEMORY{ #Write to temp setglobal FP_TEMP = '"/tmp/.mem'" free -m > $FP_TEMP #RAM MB setglobal MEMORY_TOTAL = $[cat $FP_TEMP | grep -m1 'Mem: ' | awk '{print $2}] #Grab values and seperate cache from "used and free" results. setglobal MEMORY_CACHED = $[cat $FP_TEMP | grep -m1 'Mem: ' | awk '{print $7}] setglobal MEMORY_USED = $shExpr(' $(cat $FP_TEMP | grep -m1 'Mem: ' | awk '{print $3}') - $MEMORY_CACHED ') setglobal MEMORY_FREE = $shExpr(' $(cat $FP_TEMP | grep -m1 'Mem: ' | awk '{print $4}') + $MEMORY_CACHED ') setglobal MEMORY_PERCENT = $[echo | awk "{print $MEMORY_USED / $MEMORY_TOTAL * 100}] #convert to interger and graph it Percent_To_Graph $MEMORY_PERCENT setglobal MEMORY_PERCENT = $C_PERCENT_GRAPH #SWAP MB setglobal MEMORY_SWAPTOTAL = $[cat $FP_TEMP | grep -m1 'Swap: ' | awk '{print $2}] # - Swap available and active if sh-expr ' $MEMORY_SWAPTOTAL > 0 ' { setglobal MEMORY_SWAPUSED = $[cat $FP_TEMP | grep -m1 'Swap: ' | awk '{print $3}] setglobal MEMORY_SWAPFREE = $[cat $FP_TEMP | grep -m1 'Swap: ' | awk '{print $4}] setglobal MEMORY_SWAPERCENT = $[ echo | awk "{print $MEMORY_SWAPUSED / $MEMORY_SWAPTOTAL * 100}] #convert to interger and graph it Percent_To_Graph $MEMORY_SWAPERCENT setglobal MEMORY_SWAPERCENT = $C_PERCENT_GRAPH } else { setglobal MEMORY_SWAPERCENT = '" Disabled'" } } #PI-HOLE STATS! setglobal PIHOLE_QUERY_COUNT = '0' setglobal PIHOLE_TOTAL_ADS = '0' setglobal PIHOLE_PERCENT_ADS = '0' setglobal PIHOLE_TOTAL_DOMAINS = '0' setglobal PIHOLE_LAST_DOMAIN_BLOCKED = '0' proc Obtain_PIHOLE{ local pihole_log_file="/var/log/pihole.log" #Lets pull the total number of blocked domains only once during 1st run, its quite cpu intensive. if sh-expr ' $PIHOLE_TOTAL_DOMAINS == 0 ' { if test -f /etc/pihole/gravity.list { setglobal PIHOLE_TOTAL_DOMAINS = $[wc -l /etc/pihole/gravity.list | awk '{print $1}] } else { setglobal PIHOLE_TOTAL_DOMAINS = '"Not Installed'" } } local today=$[date +'%b %e] setglobal PIHOLE_QUERY_COUNT = $[cat $pihole_log_file | grep $today | awk '/query/ {print $7}' | wc -l] #Prevent / 0 on percentage if sh-expr ' $PIHOLE_QUERY_COUNT <= 0 ' { setglobal PIHOLE_QUERY_COUNT = '1' } setglobal PIHOLE_TOTAL_ADS = $[cat $pihole_log_file | grep $today | awk '/\/etc\/pihole\/gravity.list/ {print $7}' | wc -l] setglobal PIHOLE_PERCENT_ADS = $[echo | awk "{print $PIHOLE_TOTAL_ADS / $PIHOLE_QUERY_COUNT * 100}] #convert to interger and graph it Percent_To_Graph $PIHOLE_PERCENT_ADS setglobal PIHOLE_PERCENT_ADS = $C_PERCENT_GRAPH #Get last blocked domain if sh-expr ' $PIHOLE_TOTAL_ADS == 0 ' { setglobal PIHOLE_LAST_DOMAIN_BLOCKED = '"None'" } else { setglobal PIHOLE_LAST_DOMAIN_BLOCKED = $[tac /var/log/pihole.log | grep -m1 'gravity.list' | awk '{print $6}' | cut -c 1-24] } } #///////////////////////////////////////////////////////////////////////////////////// # Scene Settings #///////////////////////////////////////////////////////////////////////////////////// setglobal RUN_INTRO = '0' if sh-expr ' $INPUT == 1 ' { setglobal RUN_INTRO = '1' } #SCENE INDEXS setglobal SCENE_CURRENT = '2' setglobal MAX_SCENES = '9' #Refresh rate (every X seconds) setglobal REFRESH_RATE = '5' #0='f | 1='c setglobal TEMPERATURE_OUTPUT_TYPE = '1' #0=bit (Mbit) | 1=byte (MB) setglobal NETWORK_USAGE_CURRENT_OUTPUT_TYPE = '0' #Enabled Scenes setglobal aEnabledScenes = ''() for ((i=0; i<$MAX_SCENES; i++)) do aEnabledScenes[$i]=1 done #///////////////////////////////////////////////////////////////////////////////////// # Scene Print / Update #///////////////////////////////////////////////////////////////////////////////////// proc Run_Intro{ #'--------------------------' clear local aAnimation=( ' ' 'i - c' 'P i - c l' 't P i - c l o' 'e t P i- c l o u' 'i e t Pi- c l o u d s' 'D i etPi- c l o u d s h' ' D ietPi-c l o u d s h e' ' DietPi-cl o u d s h e ' ' DietPi-clou d s h e l ' ' DietPi-clouds h e l l ' ' DietPi-cloudshe l l ' ' DietPi-cloudshell ' ) local aBar=( ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ) for ((i=0; i<${#aAnimation[@]}; i++)) do clear echo -e "$C_RESET" echo -e "" echo -e "" echo -e "" echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}${aAnimation[$i]}" echo -e "$C_RESET v$DIETPI_CLOUDSHELL_VERSION" echo -e "" echo -e " Loading..." echo -e "$C_RESET${aCOLOUR[$USER_COLOUR_INDEX]}$C_REVERSE${aBar[$i]}" sleep 0.2 done #delete[] array unset aAnimation unset aBar sleep 0.1 } #Top banner setglobal BANNER_PRINT = '0' setglobal BANNER_MODE = '0' proc Update_Banner{ #Banner Modes if sh-expr ' $BANNER_MODE == 0 ' { setglobal BANNER_PRINT = ""DietPi - Cloudshell v$DIETPI_CLOUDSHELL_VERSION"" } elif sh-expr ' $BANNER_MODE == 1 ' { Obtain_DATE_TIME setglobal BANNER_PRINT = $DATE_TIME } elif sh-expr ' $BANNER_MODE == 2 ' { Obtain_UPTIME setglobal BANNER_PRINT = $UPTIME } #Set next index sh-expr 'BANNER_MODE++' #Cap if sh-expr ' $BANNER_MODE >= 3 ' { setglobal BANNER_MODE = '0' } } #CPU proc Update_Scene_0{ #Update data Obtain_CPU #Clear screen clear #Banner echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE CPU Usage: " echo -e "$C_RESET$CPU_USAGE" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE CPU Stats: " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Temp $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $C_CPUTEMP$CPU_TEMP" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Processes $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $CPU_TOTALPROCESSES" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Governor $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $CPU_GOV" #XU3/4 unique octo quad sets if sh-expr ' $G_HW_MODEL == 11 ' { echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Freq 0-3 $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $CPU_FREQ_1 mhz" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Freq 4-7 $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $CPU_FREQ_2 mhz" #Generic CPU hardware } else { echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Freq $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $CPU_FREQ_1 mhz" } } #$1 $2 = Storage index's to update and display (must be a range of 1 , eg: 0-1 1-2 3-4) proc Update_Scene_1{ local index_1=$1 local index_2=$2 #Update data Obtain_STORAGE $index_1 $index_2 #Clear screen clear #Banner echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE $(STORAGE_NAME[$index_1])" echo -e "$C_RESET$(STORAGE_PERCENT[$index_1])" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Used: $C_RESET$(STORAGE_USED[$index_1]) / $(STORAGE_TOTAL[$index_1])" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Free: $C_RESET$(STORAGE_FREE[$index_1])" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE $(STORAGE_NAME[$index_2])" echo -e "$C_RESET$(STORAGE_PERCENT[$index_2])" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Used: $C_RESET$(STORAGE_USED[$index_2]) / $(STORAGE_TOTAL[$index_2])" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Free: $C_RESET$(STORAGE_FREE[$index_2])" } #DietPi proc Update_Scene_4{ #Update data Obtain_DIETPIINFO #Clear screen clear #Banner echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE DietPi: " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Version $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $DIETPI_VERSION_CURRENT" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Updates $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $DIETPI_UPDATE_AVAILABLE" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Web $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $DIETPI_WEBSITE" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Twitter $(aCOLOUR[$USER_COLOUR_INDEX]):$C_RESET $DIETPI_TWITTER" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Device: " echo -e "$C_RESET $DIETPI_HW_DESCRIPTION" } #NETWORK DETAILS proc Update_Scene_5{ #Update data Obtain_NETWORK_DETAILS #Clear screen clear #Banner echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Network Details: " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) IP : $C_RESET$NETWORK_DETAILS_IP_INT" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Mode : $C_RESET$NETWORK_DETAILS_MODE" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Adapter : $C_RESET$NETWORK_DETAILS_ADAPTER" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Duplex : $C_RESET$NETWORK_DETAILS_DUPLEXSPEED" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Signal : $C_RESET$NETWORK_DETAILS_SIGNAL_STRENGTH" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Hostname: $C_RESET$NETWORK_DETAILS_HOSTNAME" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) MAC: $C_RESET$NETWORK_DETAILS_MAC_ADDRESS" } #NETWORK USAGE proc Update_Scene_6{ #Update data Obtain_NETWORK_USAGE # - Convert usage values into human readable format. Run before clearing screen due to additional processing (delay) local total_sent_output=$[ BYTE_PRINT_CONVERSION $NETWORK_USAGE_TOTAL_CURRENT_SENT] local total_recieved_output=$[ BYTE_PRINT_CONVERSION $NETWORK_USAGE_TOTAL_CURRENT_RECIEVED] local today_sent_output=$[ BYTE_PRINT_CONVERSION $NETWORK_USAGE_DAY_CURRENT_SENT] local today_recieved_output=$[ BYTE_PRINT_CONVERSION $NETWORK_USAGE_DAY_CURRENT_RECIEVED] local now_sent_output=0 local now_recieved_output0 if sh-expr ' $NETWORK_USAGE_CURRENT_OUTPUT_TYPE == 0 ' { setglobal now_sent_output = $[ BIT_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_SENT] setglobal now_recieved_output = $[ BIT_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_RECIEVED] } else { setglobal now_sent_output = $[ BYTE_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_SENT] setglobal now_recieved_output = $[ BYTE_PRINT_CONVERSION $NETWORK_USAGE_NOW_CURRENT_RECIEVED] } #Clear screen clear #Banner # - Banner does not fit this scene (>= 9 lines) #echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Network Usage (TOTAL): " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Sent : $C_RESET$total_sent_output" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Recieved : $C_RESET$total_recieved_output" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Network Usage (TODAY): " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Sent : $C_RESET$today_sent_output" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Recieved : $C_RESET$today_recieved_output" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Network Usage (CURRENT): " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Sent : $C_RESET$now_sent_output/s" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Recieved : $C_RESET$now_recieved_output/s" } #Memory proc Update_Scene_7{ #Update data Obtain_MEMORY #Clear screen clear #Banner echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Memory Usage (RAM): " echo -e "$C_RESET$MEMORY_PERCENT" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Used: $C_RESET$MEMORY_USED MB / $MEMORY_TOTAL MB" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Free: $C_RESET$MEMORY_FREE MB" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Memory Usage (SWAP): " echo -e "$C_RESET$MEMORY_SWAPERCENT" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Used: $C_RESET$MEMORY_SWAPUSED MB / $MEMORY_SWAPTOTAL MB" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Free: $C_RESET$MEMORY_SWAPFREE MB" } #Pi-hole proc Update_Scene_8{ #Update data Obtain_PIHOLE #Clear screen clear #Banner echo -e "$C_RESET $BANNER_PRINT" # echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Pi-hole stats (TODAY): " echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Ads Blocked: $C_RESET$PIHOLE_TOTAL_ADS" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) DNS Queries: $C_RESET$PIHOLE_QUERY_COUNT" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX]) Blocked Domains: $C_RESET$PIHOLE_TOTAL_DOMAINS" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE % of traffic = Ads: " echo -e "$C_RESET$PIHOLE_PERCENT_ADS" echo -e "$C_RESET$(aCOLOUR[$USER_COLOUR_INDEX])$C_REVERSE Last domain blocked: " echo -e "$C_RESET $PIHOLE_LAST_DOMAIN_BLOCKED" } #///////////////////////////////////////////////////////////////////////////////////// # Settings File #///////////////////////////////////////////////////////////////////////////////////// #Define Location setglobal FILEPATH_SETTINGS = '"/DietPi/dietpi/.dietpi-cloudshell'" proc Read_Settings_File{ if test -f $FILEPATH_SETTINGS { source "$FILEPATH_SETTINGS" } } proc Write_Settings_File{ cat << """ > "$FILEPATH_SETTINGS" REFRESH_RATE=$REFRESH_RATE USER_COLOUR_INDEX=$USER_COLOUR_INDEX TEMPERATURE_OUTPUT_TYPE=$TEMPERATURE_OUTPUT_TYPE OUTPUT_DISPLAY_INDEX=$OUTPUT_DISPLAY_INDEX NETWORK_USAGE_CURRENT_OUTPUT_TYPE=$NETWORK_USAGE_CURRENT_OUTPUT_TYPE BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED=$BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED BLANK_SCREEN_TIME_HOUR_START=$BLANK_SCREEN_TIME_HOUR_START BLANK_SCREEN_TIME_HOUR_END=$BLANK_SCREEN_TIME_HOUR_END """ > $FILEPATH_SETTINGS REFRESH_RATE=$REFRESH_RATE USER_COLOUR_INDEX=$USER_COLOUR_INDEX TEMPERATURE_OUTPUT_TYPE=$TEMPERATURE_OUTPUT_TYPE OUTPUT_DISPLAY_INDEX=$OUTPUT_DISPLAY_INDEX NETWORK_USAGE_CURRENT_OUTPUT_TYPE=$NETWORK_USAGE_CURRENT_OUTPUT_TYPE BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED=$BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED BLANK_SCREEN_TIME_HOUR_START=$BLANK_SCREEN_TIME_HOUR_START BLANK_SCREEN_TIME_HOUR_END=$BLANK_SCREEN_TIME_HOUR_END _EOF_ #Add enabled scenes for ((i=0; i<$MAX_SCENES; i++)) do echo -e "aEnabledScenes[$i]=${aEnabledScenes[$i]}" >> $FILEPATH_SETTINGS done #Add Drive Paths and Names for ((i=0; i<$MAX_STORAGE; i++)) do echo -e "STORAGE_PATH[$i]='${STORAGE_PATH[$i]}'" >> $FILEPATH_SETTINGS echo -e "STORAGE_NAME[$i]='${STORAGE_NAME[$i]}'" >> $FILEPATH_SETTINGS done } #///////////////////////////////////////////////////////////////////////////////////// # Init #///////////////////////////////////////////////////////////////////////////////////// proc Init{ #-------------------------------------------------------------------------------- #Storage array Init_STORAGE #-------------------------------------------------------------------------------- #Load Settings file. Read_Settings_File #-------------------------------------------------------------------------------- #VM disable CPU scene if sh-expr ' $G_HW_MODEL == 20 ' { compat array-assign aEnabledScenes '0' '0' } #-------------------------------------------------------------------------------- #Check and disable scenes if software is not installed: # 6 Pi-hole if test ! -f /etc/pihole/gravity.list { compat array-assign aEnabledScenes '8' '0' } #-------------------------------------------------------------------------------- #Ensure we have at least 1 Scene enabled in the settings file. local enabled_scene=0 for ((i=0; i<$MAX_SCENES; i++)) do if (( ${aEnabledScenes[$i]} )); then enabled_scene=1 break fi done #No Scenes selected! Override user setting and enable at least 1 scene (dietpi) if sh-expr ' $enabled_scene == 0 ' { compat array-assign aEnabledScenes '4' '1' setglobal SCENE_CURRENT = '4' } #-------------------------------------------------------------------------------- #Update DietPi network shared data: https://github.com/Fourdee/DietPi/issues/359 /DietPi/dietpi/func/obtain_network_details } #///////////////////////////////////////////////////////////////////////////////////// # Start/Stop Control for Menu #///////////////////////////////////////////////////////////////////////////////////// #0=tty1 1=current setglobal OUTPUT_DISPLAY_INDEX = '0' proc Stop{ #Service if started. systemctl stop dietpi-cloudshell #Kill all , excluding Menu. ps ax | grep '[d]ietpi-cloudshell [1-9]' | awk '{print $1}' > $FP_TEMP while read -r line { kill $line &> /dev/null } < $FP_TEMP } proc Start{ #Are we starting on the current screen? (eg: from tty1) local output_current_screen=0 if test $[tty] = "/dev/tty1" { setglobal output_current_screen = '1' } elif sh-expr ' $OUTPUT_DISPLAY_INDEX == 1 ' { setglobal output_current_screen = '1' } #Inform user to press CTRL+C to exit if sh-expr ' $output_current_screen == 1 ' { clear echo -e $C_RESET read -p "Use CTRL+C to exit. Press any key to launch $PROGRAM_NAME..." } #Launch in blocking mode if sh-expr ' $output_current_screen == 1 ' { /DietPi/dietpi/dietpi-cloudshell 1 #Launch as service on main screen } else { systemctl start dietpi-cloudshell } sleep 0.1 } #///////////////////////////////////////////////////////////////////////////////////// # Menu System #///////////////////////////////////////////////////////////////////////////////////// setglobal WHIP_BACKTITLE = '0' setglobal WHIP_TITLE = '0' setglobal WHIP_QUESTION = '0' setglobal CHOICE = '0' setglobal TARGETMENUID = '0' setglobal LASTSELECTED_ITEM = ''"" proc Menu_Exit{ setglobal WHIP_TITLE = ""Exit $PROGRAM_NAME"" setglobal WHIP_QUESTION = ""Exit $PROGRAM_NAME configuration tool?"" whiptail --title $WHIP_TITLE --yesno $WHIP_QUESTION --backtitle $WHIP_TITLE --yes-button "Ok" --no-button "Back" --defaultno 9 55 setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { #Save changes Write_Settings_File #exit setglobal TARGETMENUID = '-1' } else { #Return to Main Menu setglobal TARGETMENUID = '0' } } #TARGETMENUID=0 proc Menu_Main{ setglobal TARGETMENUID = '0' setglobal WHIP_BACKTITLE = ""- $PROGRAM_NAME v$DIETPI_CLOUDSHELL_VERSION -"" setglobal WHIP_TITLE = ""- $PROGRAM_NAME -"" local temp_output_text="Fahrenheit" if sh-expr ' $TEMPERATURE_OUTPUT_TYPE == 1 ' { setglobal temp_output_text = '"Celsius'" } local target_output_text="Main Screen (tty1)" if sh-expr ' $OUTPUT_DISPLAY_INDEX == 1 ' { setglobal target_output_text = '"Current screen or terminal'" } local bitbyte_output_text="Bit (Kbit, Mbit, Gbit)" if sh-expr ' $NETWORK_USAGE_CURRENT_OUTPUT_TYPE == 1 ' { setglobal bitbyte_output_text = '"Byte (KB, MB, GB)'" } local autoscreenoff="Disabled" if sh-expr ' $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED ' { setglobal autoscreenoff = '"Enabled'" } setglobal OPTION = $[whiptail --title $WHIP_TITLE --backtitle $WHIP_BACKTITLE --menu "" --cancel-button "Exit" --default-item $LASTSELECTED_ITEM 17 75 10 \ "Colour" "Setting: Change the colour scheme." \ "Update Rate" "Setting: Control the time between screen updates." \ "Scenes" "Setting: Toggle which scenes are shown." \ "Storage" "Setting: Set mount locations used for storage stats" \ "Temperature" "Setting: Output = $temp_output_text" \ "Net Usage Current" "Setting: Output = $bitbyte_output_text" \ "Output Display" "Setting: $target_output_text." \ "Auto screen off" "Setting: $autoscreenoff | Start $BLANK_SCREEN_TIME_HOUR_START h | End $BLANK_SCREEN_TIME_HOUR_END h" \ "Start / Restart" "Apply settings. Launch on $target_output_text." \ "Stop" "Stops $PROGRAM_NAME." !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { setglobal LASTSELECTED_ITEM = $OPTION match $OPTION { with "Storage" setglobal TARGETMENUID = '5' with "Auto screen off" setglobal TARGETMENUID = '4' with "Net Usage Current" sh-expr 'NETWORK_USAGE_CURRENT_OUTPUT_TYPE++' if sh-expr ' $NETWORK_USAGE_CURRENT_OUTPUT_TYPE > 1 ' { setglobal NETWORK_USAGE_CURRENT_OUTPUT_TYPE = '0' } with Temperature sh-expr 'TEMPERATURE_OUTPUT_TYPE++' if sh-expr ' $TEMPERATURE_OUTPUT_TYPE > 1 ' { setglobal TEMPERATURE_OUTPUT_TYPE = '0' } with "Output Display" sh-expr 'OUTPUT_DISPLAY_INDEX++' if sh-expr ' $OUTPUT_DISPLAY_INDEX > 1 ' { setglobal OUTPUT_DISPLAY_INDEX = '0' } with "Start / Restart" Write_Settings_File Stop Start with "Stop" Stop with Colour setglobal TARGETMENUID = '1' with "Update Rate" setglobal TARGETMENUID = '2' with Scenes setglobal TARGETMENUID = '3' } } else { Menu_Exit } } #TARGETMENUID=1 proc Menu_Colour{ #Return to main menu setglobal TARGETMENUID = '0' #Colour array #0 WHITE #1 RED #2 GREEN #3 YELLOW #4 BLUE #5 PURPLE #6 CYAN setglobal WHIP_TITLE = ''- Options : Colour -'' setglobal WHIP_QUESTION = ''Select your colour scheme.'' setglobal OPTION = $[whiptail --title $WHIP_TITLE --backtitle $WHIP_BACKTITLE --menu $WHIP_QUESTION --cancel-button "Back" --default-item $USER_COLOUR_INDEX 15 45 7 \ "0" "White" \ "1" "Red" \ "2" "Green" \ "3" "Yellow (Default)" \ "4" "Blue" \ "5" "Purple" \ "6" "Cyan" !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { setglobal USER_COLOUR_INDEX = $OPTION } } #TARGETMENUID=2 proc Menu_UpdateRate{ #Return to main menu setglobal TARGETMENUID = '0' setglobal WHIP_TITLE = ''- Options : Update Rate -'' setglobal WHIP_QUESTION = ''Change the delay between scene changes and updates.'' setglobal OPTION = $[whiptail --title $WHIP_TITLE --backtitle $WHIP_BACKTITLE --menu $WHIP_QUESTION --cancel-button "Back" --default-item $REFRESH_RATE 15 55 7 \ "1" "Second" \ "3" "Seconds" \ "5" "Seconds (Default)" \ "10" "Seconds" \ "15" "Seconds" \ "20" "Seconds" \ "30" "Seconds" \ "45" "Seconds" \ "60" "Seconds" !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { setglobal REFRESH_RATE = $OPTION } } #TARGETMENUID=3 proc Menu_SceneSelection{ #Return to main menu setglobal TARGETMENUID = '0' setglobal FP_TEMP = '"/tmp/.dietpi-cloudshell_scenelist'" #Get on/off whilptail status local aWhiptailArray=() local aWhip_OnOff_Status=() for ((i=0; i<$MAX_SCENES; i++)) do #On/Off status aWhip_OnOff_Status[$i]='on' if (( ! ${aEnabledScenes[$i]} )); then aWhip_OnOff_Status[$i]='off' fi done #Define options local index=0 setglobal index = '0';setglobal aWhiptailArray = ''("$index" "CPU: Temperatures, Usage, frequency and more." "${aWhip_OnOff_Status[$index]}") setglobal index = '1';setglobal aWhiptailArray = ''("$index" "Storage: Usage information for Flash and USB drives" "${aWhip_OnOff_Status[$index]}") setglobal index = '2';setglobal aWhiptailArray = ''("$index" " - Additional Storage (USB_2/3)" "${aWhip_OnOff_Status[$index]}") setglobal index = '3';setglobal aWhiptailArray = ''("$index" " - Additional Storage (USB_4/5)" "${aWhip_OnOff_Status[$index]}") setglobal index = '4';setglobal aWhiptailArray = ''("$index" "DietPi: Information, stats and updates for DietPi." "${aWhip_OnOff_Status[$index]}") setglobal index = '5';setglobal aWhiptailArray = ''("$index" "Network Details: Ip address, Speeds, Signal and more." "${aWhip_OnOff_Status[$index]}") setglobal index = '6';setglobal aWhiptailArray = ''("$index" "Network Usage: Bandwidth usage (sent / recieved)." "${aWhip_OnOff_Status[$index]}") setglobal index = '7';setglobal aWhiptailArray = ''("$index" "Memory: Stats for RAM and Swapfile usage." "${aWhip_OnOff_Status[$index]}") setglobal index = '8';setglobal aWhiptailArray = ''("$index" "Pi-hole: Stats for Pi-hole. Total Ads blocked etc." "${aWhip_OnOff_Status[$index]}") setglobal WHIP_TITLE = ''- Options : Scene Selection -'' setglobal WHIP_QUESTION = ''Please use the spacebar to toggle which scenes are active.'' whiptail --title $WHIP_TITLE --checklist $WHIP_QUESTION --backtitle $WHIP_TITLE --separate-output 16 75 9 $(aWhiptailArray[@]) !2 > $FP_TEMP setglobal CHOICE = $Status #Delete[] array unset aWhiptailArray unset aWhip_OnOff_Status # - Reset all scenes to 0 if sh-expr ' $CHOICE == 0 ' { for ((i=0; i<$MAX_SCENES; i++)) do aEnabledScenes[$i]=0 done } # - Enable required scenes while read -r line { compat array-assign aEnabledScenes '$line' '1' } < "$FP_TEMP" } #TARGETMENUID=4 proc Menu_BlankScreenAtTime{ #Return to main menu setglobal TARGETMENUID = '0' #generate 24 hour array local aWhipHour=() for ((i=0; i<24; i++)) do aWhipHour+=("$i" "Hour") done local blank_screen_at_specific_time_enabled_text='Disabled' if sh-expr ' $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED ' { setglobal blank_screen_at_specific_time_enabled_text = ''Enabled'' } setglobal WHIP_TITLE = ''- Options : Auto screen off -'' setglobal WHIP_QUESTION = ''Automatically power down the screen and disable DietPi-Cloudshell processing during a specific time.\n\nNB: This feature will only work if DietPi-Cloudshell was launched with the DietPi-Autostart option, or, launched from the main screen (tty1).'' setglobal OPTION = $[whiptail --title $WHIP_TITLE --backtitle $WHIP_BACKTITLE --menu $WHIP_QUESTION --cancel-button "Back" --default-item $REFRESH_RATE 16 60 3 \ "Toggle" $blank_screen_at_specific_time_enabled_text \ "Start time" "Set which hour to power off screen ($BLANK_SCREEN_TIME_HOUR_START)." \ "End time" "Set which hour to power on screen ($BLANK_SCREEN_TIME_HOUR_END)." !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { if test $OPTION = "Toggle"{ sh-expr 'BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED++' if sh-expr ' $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED > 1 ' { setglobal BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED = '0' } } elif test $OPTION = "Start time"{ setglobal WHIP_QUESTION = ''Please select which hour (24h) you would like the screen to power off.'' setglobal OPTION = $[whiptail --title $WHIP_TITLE --menu $WHIP_QUESTION --default-item $BLANK_SCREEN_TIME_HOUR_START --backtitle $WHIP_BACKTITLE 16 55 7 $(aWhipHour[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { setglobal BLANK_SCREEN_TIME_HOUR_START = $OPTION } } elif test $OPTION = "End time"{ setglobal WHIP_QUESTION = ''Please select which hour (24h) you would like the screen to power on.'' setglobal OPTION = $[whiptail --title $WHIP_TITLE --menu $WHIP_QUESTION --default-item $BLANK_SCREEN_TIME_HOUR_END --backtitle $WHIP_BACKTITLE 16 55 7 $(aWhipHour[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { setglobal BLANK_SCREEN_TIME_HOUR_END = $OPTION } } setglobal TARGETMENUID = '4' } unset aWhipHour } #TARGETMENUID=5 proc Menu_Storage{ #Return to main menu setglobal TARGETMENUID = '0' local aWhiptailArray=() for ((i=1; i<$MAX_STORAGE; i++)) do #aWhiptailArray+=("Name $i" "${STORAGE_NAME[$i]}.") aWhiptailArray+=("$i" ": Drive $i | ${STORAGE_PATH[$i]}") done setglobal WHIP_TITLE = ''- Options : Storage Device Mount Location -'' setglobal WHIP_QUESTION = ''DietPi-Cloudshell pulls the storage stats from the drive mount location. If you have custom drives/mounts, please set them here to be displayed during storage scene updates.\n\n - Drive 1 = Displayed during main storage scene\n - Drive 2/3 = Displayed during additional storage scene\n - Drive 4/5 = Displayed during additional storage scene'' setglobal OPTION = $[whiptail --title $WHIP_TITLE --backtitle $PROGRAM_NAME --menu $WHIP_QUESTION --cancel-button "Back" 19 75 5 $(aWhiptailArray[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status unset aWhiptailArray if sh-expr ' $CHOICE == 0 ' { local index=$OPTION /DietPi/dietpi/dietpi-drive_manager 1 local return_string="$[cat /tmp/dietpi-drive_manager_selmnt]" if test -n $return_string { compat array-assign STORAGE_PATH '$index' $return_string } setglobal TARGETMENUID = '5' } } #///////////////////////////////////////////////////////////////////////////////////// # MAIN #///////////////////////////////////////////////////////////////////////////////////// #----------------------------------------------------------------------------------- #Init Init #----------------------------------------------------------------------------------- #Run menu if sh-expr ' $INPUT == 0 ' { #Start Menu while sh-expr ' $TARGETMENUID >= 0 ' { clear if sh-expr ' $TARGETMENUID == 0 ' { Menu_Main } elif sh-expr ' $TARGETMENUID == 1 ' { Menu_Colour } elif sh-expr ' $TARGETMENUID == 2 ' { Menu_UpdateRate } elif sh-expr ' $TARGETMENUID == 3 ' { Menu_SceneSelection } elif sh-expr ' $TARGETMENUID == 4 ' { Menu_BlankScreenAtTime } elif sh-expr ' $TARGETMENUID == 5 ' { Menu_Storage } } #----------------------------------------------------------------------------------- #Run DietPi-Cloudshell } elif sh-expr ' $INPUT >= 1 ' { Enable_Term_Options #Start Intro if sh-expr ' $RUN_INTRO ' { Run_Intro } #Set Nice to +10 (not critical) renice -n 10 $Pid &> /dev/null #Start display updates while true { if sh-expr ' $BLANK_SCREEN_AT_SPECIFIC_TIME_ENABLED ' { RUN_BLANK_SCREEN_AT_SPECIFIC_TIME } #Disable updates when screen is blanked if sh-expr ' $BLANK_SCREEN_ACTIVE ' { sleep 60 #Update enabled scenes } else { if sh-expr ' ${aEnabledScenes[$SCENE_CURRENT]} ' { Update_Banner # - Input mode scene update (storage array) if sh-expr ' $SCENE_CURRENT == 1 ' { Update_Scene_1 0 1 # - Input mode scene update (storage array) } elif sh-expr ' $SCENE_CURRENT == 2 ' { Update_Scene_1 2 3 # - Input mode scene update (storage array) } elif sh-expr ' $SCENE_CURRENT == 3 ' { Update_Scene_1 4 5 # - Normal scene update } else { Update_Scene_$SCENE_CURRENT } #Apply refresh rate delay sleep $REFRESH_RATE } #Scene Switcher sh-expr 'SCENE_CURRENT++' #Cap if sh-expr ' $SCENE_CURRENT >= $MAX_SCENES ' { setglobal SCENE_CURRENT = '0' } } } } #----------------------------------------------------------------------------------- #Clean up temp files rm $FP_TEMP &> /dev/null #----------------------------------------------------------------------------------- #Delete[] Global arrays unset aCOLOUR unset aEnabledScenes Destroy_STORAGE #----------------------------------------------------------------------------------- exit #----------------------------------------------------------------------------------- }