From cf07fb0ad821e9eec583541fc452cc45c0fbba18 Mon Sep 17 00:00:00 2001 From: Thomas Kaiser Date: Fri, 4 Mar 2016 00:32:07 +0100 Subject: [PATCH] Added preliminary armbianmonitor code --- documentation/H3_mini_faq.md | 1 + scripts/armbianmonitor/armbianmonitor | 417 ++++++++++++++++ scripts/armbianmonitor/armbianmonitor-daemon | 475 +++++++++++++++++++ 3 files changed, 893 insertions(+) create mode 100644 scripts/armbianmonitor/armbianmonitor create mode 100644 scripts/armbianmonitor/armbianmonitor-daemon diff --git a/documentation/H3_mini_faq.md b/documentation/H3_mini_faq.md index 5294b77c66..bef9354f53 100644 --- a/documentation/H3_mini_faq.md +++ b/documentation/H3_mini_faq.md @@ -23,6 +23,7 @@ Armbian supports starting with release 5.04 all available H3 based Orange Pi boa - Auto detection for the Orange Pi 2 doesn't work properly. Please have a look [for a manual fix](http://forum.armbian.com/index.php/topic/617-wip-orange-pi-one-support-for-the-upcoming-orange-pi-one/?p=5718) or wait for 5.05 where this will be fixed - Mali acceleration currently only working for root user. Please apply [a fix](http://forum.armbian.com/index.php/topic/617-wip-orange-pi-one-support-for-the-upcoming-orange-pi-one/?p=5719) manually or wait for 5.05 to fix this +- Booting from NAND on OPi Plus currently not supported ***Important to know*** diff --git a/scripts/armbianmonitor/armbianmonitor b/scripts/armbianmonitor/armbianmonitor new file mode 100644 index 0000000000..7be0ff608b --- /dev/null +++ b/scripts/armbianmonitor/armbianmonitor @@ -0,0 +1,417 @@ +#!/bin/bash +# +# armbianmonitor +# +# This script serves different purposes based on how it is called: +# +# - toggle boot verbosity (works) +# - monitoring mode: continually print monitoring info (WiP) +# - uploading /var/log/armhwinfo.log to online pastebin service +# +# Without arguments called it should present a simple user +# interface that guides through: +# +# - installation of RPi-Monitor if not already installed by user +# - active basic or more verbose monitoring mode +# - provides monitoring parameters for connected disks +# +# The second part is WiP and all the user interaction part +# still completely missing. +# +# This script is used to configure armbianmonitor behaviour. +# It will ask the user whether to activate monitoring or not, +# whether to enable debug monitoring and also how to deal with +# connected disks. In fact it walks through the list of available +# disks, checks them, tries to patch hddtemp.db if necessary +# and provides a proposal for /etc/armbianmonitor/disks.conf +# when a new disk is found. +# +# In case monitoring should be activated the following file +# will be created: /etc/armbianmonitor/start-monitoring. If +# debug output has been chosen, then DEBUG will be written to +# the file. +# +# The script will install smartmontools/gdisk if not already +# installed and patches smartmontools' update-smart-drivedb +# script if necessary. For disks the 'device model' will be +# shown but internally we rely always on the GUID. This is the +# key for entry in /etc/armbianmonitor/disks.conf +# +# When the script exits and the user activated monitoring it +# recommends doing a restart since on the next reboot the +# setup-armbian-monitoring-environment script will configure +# monitoring sources and decides based on the existence and +# contents of /etc/armbianmonitor/start-monitoring whether +# rpimonitord should be started or not. +# +# The format of /etc/armbianmonitor/disks.conf is as follows: +# +# ${GUID}:${Name}:${smartctl prefix}:${temp call}:${CRC}:${LCC} +# +# Two examples: +# +# A57BF307-7D82-4783-BD1D-B346CA8C195B:WD Green::199:193 # WD HDD on SATA +# F8D372DC-63DB-494B-B802-87DC47FAD4E1:Samsung EVO:sat::199: # SSD in USB enclosure +# +# - GUID is the GUID as determined by gdisk +# - 'Name': The name as it will later be shown in RPi-Monitor, defaults to +# the 'device model' read out through smartctl but can be changed to +# be more significant (beware that this string must contain colons!) +# - "smartctl prefix" can be empty or should be the the necessary prefix for +# USB disks, eg. '-d sat' or '-d usbjmicron' and so on -- please have a +# look at https://www.smartmontools.org/wiki/Supported_USB-Devices +# - "temp call" when being omitted indicates that hddtemp should be used. +# Otherwise it should contain the complete command line ('DISK' will be +# dynamically replaced by the device node when the actual monitoring +# happens), for example: +# /sbin/hdparm -C DISK | egrep -q "standby|sleeping" || /usr/sbin/smartctl -d sat -a DISK | awk -F" " '/Temperature_Cel/ {printf $10}' +# - 'CRC attribute': The decimal value of the S.M.A.R.T. attribute that +# is used to store the count of checksum errors between disk and host +# controller (might be omitted if the drive doesn't support it) +# - 'LCC attribute': The decimal value of the S.M.A.R.T. attribute that +# should contain the load cycle counter value (might be omitted +# if the drive doesn't support it) +# +# TODO: +# +# - develop main functionality ;) asking the user regarding monitoring +# - deal with 'SMART overall-health self-assessment test result:' +# - write documentation +# +############################################################################ + +Main() { + export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + + ParseOptions "$@" + + PreRequisits + + # check whether user runs rpimonitord on his own or we activated it + if [ -f /etc/armbianmonitor/start-monitoring ]; then + # we should already provide monitoring, check whether DEBUG + # is also set + ArmbianMonitoring=TRUE + read DebugMode /boot/.force-verbose + echo -e "Verbose kernel messages have been enabled. Needs a reboot" + fi + exit 0 + ;; + m|M) + # monitoring mode + MonitorMode ${OPTARG} + exit 0 + ;; + u|U) + # Upload /var/log/armhwinfo.log to be of help in support forum. + # TODO: ping sprunge.us before to detect network/firewall problems + which curl >/dev/null 2>&1 || apt-get -f -qq -y install curl + echo -e "/var/log/armhwinfo.log has been uploaded to \c" + (cat /var/log/armhwinfo.log ; echo -e "\n### dmesg now:\n$(dmesg)") \ + | curl -F 'sprunge=<-' http://sprunge.us + echo -e "Please post the URL in the Armbian forum where you've been asked for" + exit 0 + ;; + esac + done +} # ParseOptions + +DisplayUsage() { + # check if stdout is a terminal... + if test -t 1; then + # see if it supports colors... + ncolors=$(tput colors) + if test -n "$ncolors" && test $ncolors -ge 8; then + BOLD="$(tput bold)" + NC='\033[0m' # No Color + LGREEN='\033[1;32m' + fi + fi + echo -e "Usage: ${BOLD}${0##*/} [-h/-H] [-b] [-m] [-u]${NC}\n" + echo -e "############################################################################" + if [ ${FullUsage} ]; then + echo -e "\nDetailed Description:" + grep "^#" "$0" | grep -v "^#\!/bin/bash" | sed 's/^#//' + fi + echo -e "\n This is WiP now\n" + echo -e "############################################################################\n" +} # DisplayUsage + +MonitorMode() { + # $1 is the time in seconds to pause between two prints, defaults to 5 seconds + # This functions prints out endlessly: + # - time/date + # - average 1m load + # - detailed CPU statistics + # - Soc temperature if available + # - PMIC temperature if available + # TODO: Format output nicely + Sensors="/etc/armbianmonitor/datasources/" + while true ; do + LoadAvg=$(cut -f1 /dev/null 2>&1 || exit 0 + + for i in /sys/block/sd* ; do + DeviceNode=/dev/${i##*/} + # get GUID/UUID for disk and check whether a partition table is existent. If + # not GUID will always be random + gdisk -l ${DeviceNode} >"${MyTempDir}/gdisk.txt" + GUID=$(awk -F" " '/^Disk identifier/ {print $4}' <"${MyTempDir}/gdisk.txt") + CountOfUnavailablePartitionTables=$(grep ': not present' "${MyTempDir}/gdisk.txt" | wc -l) + if [ ${CountOfUnavailablePartitionTables} -eq 4 ]; then + echo -e "\nSkipping ${DeviceNode} due to missing partition table. Use parted to create one." + break + else + echo -e "\nExamining ${DeviceNode} with GUID ${GUID}\c" + fi + + # get name hddtemp needs + HddtempName="$(hddtemp --debug ${DeviceNode} | awk -F": " '/^Model: / {print $2}' | \ + cut -c-40 | sed 's/^[ \t]*//;s/[ \t]*$//')" + # store smartctl output in temporary file + smartctl -q noserial -s on -a ${DeviceNode} >"${MyTempDir}/smartctl.txt" 2>&1 + DeviceModel="$(awk -F": " '/^Device Model/ {print $2}' <"${MyTempDir}/smartctl.txt" | \ + sed 's/^[ \t]*//;s/[ \t]*$//')" + if [ "X${DeviceModel}" = "X" ]; then + # Reading S.M.A.R.T. failed, we try autodetect mode iterating through all + # known smartctl modes (-d auto|sat|usbcypress|usbjmicron|usbprolific|usbsunplus) + SMARTPrefix="$(CheckSMARTModes ${DeviceNode} 2>/dev/null)" + if [ "X${SMARTPrefix}" = "X" ]; then + # we can't query the disk. Time to give up + echo -e ". Unable to query the disk through S.M.A.R.T.\nPlease investigate manually using smartctl\n" + break + fi + fi + + # user feedback + if [ "X${SMARTPrefix}" = "X" ]; then + echo -e " (accessible through S.M.A.R.T.)" + else + echo -e " (can be queried with \"-d ${SMARTPrefix}\" through S.M.A.R.T.)" + fi + + # check for CRC and LCC attributes + CRCAttribute=$(awk -F" " '/CRC_Error_Count/ {print $1}' <"${MyTempDir}/smartctl.txt") + LCCAttribute=$(grep -i "load.cycle" "${MyTempDir}/smartctl.txt" | awk -F" " '{print $1}') + + # check whether /etc/hddtemp.db should be patched + grep -q "${HddtempName}" /etc/hddtemp.db + if [ $? -ne 0 ]; then + # No entry into hddtemp database, we've a look whether there's a 'temperature' + # attribute available (we take the 1st we find) and if that's the case we use this + DiskTemp=$(awk -F" " '/Temperature/ {print $1}' <"${MyTempDir}/smartctl.txt" | head -n1) + if [[ ${DiskTemp} -gt 0 ]]; then + echo -e "\"${HddtempName}\" ${DiskTemp} C \"${DeviceModel}\"" >>/etc/hddtemp.db + echo -e "\nAdded disk \"${DeviceModel}\"/\"${HddtempName}\" to /etc/hddtemp.db using S.M.A.R.T. attribute ${DiskTemp}\nbased on the following available thermal values:" + grep "Temperature" "${MyTempDir}/smartctl.txt" + # check hddtemp result + HddtempResult=$(hddtemp -n ${DeviceNode} | awk -F" " '{print $1}') + if [ "X${HddtempResult}" = "X${DeviceNode}:" ]; then + # hddtemp isn't able to query the disk + HddtempStatus="does not work. Please check with smartctl and adjust config accordingly" + echo -e "\nhddtemp output: $(hddtemp ${DeviceNode})" + echo -e "\nIt seems we can not rely on hddtemp to query this disk. Please try smartctl instead\n" + else + HddtempStatus="will work" + echo -e "\nhddtemp output: ${HddtempResult})" + echo -e "\nIn case this seems not to be correct please adjust /etc/hddtemp.db manually\n" + fi + else + HddtempStatus="does not work. Please check with smartctl and adjust config accordingly" + fi + else + HddtempStatus="will work" + fi + + # check for firmware updates + FirmwareUpdate="$(grep "^http" "${MyTempDir}/smartctl.txt")" + + # Check whether the disk (based on GUID) is already configured in our config file + # /etc/armbianmonitor/disks.conf or not + + grep -q "^${GUID}:" /etc/armbianmonitor/disks.conf >/dev/null 2>/dev/null + case $? in + 0) + # already listed, we provide just infos: + echo -e "Disk is already configured by the following monitoring config:\n$(grep "^${GUID}:" /etc/armbianmonitor/disks.conf)\n" + ;; + *) + # new disk, we recommend an entry for /etc/armbianmonitor/disks.conf + echo -e "Disk not configured for monitoring. We were able to extract the following information:\nGUID: ${GUID}" + if [ "X${SMARTPrefix}" != "X" ]; then + echo -e "QueryMode: -d ${SMARTPrefix}" + fi + echo -e "hddtemp: ${HddtempStatus}\nCRC attribute: ${CRCAttribute}\nLCC Attribute: ${LCCAttribute}" + case ${HddtempStatus} in + "will work") + echo -e "If you want to monitor the disk please add to /etc/armbianmonitor/disks.conf:\n${GUID}:${DeviceModel}:${SMARTPrefix}::${CRCAttribute}:${LCCAttribute}" + ;; + *) + echo -e "Proposal for /etc/armbianmonitor/disks.conf:\n${GUID}:${DeviceModel}:${SMARTPrefix}:FIXME:${CRCAttribute}:${LCCAttribute}" + echo -e "You have to figure out how to query the disk for its thermal sensor." + echo -e "Please check the output of \"hddtemp --debug ${DeviceNode}\" and smartctl\n" + ;; + esac + ;; + esac + if [ "X${FirmwareUpdate}" != "X" ]; then + echo -e "\nWARNING: A firmware update seems to be available:\n${FirmwareUpdate}\n" + fi + done +} # CheckDisks + +CheckSMARTModes() { + # This function tries to access USB disks through S.M.A.R.T. and returns the necessary + # '-d' call as well as fills in ${MyTempDir}/smartctl.txt + + for i in auto sat usbcypress usbjmicron usbprolific usbsunplus ; do + # user feedback + echo -n "." >/dev/tty + # query disk using the specific protocol + echo -n "" >"${MyTempDir}/smartctl.txt" + smartctl -q noserial -s on -d ${i} -a ${1} >"${MyTempDir}/smartctl.txt" 2>/dev/null + DeviceModel="$(awk -F": " '/^Device Model/ {print $2}' <"${MyTempDir}/smartctl.txt" | \ + sed 's/^[ \t]*//;s/[ \t]*$//')" + if [ "X${DeviceModel}" != "X" ]; then + echo ${i} + break + fi + done +} # CheckSMARTModes + +PreRequisits() { + # Ensure that we're running as root since otherwise querying SATA/USB disks won't work + if [ "$(id -u)" != "0" ]; then + echo "This script must be run as root" >&2 + exit 1 + fi + + export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + unset LANG + DISTROCODE=$(lsb_release -s -c) + + # check whether gdisk/smartctl are available and up to date + echo -e "Check whether necessary software is available\c" + which gdisk >/dev/null 2>&1 || (echo -e " Installing gdisk\c" ; apt-get -f -qq -y install gdisk) + which smartctl >/dev/null 2>&1 || (echo -e " Installing smartmontools\c" ; apt-get -f -qq -y install smartmontools) + echo -e " [done]\nUpdating smartmontools' drivedb\c" + /usr/sbin/update-smart-drivedb >/dev/null 2>&1 + if [ $? -ne 0 -a "X${DISTROCODE}" = "Xwheezy" ]; then + sed -i "/^SRCEXPR/{s#=.*#='http://sourceforge.net/p/smartmontools/code/HEAD/tree/\$location/smartmontools/drivedb.h?format=raw'#}" /usr/sbin/update-smart-drivedb + /usr/sbin/update-smart-drivedb + fi + echo -e " [done]" + CreateTempDir +} # PreRequisits + +CreateTempDir() { + # create a safe temporary dir + MyTempDir=$(mktemp -d /tmp/${0##*/}.XXXXXX) + if [ ! -d "${MyTempDir}" ]; then + MyTempDir=/tmp/${0##*/}.$RANDOM.$RANDOM.$RANDOM.$$ + (umask 066 && mkdir ${MyTempDir}) || (echo "Failed to create temp dir. Aborting" >&2 ; exit 1) + fi + chmod 711 "${MyTempDir}" + trap "rm -rf \"${MyTempDir}\" ; exit 0" 0 1 2 3 15 + for file in smartctl.txt gdisk.txt ; do + touch "${MyTempDir}/${file}" + chmod 644 "${MyTempDir}/${file}" + done +} #CreateTempFiles + +InstallRPiMonitor() { + # Installs rpimonitord based on the official instructions from + # http://rpi-experiences.blogspot.fr/p/rpi-monitor-installation.html + apt-get -qq -y update + apt-get -f -qq -y install apt-transport-https ca-certificates + wget -q http://goo.gl/rsel0F -O /etc/apt/sources.list.d/rpimonitor.list + apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 2C0D3C0F + apt-get -qq -y update + apt-get -f -qq -y install rpimonitor + /usr/share/rpimonitor/scripts/updatePackagesStatus.pl & +} # InstallRPiMonitor + +Main "$@" diff --git a/scripts/armbianmonitor/armbianmonitor-daemon b/scripts/armbianmonitor/armbianmonitor-daemon new file mode 100644 index 0000000000..68e8f1a297 --- /dev/null +++ b/scripts/armbianmonitor/armbianmonitor-daemon @@ -0,0 +1,475 @@ +#!/bin/bash +# +# armbianmonitor-daemon +# +# This script relies on information gathered in armhwinfo. It +# calls armhwinfo in query mode and relies then on the exported +# variables: HARDWARE ARCH KERNELID MACHINE ID VERSION +# +# The purpose is to create an environment for rpimonitord so that +# relevant hardware informations can be monitored easily. This +# script starts uses configuration files in /etc/armbianmonitor/, +# collects data sources below /etc/armbianmonitor/datasources/ and +# adjusts templates for RPi-Monitor on the fly. Only if the file +# /etc/armbianmonitor/start-monitoring exists this script relinks +# /etc/rpimonitor/data.conf and starts rpimonitord if not already +# running. +# +# In case the script detects that not all necessary data sources +# are available through sysfs it will act as a daemon to collect +# data on its own and to write it to the approriate file. As an +# example the SoC's temperature: Running on an AXP209 based board +# the script will check /sys/class/thermal/thermal_zone0/temp and +# if existing link it to /etc/armbianmonitor/datasources/soctemp. +# In case it does not exist the script will create a normal file +# at this location and writes the thermal value to it using the +# sunxi_axp209_temp binary in an endless loop. +# +# At least the following files/symlinks will be provided below +# /etc/armbianmonitor/datasources/ depending on SoC/PMIC in question: +# +# soctemp (SoC's internal temp in degree Celsius * 1000) +# pmictemp (PMIC's internal temp in degree Celsius * 1000) +# ac_voltage (DC-IN voltage in V * 1000000) +# usb_voltage (USB OTG voltage in V * 1000000) +# battery_voltage (battery voltage in V * 1000000) +# ac_current (DC-IN current in A * 1000000) +# usb_current (USB OTG current in A * 1000000) +# battery_current (battery current in A * 1000000) +# +# When extended debugging has been chosen (using _armbian-monitoring_ +# this can be configured. Then /etc/armbianmonitor/start-monitoring +# contains DEBUG) this script will also provide a few more files: +# +# cpustat (cpu_stat,system_stat,user_stat,nice_stat,iowait_stat,irq_stat +# collected through /proc/cpustat in daemon mode) +# cpu_count (number of active CPU cores) +# vcorevoltage (Vcore in V * 1000 based on sysfs or script.bin/.dtb) +# +# Disk monitoring: For configured disks the following parameters can be +# monitored: temperature, S.M.A.R.T. health, load cycle count and CRC +# errors indicating connection/cable problems. The config file used is +# /etc/armbianmonitoring/disks.conf +# +# Filesystem monitoring: In /etc/armbianmonitoring/filesystems.conf +# mountpoints and trigger values can be defined that will be used to +# create the template stuff for these fs at startup of this script. +# +# The behaviour of this script can be configured through another tool +# called armbian-monitoring. The latter will also check for connected +# disks, get their name and GUID and let the user choose whether the +# disk should be monitored or not. The information has to be stored in +# /etc/armbianmonitor/disks.conf relying on the GUIDs of the disks. + + # define some variables: +CheckInterval=7.5 # time in seconds between two checks +DiskCheckInterval=60 # time in seconds between disk checks + +Main() { + PreRequisits + + case ${ID} in + Cubieboard|Cubietruck|Orange|"Lamobo R1"|"Lime 2"|Lime|Banana|Micro) + DealWithAXP209 + ;; + "Banana M2") + DealWithNewBoard + # DealWithAXP221 + ;; + "Cubietruck Plus"|"Banana Pi M3"|"pcDuino8 Uno") + DealWithNewBoard + # DealWithAXP818 + ;; + Guitar|"Roseapple Pi") + DealWithNewBoard + # DealWithS500 + ;; + "Odroid XU4"|"Odroid XU3") + DealWithNewBoard + # DealWithExynos4 + ;; + "Odroid C1") + DealWithNewBoard + # DealWithS805 + ;; + Clearfog|"Turris Omnia") + DealWithNewBoard + # DealWithArmada38x + ;; + "Cubox i4"|"HB i2eX"|"Cubox i2eX"|"HB i1"|"HB i2"|"Wandboard") + DealWithNewBoard + # DealWithiMX6 + ;; + "Orange Pi PC"|"Orange Pi Plus"|"Orange Pi 2"|"Orange Pi One"|"Orange Pi Lite") + DealWithNewBoard + # DealWithH3 + ;; + Geekbox) + DealWithNewBoard + # DealWithRK3368 + ;; + *) + # No templates exist now. Combine sane defaults with some guessing + DealWithNewBoard + ;; + esac + + # Create the Armbian templates + CreateTemplates + + exit 0 + + # Decide depending on existence of /etc/armbianmonitor/start-monitoring + ShouldMonitoringBeStarted + + # Provide missing data in daemon mode + LoopEndlessly +} # Main + +LoopEndlessly() { + while true ; do + # get VCore + read CPUFreq /tmp/VCore + + # check disk temperature(s). We execute this only every ${DiskCheckInterval} since + # it's a bit costly (S.M.A.R.T. queries). + TimeNow=$(( $(date "+%s") / ${DiskCheckInterval} )) + if [[ ${TimeNow} -gt ${LastDiskCheck} ]]; then + # time for a disk check. If ${CheckAllDisks} is FALSE and /dev/sda exists we + # only query this device otherwise all available (might be none) + CheckDisks + # update check timestamp + LastDiskCheck=${TimeNow} + fi + + # External temperature from weather stations + # TimeNow=$(( $(date "+%s") / ${TempCheckInterval} )) + # if [[ ${TimeNow} -gt ${LastTempCheck} ]]; then + # read in external temp values from 2 different web sources + # ExternalTemp=$(GetExternalTemp) + # LastExternalTemp=$(SanitizeValue ${ExternalTemp} ${LastExternalTemp} | tee /tmp/externaltemp) + # LastTempCheck=${TimeNow} + # fi + + # cpustat + TimeNow=$(( $(date "+%s") / ${CpuStatCheckInterval} )) + if [[ ${TimeNow} -gt ${LastCpuStatCheck} ]]; then + ProcessStats + LastCpuStatCheck=${TimeNow} + fi + sleep ${CheckInterval} + done +} # LoopEndlessly + +CheckDisks() { + # To be done based on new /etc/armbianmonitoring/disks.conf config file + : +} # CheckDisks + +DealWithAXP209() { + # check existence of sysfs nodes + if [ -f /sys/devices/virtual/thermal/thermal_zone0/temp ]; then + ln -fs /sys/devices/virtual/thermal/thermal_zone0/temp /etc/armbianmonitor/datasources/soctemp + else + if [ -L /etc/armbianmonitor/datasources/soctemp ]; then + rm -f /etc/armbianmonitor/datasources/soctemp + fi + echo -n 25000 >/etc/armbianmonitor/datasources/soctemp + export GetSoCTemp="${ARCH}-${ID}" + fi + if [ -d /sys/devices/platform/soc@01c00000/1c2ac00.i2c/i2c-0/0-0034 ]; then + # mainline kernel and 'axp209 mainline sysfs interface' patch applied + ln -fs /sys/power/axp_pmu/ac/voltage /etc/armbianmonitor/datasources/ac_voltage + ln -fs /sys/power/axp_pmu/ac/amperage /etc/armbianmonitor/datasources/ac_current + ln -fs /sys/power/axp_pmu/vbus/voltage /etc/armbianmonitor/datasources/usb_voltage + ln -fs /sys/power/axp_pmu/vbus/amperage /etc/armbianmonitor/datasources/usb_current + ln -fs /sys/power/axp_pmu/battery/voltage /etc/armbianmonitor/datasources/battery_voltage + ln -fs /sys/power/axp_pmu/battery/amperage /etc/armbianmonitor/datasources/battery_current + ln -fs /sys/power/axp_pmu/pmu/temp /etc/armbianmonitor/datasources/pmictemp + ln -fs /sys/power/axp_pmu/battery/capacity /etc/armbianmonitor/datasources/battery_percent + ln -fs /sys/power/axp_pmu/battery/charging /etc/armbianmonitor/datasources/battery_charging + ln -fs /sys/power/axp_pmu/charger/amperage /etc/armbianmonitor/datasources/charger_current + ln -fs /sys/power/axp_pmu/battery/connected /etc/armbianmonitor/datasources/battery_connected + ln -fs /sys/power/axp_pmu/battery/charge /etc/armbianmonitor/datasources/battery_charge + fi + if [ -d /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/axp20-supplyer.28/power_supply ]; then + # sunxi 3.4 kernel + SysFSPrefix=/sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/axp20-supplyer.28/power_supply + ln -fs "${SysFSPrefix}"/ac/voltage_now /etc/armbianmonitor/datasources/ac_voltage + ln -fs "${SysFSPrefix}"/ac/current_now /etc/armbianmonitor/datasources/ac_current + ln -fs "${SysFSPrefix}"/usb/voltage_now /etc/armbianmonitor/datasources/usb_voltage + ln -fs "${SysFSPrefix}"/usb/current_now /etc/armbianmonitor/datasources/usb_current + ln -fs "${SysFSPrefix}"/battery/voltage_now /etc/armbianmonitor/datasources/battery_voltage + ln -fs "${SysFSPrefix}"/battery/current_now /etc/armbianmonitor/datasources/battery_current + ln -fs /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input /etc/armbianmonitor/datasources/pmictemp + ln -fs /sys/class/power_supply/battery/capacity /etc/armbianmonitor/datasources/battery_percent + ln -fs /sys/class/power_supply/battery/charging /etc/armbianmonitor/datasources/battery_charging + ln -fs /sys/class/power_supply/battery/connected /etc/armbianmonitor/datasources/battery_connected + ln -fs /sys/class/power_supply/battery/charge /etc/armbianmonitor/datasources/battery_charge + fi + # relink template + if [ "X${DebugMode}" = "XDEBUG" ]; then + ln -sf /etc/armbianmonitor/templates/axp209_template_debug.conf /etc/armbianmonitor/templates/cpu_pmic.conf + else + ln -sf /etc/armbianmonitor/templates/axp209_template.conf /etc/armbianmonitor/templates/cpu_pmic.conf + fi +} # DealWithAXP209 + +DealWithNewBoard() { + # check existence of sysfs nodes + if [ -f /sys/devices/virtual/thermal/thermal_zone0/temp ]; then + ln -fs /sys/devices/virtual/thermal/thermal_zone0/temp /etc/armbianmonitor/datasources/soctemp + elif [ -f /sys/devices/virtual/thermal/thermal_zone1/temp ]; then + ln -fs /sys/devices/virtual/thermal/thermal_zone1/temp /etc/armbianmonitor/datasources/soctemp + fi + # relink template + if [ "X${DebugMode}" = "XDEBUG" ]; then + ln -sf /etc/armbianmonitor/templates/unknown_board_template_debug.conf /etc/armbianmonitor/templates/cpu_pmic.conf + else + ln -sf /etc/armbianmonitor/templates/unknown_board_template.conf /etc/armbianmonitor/templates/cpu_pmic.conf + fi +} # DealWithNewBoard + +CreateTemplates() { + # check whether templates we write aren't symlinks to somewhere else + for i in armbian.conf uptime.conf version.conf ; do + if [ -L /etc/armbianmonitor/templates/${i} ]; then + rm /etc/armbianmonitor/templates/${i} + touch /etc/armbianmonitor/templates/${i} + chmod 711 /etc/armbianmonitor/templates/${i} + fi + done + + # check whether our logo is available + if [ ! -f /usr/share/rpimonitor/web/img/armbian.png ]; then + if [ -L /usr/share/rpimonitor/web/img/armbian.png ]; then + rm /usr/share/rpimonitor/web/img/armbian.png + fi + cp -p /etc/armbianmonitor/templates/armbian.png /usr/share/rpimonitor/web/img/ + fi + + # create main template + echo "web.page.icon='img/armbian.png' +web.page.menutitle='RPi-Monitor ('+data.hostname+')' +web.page.pagetitle='RPi-Monitor ('+data.hostname+')' +web.status.1.name=$ID +web.statistics.1.name=$ID +web.addons.1.name=Addons +web.addons.1.addons=about +include=/etc/armbianmonitor/templates/version.conf +include=/etc/armbianmonitor/templates/uptime.conf +include=/etc/armbianmonitor/templates/cpu_pmic.conf +include=/etc/rpimonitor/template/memory.conf" >/etc/armbianmonitor/armbian.conf + + # remove firmware line in version info: + grep -v "Firmware" /etc/rpimonitor/template/version.conf | sed 's|line.5|line.4|' >/etc/armbianmonitor/templates/version.conf + + # uptime template with correct machine name: + sed "s/Raspberry Pi/$ID/" < /etc/rpimonitor/template/uptime.conf >/etc/armbianmonitor/templates/uptime.conf + + # check swap settings. In case we're using swap then add template + HowManySwapDevices=$(swapon -s | wc -l) + if [[ ${HowManySwapDevices} -gt 1 ]]; then + echo "include=/etc/rpimonitor/template/swap.conf" >>/etc/armbianmonitor/armbian.conf + fi + + echo "include=/etc/armbianmonitor/template/filesystems.conf +include=/etc/armbianmonitor/template/disks.conf +include=/etc/rpimonitor/template/network.conf" >>/etc/armbianmonitor/armbian.conf + + UpdateFileSystems + UpdateDisks +} # + +UpdateFileSystems() { + # Generates /etc/armbianmonitor/template/filesystems.conf dynamically + # based on the contents of /etc/armbianmonitoring/filesystems.conf + + # if not existing, create config file with single entry for / + if [ ! -f /etc/armbianmonitoring/filesystems.conf ]; then + echo '/' >/etc/armbianmonitoring/filesystems.conf + chmod 711 /etc/armbianmonitoring/filesystems.conf + fi + + # Update template: + +} # UpdateFileSystems + +UpdateDisks() { + # Generates /etc/armbianmonitor/template/disks.conf dynamically + # based on the contents of /etc/armbianmonitor/disks.conf. The + # current mapping between GUIDs and /dev/sd* nodes will be stored + # in /etc/armbianmonitor/datasources/disk-by-guid + + # ensure lookup file is empty: + if [ -L /etc/armbianmonitor/datasources/disk-by-guid ]; then + rm -f /etc/armbianmonitor/datasources/disk-by-guid + fi + echo -n "" >/etc/armbianmonitor/datasources/disk-by-guid + chmod 711 /etc/armbianmonitor/datasources/disk-by-guid + + OIFS=${IFS} + IFS=: + cat /etc/armbianmonitor/disks.conf | while read ; do + IFS=: + set ${REPLY} + GUID="$1" + DiskName="$2" + SMARTPrefix="$3" + TempCommand="$4" + CRCAttribute="$5" + LCCAttribute="$6" + IFS=${OIFS} + + # try to resolve device node (when not present, then disk's + # not mounted -- we then create the entry without device node) + DeviceNode="$(ResolveGUID ${GUID})" + echo -e "${GUID}\t${DiskName}\t${DeviceNode}" >>/etc/armbianmonitor/datasources/disk-by-guid + + # create template stuff for every listed disk + : + done + IFS=${OIFS} +} # UpdateDisks + +ResolveGUID() { + # function that will be supplied with a GUID and returns the device node, eg. + # translating 637B7677-18E7-4C7B-8DF3-CFED96EA55C3 to /dev/sdb + + # check whether disks are existent + ls /sys/block/sd* >/dev/null 2>&1 || return + + for i in /sys/block/sd* ; do + DeviceNode=/dev/${i##*/} + GUID=$(gdisk -l ${DeviceNode} | awk -F" " '/^Disk identifier/ {print $4}') + if [ "X${GUID}" = "X${1}" ]; then + echo -n ${DeviceNode} + break + fi + done +} # GetGUIDforDisk + +PreRequisits() { + export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + unset LANG + LastDiskCheck=0 + + # we need the informations gathered from armhwinfo. In case we're not called + # from there, get the variables on our own + if [ "X${ID}" = "X" ]; then + . /etc/init.d/armhwinfo start >/dev/null 2>&1 + fi + + # check/create /etc/armbianmonitor and /etc/armbianmonitor/datasources + if [ ! -d /etc/armbianmonitor ]; then + mkdir -p -m 755 /etc/armbianmonitor + else + chmod 755 /etc/armbianmonitor + fi + if [ ! -d /etc/armbianmonitor/datasources ]; then + mkdir -p -m 755 /etc/armbianmonitor/datasources + else + chmod 755 /etc/armbianmonitor/datasources + fi + + # check whether we should do debug monitoring or normal + read DebugMode /dev/null | \ + egrep "^LV._|^LV_|extrem|boot_clock|_freq|^dram_" | \ + egrep -v "cpu_freq|dram_freq" | while read ; do + echo "# ${REPLY}" + done >/tmp/dvfs-table + + echo -e '\nGetVCore() {' >>/tmp/dvfs-table + + # parse /tmp/dvfs-table to get dvfs entries + grep "^# LV._freq" /tmp/dvfs-table | sort -r | while read ; do + set ${REPLY} + CPUFreq=$4 + # if [ ${CPUFreq} -eq 0 ]; then + # echo -e "if [ \$1 -ge $(( ${CPUFreq} / 1000 )) ]; then\n\techo -n ${VCore}\nel\c" >>/tmp/dvfs-table + # break + # else + # VCore=$(grep -A1 "^# $2" /tmp/dvfs-table | tail -n1 | awk -F" " '{print $4}') + # echo -e "if [ \$1 -ge $(( ${CPUFreq} / 1000 )) ]; then\n\techo -n ${VCore}\nel\c" >>/tmp/dvfs-table + if [ ${CPUFreq} -ne 0 ]; then + VCore=$(grep -A1 "^# $2" /tmp/dvfs-table | tail -n1 | awk -F" " '{print $4}') + echo -e "if [ \$1 -le $(( ${CPUFreq} / 1000 )) ]; then\n\techo -n ${VCore}\nel\c" >>/tmp/dvfs-table + fi + done + # VCore=$(grep -A1 "^# LV1_freq" /tmp/dvfs-table | tail -n1 | awk -F" " '{print $4}') + echo -e "se\n\techo -n ${VCore}\nfi\n}" >>/tmp/dvfs-table +} # ParseDVFSTable + +ProcessStats() { + set $(awk -F" " '/^cpu / {print $2"\t"$3"\t"$4"\t"$5"\t"$6"\t"$7"\t"$8}' /tmp/cpustat + + LastUserStat=${UserStat} + LastNiceStat=${NiceStat} + LastSystemStat=${SystemStat} + LastIdleStat=${IdleStat} + LastIOWaitStat=${IOWaitStat} + LastIrqStat=${IrqStat} + LastSoftIrqStat=${SoftIrqStat} +} # ProcessStats + +GetExternalTemp() { + # example function that parses meteo.physik.uni-muenchen.de and mingaweda.de + # temperature values for Munich and compares them. When values are out + # of bounds then only the other value will be returned otherwise the average + ExternalTemp1=$(/usr/bin/links -http.fake-user-agent 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12' -dump "http://www.meteo.physik.uni-muenchen.de/dokuwiki/doku.php?id=wetter:stadt:messung" | awk -F" " '/Lufttemperatur/ {printf ("%0.0f",$4*1000); }') + ExternalTemp2=$(/usr/bin/links -http.fake-user-agent 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12' -dump "http://www.mingaweda.de/wetterdaten/" | awk -F" " '/Ausfu:hrliche/ {printf ("%0.0f",$2*1000); }') + + if [ "X${ExternalTemp2}" = "X" ]; then + ExternalTemp2=${ExternalTemp1} + elif [ "X${ExternalTemp1}" = "X" ]; then + ExternalTemp1=${ExternalTemp2} + fi + + echo $(( ( ${ExternalTemp1} + ${ExternalTemp2} ) / 2 )) +} # GetExternalTemp + +Main