mirror of
				https://github.com/okunze/Argon40-ArgonOne-Script.git
				synced 2025-11-04 02:50:41 +01:00 
			
		
		
		
	Automated Change by GitHub Action
This commit is contained in:
		
				
					committed by
					
						
						github-actions[bot]
					
				
			
			
				
	
			
			
			
						parent
						
							1a7ab2e005
						
					
				
				
					commit
					755a2ca262
				
			
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 118 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								source/argoneon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/argoneon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 30 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgcpu.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgcpu.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgdefault.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgdefault.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgip.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgip.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgraid.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgraid.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgram.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgram.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgstorage.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgstorage.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgtemp.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgtemp.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/bgtime.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/bgtime.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font16x12.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font16x12.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font16x8.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font16x8.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font24x16.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font24x16.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font32x24.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font32x24.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font48x32.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font48x32.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font64x48.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font64x48.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/font8x6.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/font8x6.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								source/oled/logo1v5.bin
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								source/oled/logo1v5.bin
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										194
									
								
								source/scripts/argon-blstrdac.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								source/scripts/argon-blstrdac.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ -e /boot/firmware/config.txt ] ; then
 | 
			
		||||
  FIRMWARE=/firmware
 | 
			
		||||
else
 | 
			
		||||
  FIRMWARE=
 | 
			
		||||
fi
 | 
			
		||||
CONFIG=/boot${FIRMWARE}/config.txt
 | 
			
		||||
 | 
			
		||||
# Check if Raspbian
 | 
			
		||||
CHECKPLATFORM="Others"
 | 
			
		||||
if [ -f "/etc/os-release" ]
 | 
			
		||||
then
 | 
			
		||||
	source /etc/os-release
 | 
			
		||||
	if [ "$ID" = "raspbian" ]
 | 
			
		||||
	then
 | 
			
		||||
		CHECKPLATFORM="Raspbian"
 | 
			
		||||
	elif [ "$ID" = "debian" ]
 | 
			
		||||
	then
 | 
			
		||||
		# For backwards compatibility, continue using raspbian
 | 
			
		||||
		CHECKPLATFORM="Raspbian"
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
echo "------------------------------------"
 | 
			
		||||
echo " Argon BLSTR DAC Configuration Tool"
 | 
			
		||||
echo "------------------------------------"
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 100 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
irexecrcfile=/etc/lirc/irexec.lircrc
 | 
			
		||||
irexecshfile=/etc/argon/argonirexec
 | 
			
		||||
irdecodefile=/etc/argon/argonirdecoder
 | 
			
		||||
kodiuserdatafolder="$HOME/.kodi/userdata"
 | 
			
		||||
kodilircmapfile="$kodiuserdatafolder/Lircmap.xml"
 | 
			
		||||
remotemode=""
 | 
			
		||||
needinstallation=1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CONFIGSETTING="dtoverlay=hifiberry-dacplus,slave"
 | 
			
		||||
 | 
			
		||||
if grep -q -E "$CONFIGSETTING" $CONFIG
 | 
			
		||||
then
 | 
			
		||||
	# Already installed
 | 
			
		||||
	needinstallation=0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
loopflag=1
 | 
			
		||||
while [ $loopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	echo
 | 
			
		||||
	echo "Select option:"
 | 
			
		||||
	if [ $needinstallation -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "  1. Enable BLSTR DAC"
 | 
			
		||||
		echo "  2. Cancel"
 | 
			
		||||
		echo -n "Enter Number (1-2):"
 | 
			
		||||
	else
 | 
			
		||||
		echo "  1. Select audio configuration"
 | 
			
		||||
		echo "  2. Disable BLSTR DAC"
 | 
			
		||||
		echo "  3. Cancel"
 | 
			
		||||
		echo -n "Enter Number (1-3):"
 | 
			
		||||
	fi
 | 
			
		||||
	newmode=$( get_number )
 | 
			
		||||
	if [[ $newmode -ge 1 && $newmode -le 3 ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [[ $needinstallation -eq 1 && $newmode -ge 3 ]]
 | 
			
		||||
		then
 | 
			
		||||
			# Invalid option
 | 
			
		||||
			loopflag=1
 | 
			
		||||
			# Uninstall
 | 
			
		||||
		else
 | 
			
		||||
			loopflag=0
 | 
			
		||||
			if [ $needinstallation -eq 1 ]
 | 
			
		||||
			then
 | 
			
		||||
				if [ $newmode -eq 2 ]
 | 
			
		||||
				then
 | 
			
		||||
					# Cancel
 | 
			
		||||
					newmode=4
 | 
			
		||||
				fi
 | 
			
		||||
			else
 | 
			
		||||
				if [ $newmode -eq 1 ]
 | 
			
		||||
				then
 | 
			
		||||
					# Audio Conf
 | 
			
		||||
					newmode=3
 | 
			
		||||
				fi
 | 
			
		||||
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
needrestart=0
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
if [ $newmode -eq 2 ]
 | 
			
		||||
then
 | 
			
		||||
	# Uninstall
 | 
			
		||||
	blstrdactmpconfigfile=/dev/shm/argonblstrdacconfig.txt
 | 
			
		||||
 | 
			
		||||
	cat $CONFIG | grep -v "$CONFIGSETTING" > $blstrdactmpconfigfile
 | 
			
		||||
	cat $blstrdactmpconfigfile | sudo tee $CONFIG 1> /dev/null
 | 
			
		||||
	sudo rm $blstrdactmpconfigfile
 | 
			
		||||
 | 
			
		||||
	echo "Uninstall Completed"
 | 
			
		||||
	echo
 | 
			
		||||
 | 
			
		||||
	needrestart=1
 | 
			
		||||
 | 
			
		||||
elif [ $newmode -eq 3 ]
 | 
			
		||||
then
 | 
			
		||||
	# Audio Conf
 | 
			
		||||
 | 
			
		||||
	loopflag=1
 | 
			
		||||
	while [ $loopflag -eq 1 ]
 | 
			
		||||
	do
 | 
			
		||||
		echo
 | 
			
		||||
		echo "Select audio configuration:"
 | 
			
		||||
		echo "  1. PulseAudio"
 | 
			
		||||
		echo "  2. Pipewire"
 | 
			
		||||
		echo "  3. Cancel"
 | 
			
		||||
		echo -n "Enter Number (1-3):"
 | 
			
		||||
 | 
			
		||||
		newmode=$( get_number )
 | 
			
		||||
		if [[ $newmode -ge 1 && $newmode -le 3 ]]
 | 
			
		||||
		then
 | 
			
		||||
			loopflag=0
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	if [[ $newmode -ge 1 && $newmode -le 2 ]]
 | 
			
		||||
	then
 | 
			
		||||
		sudo raspi-config nonint do_audioconf $newmode
 | 
			
		||||
	else
 | 
			
		||||
		echo "Cancelled"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
elif [ $newmode -eq 1 ]
 | 
			
		||||
then
 | 
			
		||||
	# Install
 | 
			
		||||
 | 
			
		||||
	echo "$CONFIGSETTING" | sudo tee -a $CONFIG 1> /dev/null
 | 
			
		||||
 | 
			
		||||
	#sudo raspi-config nonint do_audioconf 1
 | 
			
		||||
	#systemctl --global -q disable pipewire-pulse
 | 
			
		||||
	#systemctl --global -q disable wireplumber
 | 
			
		||||
	#systemctl --global -q enable pulseaudio
 | 
			
		||||
	#if [ -e /etc/alsa/conf.d/99-pipewire-default.conf ] ; then
 | 
			
		||||
	#	rm /etc/alsa/conf.d/99-pipewire-default.conf
 | 
			
		||||
	#fi
 | 
			
		||||
 | 
			
		||||
	echo "Please run configuration and choose different audio configuration if there are problems"
 | 
			
		||||
 | 
			
		||||
	needrestart=1
 | 
			
		||||
else
 | 
			
		||||
	echo "Cancelled"
 | 
			
		||||
	#exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
#echo "Thank you."
 | 
			
		||||
if [ $needrestart -eq 1 ]
 | 
			
		||||
then
 | 
			
		||||
	echo "Changes should take after reboot."
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										568
									
								
								source/scripts/argon-rpi-eeprom-config-psu.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										568
									
								
								source/scripts/argon-rpi-eeprom-config-psu.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,568 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
# Based on /usr/bin/rpi-eeprom-config of bookworm
 | 
			
		||||
"""
 | 
			
		||||
rpi-eeprom-config
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import argparse
 | 
			
		||||
import atexit
 | 
			
		||||
import os
 | 
			
		||||
import subprocess
 | 
			
		||||
import string
 | 
			
		||||
import struct
 | 
			
		||||
import sys
 | 
			
		||||
import tempfile
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
VALID_IMAGE_SIZES = [512 * 1024, 2 * 1024 * 1024]
 | 
			
		||||
 | 
			
		||||
BOOTCONF_TXT = 'bootconf.txt'
 | 
			
		||||
BOOTCONF_SIG = 'bootconf.sig'
 | 
			
		||||
PUBKEY_BIN = 'pubkey.bin'
 | 
			
		||||
 | 
			
		||||
# Each section starts with a magic number followed by a 32 bit offset to the
 | 
			
		||||
# next section (big-endian).
 | 
			
		||||
# The number, order and size of the sections depends on the bootloader version
 | 
			
		||||
# but the following mask can be used to test for section headers and skip
 | 
			
		||||
# unknown data.
 | 
			
		||||
#
 | 
			
		||||
# The last 4KB of the EEPROM image is reserved for internal use by the
 | 
			
		||||
# bootloader and may be overwritten during the update process.
 | 
			
		||||
MAGIC = 0x55aaf00f
 | 
			
		||||
PAD_MAGIC = 0x55aafeef
 | 
			
		||||
MAGIC_MASK = 0xfffff00f
 | 
			
		||||
FILE_MAGIC = 0x55aaf11f # id for modifiable files
 | 
			
		||||
FILE_HDR_LEN = 20
 | 
			
		||||
FILENAME_LEN = 12
 | 
			
		||||
TEMP_DIR = None
 | 
			
		||||
 | 
			
		||||
# Modifiable files are stored in a single 4K erasable sector.
 | 
			
		||||
# The max content 4076 bytes because of the file header.
 | 
			
		||||
ERASE_ALIGN_SIZE = 4096
 | 
			
		||||
MAX_FILE_SIZE = ERASE_ALIGN_SIZE - FILE_HDR_LEN
 | 
			
		||||
 | 
			
		||||
DEBUG = False
 | 
			
		||||
 | 
			
		||||
# BEGIN: Argon40 added methods
 | 
			
		||||
def argon_rpisupported():
 | 
			
		||||
    # bcm2711 = pi4, bcm2712 = pi5
 | 
			
		||||
    return rpi5()
 | 
			
		||||
 | 
			
		||||
def argon_edit_config():
 | 
			
		||||
    # modified/stripped version of edit_config
 | 
			
		||||
 | 
			
		||||
    config_src = ''
 | 
			
		||||
    # If there is a pending update then use the configuration from
 | 
			
		||||
    # that in order to support incremental updates. Otherwise,
 | 
			
		||||
    # use the current EEPROM configuration.
 | 
			
		||||
    bootfs = shell_cmd(['rpi-eeprom-update', '-b']).rstrip()
 | 
			
		||||
    pending = os.path.join(bootfs, 'pieeprom.upd')
 | 
			
		||||
    if os.path.exists(pending):
 | 
			
		||||
        config_src = pending
 | 
			
		||||
        image = BootloaderImage(pending)
 | 
			
		||||
        current_config = image.get_file(BOOTCONF_TXT).decode('utf-8')
 | 
			
		||||
    else:
 | 
			
		||||
        current_config, config_src = read_current_config()
 | 
			
		||||
 | 
			
		||||
    # Add PSU Mas Current etc if not yet set
 | 
			
		||||
    foundnewsetting = 0
 | 
			
		||||
    addsetting="\nPSU_MAX_CURRENT=5000"
 | 
			
		||||
    current_config_lines = current_config.splitlines()
 | 
			
		||||
    new_config = current_config
 | 
			
		||||
    lineidx = 0
 | 
			
		||||
    while lineidx < len(current_config_lines):
 | 
			
		||||
        current_config_pair = current_config_lines[lineidx].split("=")
 | 
			
		||||
        newsetting = ""
 | 
			
		||||
        if current_config_pair[0] == "PSU_MAX_CURRENT":
 | 
			
		||||
            newsetting = "PSU_MAX_CURRENT=5000"
 | 
			
		||||
 | 
			
		||||
        if newsetting != "":
 | 
			
		||||
            addsetting = addsetting.replace("\n"+newsetting,"",1)
 | 
			
		||||
            if current_config_lines[lineidx] != newsetting:
 | 
			
		||||
                foundnewsetting = foundnewsetting + 1
 | 
			
		||||
                new_config = new_config.replace(current_config_lines[lineidx], newsetting, 1)
 | 
			
		||||
 | 
			
		||||
        lineidx = lineidx + 1
 | 
			
		||||
 | 
			
		||||
    if addsetting != "":
 | 
			
		||||
        # Append additional settings after [all]
 | 
			
		||||
        new_config = new_config.replace("[all]", "[all]"+addsetting, 1)
 | 
			
		||||
        foundnewsetting = foundnewsetting + 1
 | 
			
		||||
 | 
			
		||||
    if foundnewsetting == 0:
 | 
			
		||||
        # Already configured
 | 
			
		||||
        print("EEPROM settings up to date")
 | 
			
		||||
        sys.exit(0)
 | 
			
		||||
 | 
			
		||||
    # Skipped editor and write new config to temp file
 | 
			
		||||
    create_tempdir()
 | 
			
		||||
    tmp_conf = os.path.join(TEMP_DIR, 'boot.conf')
 | 
			
		||||
    out = open(tmp_conf, 'w')
 | 
			
		||||
    out.write(new_config)
 | 
			
		||||
    out.close()
 | 
			
		||||
 | 
			
		||||
    # Apply updates
 | 
			
		||||
 | 
			
		||||
    apply_update(tmp_conf, None, config_src)
 | 
			
		||||
 | 
			
		||||
# END: Argon40 added methods
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def debug(s):
 | 
			
		||||
    if DEBUG:
 | 
			
		||||
        sys.stderr.write(s + '\n')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def rpi4():
 | 
			
		||||
    compatible_path = "/sys/firmware/devicetree/base/compatible"
 | 
			
		||||
    if os.path.exists(compatible_path):
 | 
			
		||||
        with open(compatible_path, "rb") as f:
 | 
			
		||||
            compatible = f.read().decode('utf-8')
 | 
			
		||||
            if "bcm2711" in compatible:
 | 
			
		||||
                return True
 | 
			
		||||
    return False
 | 
			
		||||
 | 
			
		||||
def rpi5():
 | 
			
		||||
    compatible_path = "/sys/firmware/devicetree/base/compatible"
 | 
			
		||||
    if os.path.exists(compatible_path):
 | 
			
		||||
        with open(compatible_path, "rb") as f:
 | 
			
		||||
            compatible = f.read().decode('utf-8')
 | 
			
		||||
            if "bcm2712" in compatible:
 | 
			
		||||
                return True
 | 
			
		||||
    return False
 | 
			
		||||
 | 
			
		||||
def exit_handler():
 | 
			
		||||
    """
 | 
			
		||||
    Delete any temporary files.
 | 
			
		||||
    """
 | 
			
		||||
    if TEMP_DIR is not None and os.path.exists(TEMP_DIR):
 | 
			
		||||
        tmp_image = os.path.join(TEMP_DIR, 'pieeprom.upd')
 | 
			
		||||
        if os.path.exists(tmp_image):
 | 
			
		||||
            os.remove(tmp_image)
 | 
			
		||||
        tmp_conf = os.path.join(TEMP_DIR, 'boot.conf')
 | 
			
		||||
        if os.path.exists(tmp_conf):
 | 
			
		||||
            os.remove(tmp_conf)
 | 
			
		||||
        os.rmdir(TEMP_DIR)
 | 
			
		||||
 | 
			
		||||
def create_tempdir():
 | 
			
		||||
    global TEMP_DIR
 | 
			
		||||
    if TEMP_DIR is None:
 | 
			
		||||
        TEMP_DIR = tempfile.mkdtemp()
 | 
			
		||||
 | 
			
		||||
def pemtobin(infile):
 | 
			
		||||
    """
 | 
			
		||||
    Converts an RSA public key into the format expected by the bootloader.
 | 
			
		||||
    """
 | 
			
		||||
    # Import the package here to make this a weak dependency.
 | 
			
		||||
    from Cryptodome.PublicKey import RSA
 | 
			
		||||
 | 
			
		||||
    arr = bytearray()
 | 
			
		||||
    f = open(infile,'r')
 | 
			
		||||
    key = RSA.importKey(f.read())
 | 
			
		||||
 | 
			
		||||
    if key.size_in_bits() != 2048:
 | 
			
		||||
        raise Exception("RSA key size must be 2048")
 | 
			
		||||
 | 
			
		||||
    # Export N and E in little endian format
 | 
			
		||||
    arr.extend(key.n.to_bytes(256, byteorder='little'))
 | 
			
		||||
    arr.extend(key.e.to_bytes(8, byteorder='little'))
 | 
			
		||||
    return arr
 | 
			
		||||
 | 
			
		||||
def exit_error(msg):
 | 
			
		||||
    """
 | 
			
		||||
    Trapped a fatal error, output message to stderr and exit with non-zero
 | 
			
		||||
    return code.
 | 
			
		||||
    """
 | 
			
		||||
    sys.stderr.write("ERROR: %s\n" % msg)
 | 
			
		||||
    sys.exit(1)
 | 
			
		||||
 | 
			
		||||
def shell_cmd(args):
 | 
			
		||||
    """
 | 
			
		||||
    Executes a shell command waits for completion returning STDOUT. If an
 | 
			
		||||
    error occurs then exit and output the subprocess stdout, stderr messages
 | 
			
		||||
    for debug.
 | 
			
		||||
    """
 | 
			
		||||
    start = time.time()
 | 
			
		||||
    arg_str = ' '.join(args)
 | 
			
		||||
    result = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 | 
			
		||||
 | 
			
		||||
    while time.time() - start < 5:
 | 
			
		||||
        if result.poll() is not None:
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
    if result.poll() is None:
 | 
			
		||||
        exit_error("%s timeout" % arg_str)
 | 
			
		||||
 | 
			
		||||
    if result.returncode != 0:
 | 
			
		||||
        exit_error("%s failed: %d\n %s\n %s\n" %
 | 
			
		||||
                   (arg_str, result.returncode, result.stdout.read(), result.stderr.read()))
 | 
			
		||||
    else:
 | 
			
		||||
        return result.stdout.read().decode('utf-8')
 | 
			
		||||
 | 
			
		||||
def get_latest_eeprom():
 | 
			
		||||
    """
 | 
			
		||||
    Returns the path of the latest EEPROM image file if it exists.
 | 
			
		||||
    """
 | 
			
		||||
    latest = shell_cmd(['rpi-eeprom-update', '-l']).rstrip()
 | 
			
		||||
    if not os.path.exists(latest):
 | 
			
		||||
        exit_error("EEPROM image '%s' not found" % latest)
 | 
			
		||||
    return latest
 | 
			
		||||
 | 
			
		||||
def apply_update(config, eeprom=None, config_src=None):
 | 
			
		||||
    """
 | 
			
		||||
    Applies the config file to the latest available EEPROM image and spawns
 | 
			
		||||
    rpi-eeprom-update to schedule the update at the next reboot.
 | 
			
		||||
    """
 | 
			
		||||
    if eeprom is not None:
 | 
			
		||||
        eeprom_image = eeprom
 | 
			
		||||
    else:
 | 
			
		||||
        eeprom_image = get_latest_eeprom()
 | 
			
		||||
    create_tempdir()
 | 
			
		||||
 | 
			
		||||
    # Replace the contents of bootconf.txt with the contents of the config file
 | 
			
		||||
    tmp_update = os.path.join(TEMP_DIR, 'pieeprom.upd')
 | 
			
		||||
    image = BootloaderImage(eeprom_image, tmp_update)
 | 
			
		||||
    image.update_file(config, BOOTCONF_TXT)
 | 
			
		||||
    image.write()
 | 
			
		||||
 | 
			
		||||
    config_str = open(config).read()
 | 
			
		||||
    if config_src is None:
 | 
			
		||||
        config_src = ''
 | 
			
		||||
    sys.stdout.write("Updating bootloader EEPROM\n image: %s\nconfig_src: %s\nconfig: %s\n%s\n%s\n%s\n" %
 | 
			
		||||
                     (eeprom_image, config_src, config, '#' * 80, config_str, '#' * 80))
 | 
			
		||||
 | 
			
		||||
    sys.stdout.write("\n*** To cancel this update run 'sudo rpi-eeprom-update -r' ***\n\n")
 | 
			
		||||
 | 
			
		||||
    # Ignore APT package checksums so that this doesn't fail when used
 | 
			
		||||
    # with EEPROMs with configs delivered outside of APT.
 | 
			
		||||
    # The checksums are really just a safety check for automatic updates.
 | 
			
		||||
    args = ['rpi-eeprom-update', '-d', '-i', '-f', tmp_update]
 | 
			
		||||
    resp = shell_cmd(args)
 | 
			
		||||
    sys.stdout.write(resp)
 | 
			
		||||
 | 
			
		||||
def edit_config(eeprom=None):
 | 
			
		||||
    """
 | 
			
		||||
    Implements something like 'git commit' for editing EEPROM configs.
 | 
			
		||||
    """
 | 
			
		||||
    # Default to nano if $EDITOR is not defined.
 | 
			
		||||
    editor = 'nano'
 | 
			
		||||
    if 'EDITOR' in os.environ:
 | 
			
		||||
        editor = os.environ['EDITOR']
 | 
			
		||||
 | 
			
		||||
    config_src = ''
 | 
			
		||||
    # If there is a pending update then use the configuration from
 | 
			
		||||
    # that in order to support incremental updates. Otherwise,
 | 
			
		||||
    # use the current EEPROM configuration.
 | 
			
		||||
    bootfs = shell_cmd(['rpi-eeprom-update', '-b']).rstrip()
 | 
			
		||||
    pending = os.path.join(bootfs, 'pieeprom.upd')
 | 
			
		||||
    if os.path.exists(pending):
 | 
			
		||||
        config_src = pending
 | 
			
		||||
        image = BootloaderImage(pending)
 | 
			
		||||
        current_config = image.get_file(BOOTCONF_TXT).decode('utf-8')
 | 
			
		||||
    else:
 | 
			
		||||
        current_config, config_src = read_current_config()
 | 
			
		||||
 | 
			
		||||
    create_tempdir()
 | 
			
		||||
    tmp_conf = os.path.join(TEMP_DIR, 'boot.conf')
 | 
			
		||||
    out = open(tmp_conf, 'w')
 | 
			
		||||
    out.write(current_config)
 | 
			
		||||
    out.close()
 | 
			
		||||
    cmd = "\'%s\' \'%s\'" % (editor, tmp_conf)
 | 
			
		||||
    result = os.system(cmd)
 | 
			
		||||
    if result != 0:
 | 
			
		||||
        exit_error("Aborting update because \'%s\' exited with code %d." % (cmd, result))
 | 
			
		||||
 | 
			
		||||
    new_config = open(tmp_conf, 'r').read()
 | 
			
		||||
    if len(new_config.splitlines()) < 2:
 | 
			
		||||
        exit_error("Aborting update because \'%s\' appears to be empty." % tmp_conf)
 | 
			
		||||
    apply_update(tmp_conf, eeprom, config_src)
 | 
			
		||||
 | 
			
		||||
def read_current_config():
 | 
			
		||||
    """
 | 
			
		||||
    Reads the configuration used by the current bootloader.
 | 
			
		||||
    """
 | 
			
		||||
    fw_base = "/sys/firmware/devicetree/base/"
 | 
			
		||||
    nvmem_base = "/sys/bus/nvmem/devices/"
 | 
			
		||||
 | 
			
		||||
    if os.path.exists(fw_base + "/aliases/blconfig"):
 | 
			
		||||
        with open(fw_base + "/aliases/blconfig", "rb") as f:
 | 
			
		||||
            nvmem_ofnode_path = fw_base + f.read().decode('utf-8')
 | 
			
		||||
            for d in os.listdir(nvmem_base):
 | 
			
		||||
                if os.path.realpath(nvmem_base + d + "/of_node") in os.path.normpath(nvmem_ofnode_path):
 | 
			
		||||
                    return (open(nvmem_base + d + "/nvmem", "rb").read().decode('utf-8'), "blconfig device")
 | 
			
		||||
 | 
			
		||||
    return (shell_cmd(['vcgencmd', 'bootloader_config']), "vcgencmd bootloader_config")
 | 
			
		||||
 | 
			
		||||
class ImageSection:
 | 
			
		||||
    def __init__(self, magic, offset, length, filename=''):
 | 
			
		||||
        self.magic = magic
 | 
			
		||||
        self.offset = offset
 | 
			
		||||
        self.length = length
 | 
			
		||||
        self.filename = filename
 | 
			
		||||
        debug("ImageSection %x offset %d length %d %s" % (magic, offset, length, filename))
 | 
			
		||||
 | 
			
		||||
class BootloaderImage(object):
 | 
			
		||||
    def __init__(self, filename, output=None):
 | 
			
		||||
        """
 | 
			
		||||
        Instantiates a Bootloader image writer with a source eeprom (filename)
 | 
			
		||||
        and optionally an output filename.
 | 
			
		||||
        """
 | 
			
		||||
        self._filename = filename
 | 
			
		||||
        self._sections = []
 | 
			
		||||
        self._image_size = 0
 | 
			
		||||
        try:
 | 
			
		||||
            self._bytes = bytearray(open(filename, 'rb').read())
 | 
			
		||||
        except IOError as err:
 | 
			
		||||
            exit_error("Failed to read \'%s\'\n%s\n" % (filename, str(err)))
 | 
			
		||||
        self._out = None
 | 
			
		||||
        if output is not None:
 | 
			
		||||
            self._out = open(output, 'wb')
 | 
			
		||||
 | 
			
		||||
        self._image_size = len(self._bytes)
 | 
			
		||||
        if self._image_size not in VALID_IMAGE_SIZES:
 | 
			
		||||
            exit_error("%s: Expected size %d bytes actual size %d bytes" %
 | 
			
		||||
                       (filename, self._image_size, len(self._bytes)))
 | 
			
		||||
        self.parse()
 | 
			
		||||
 | 
			
		||||
    def parse(self):
 | 
			
		||||
        """
 | 
			
		||||
        Builds a table of offsets to the different sections in the EEPROM.
 | 
			
		||||
        """
 | 
			
		||||
        offset = 0
 | 
			
		||||
        magic = 0
 | 
			
		||||
        while offset < self._image_size:
 | 
			
		||||
            magic, length = struct.unpack_from('>LL', self._bytes, offset)
 | 
			
		||||
            if magic == 0x0 or magic == 0xffffffff:
 | 
			
		||||
                break # EOF
 | 
			
		||||
            elif (magic & MAGIC_MASK) != MAGIC:
 | 
			
		||||
                raise Exception('EEPROM is corrupted %x %x %x' % (magic, magic & MAGIC_MASK, MAGIC))
 | 
			
		||||
 | 
			
		||||
            filename = ''
 | 
			
		||||
            if magic == FILE_MAGIC: # Found a file
 | 
			
		||||
                # Discard trailing null characters used to pad filename
 | 
			
		||||
                filename = self._bytes[offset + 8: offset + FILE_HDR_LEN].decode('utf-8').replace('\0', '')
 | 
			
		||||
            debug("section at %d length %d magic %08x %s" % (offset, length, magic, filename))
 | 
			
		||||
            self._sections.append(ImageSection(magic, offset, length, filename))
 | 
			
		||||
 | 
			
		||||
            offset += 8 + length # length + type
 | 
			
		||||
            offset = (offset + 7) & ~7
 | 
			
		||||
 | 
			
		||||
    def find_file(self, filename):
 | 
			
		||||
        """
 | 
			
		||||
        Returns the offset, length and whether this is the last section in the
 | 
			
		||||
        EEPROM for a modifiable file within the image.
 | 
			
		||||
        """
 | 
			
		||||
        offset = -1
 | 
			
		||||
        length = -1
 | 
			
		||||
        is_last = False
 | 
			
		||||
 | 
			
		||||
        next_offset = self._image_size - ERASE_ALIGN_SIZE # Don't create padding inside the bootloader scratch page
 | 
			
		||||
        for i in range(0, len(self._sections)):
 | 
			
		||||
            s = self._sections[i]
 | 
			
		||||
            if s.magic == FILE_MAGIC and s.filename == filename:
 | 
			
		||||
                is_last = (i == len(self._sections) - 1)
 | 
			
		||||
                offset = s.offset
 | 
			
		||||
                length = s.length
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        # Find the start of the next non padding section
 | 
			
		||||
        i += 1
 | 
			
		||||
        while i < len(self._sections):
 | 
			
		||||
            if self._sections[i].magic == PAD_MAGIC:
 | 
			
		||||
                i += 1
 | 
			
		||||
            else:
 | 
			
		||||
                next_offset = self._sections[i].offset
 | 
			
		||||
                break
 | 
			
		||||
        ret = (offset, length, is_last, next_offset)
 | 
			
		||||
        debug('%s offset %d length %d is-last %d next %d' % (filename, ret[0], ret[1], ret[2], ret[3]))
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
    def update(self, src_bytes, dst_filename):
 | 
			
		||||
        """
 | 
			
		||||
        Replaces a modifiable file with specified byte array.
 | 
			
		||||
        """
 | 
			
		||||
        hdr_offset, length, is_last, next_offset = self.find_file(dst_filename)
 | 
			
		||||
        update_len = len(src_bytes) + FILE_HDR_LEN
 | 
			
		||||
 | 
			
		||||
        if hdr_offset + update_len > self._image_size - ERASE_ALIGN_SIZE:
 | 
			
		||||
            raise Exception('No space available - image past EOF.')
 | 
			
		||||
 | 
			
		||||
        if hdr_offset < 0:
 | 
			
		||||
            raise Exception('Update target %s not found' % dst_filename)
 | 
			
		||||
 | 
			
		||||
        if hdr_offset + update_len > next_offset:
 | 
			
		||||
            raise Exception('Update %d bytes is larger than section size %d' % (update_len, next_offset - hdr_offset))
 | 
			
		||||
 | 
			
		||||
        new_len = len(src_bytes) + FILENAME_LEN + 4
 | 
			
		||||
        struct.pack_into('>L', self._bytes, hdr_offset + 4, new_len)
 | 
			
		||||
        struct.pack_into(("%ds" % len(src_bytes)), self._bytes,
 | 
			
		||||
                         hdr_offset + 4 + FILE_HDR_LEN, src_bytes)
 | 
			
		||||
 | 
			
		||||
        # If the new file is smaller than the old file then set any old
 | 
			
		||||
        # data which is now unused to all ones (erase value)
 | 
			
		||||
        pad_start = hdr_offset + 4 + FILE_HDR_LEN + len(src_bytes)
 | 
			
		||||
 | 
			
		||||
        # Add padding up to 8-byte boundary
 | 
			
		||||
        while pad_start % 8 != 0:
 | 
			
		||||
            struct.pack_into('B', self._bytes, pad_start, 0xff)
 | 
			
		||||
            pad_start += 1
 | 
			
		||||
 | 
			
		||||
        # Create a padding section unless the padding size is smaller than the
 | 
			
		||||
        # size of a section head. Padding is allowed in the last section but
 | 
			
		||||
        # by convention bootconf.txt is the last section and there's no need to
 | 
			
		||||
        # pad to the end of the sector. This also ensures that the loopback
 | 
			
		||||
        # config read/write tests produce identical binaries.
 | 
			
		||||
        pad_bytes = next_offset - pad_start
 | 
			
		||||
        if pad_bytes > 8 and not is_last:
 | 
			
		||||
            pad_bytes -= 8
 | 
			
		||||
            struct.pack_into('>i', self._bytes, pad_start, PAD_MAGIC)
 | 
			
		||||
            pad_start += 4
 | 
			
		||||
            struct.pack_into('>i', self._bytes, pad_start, pad_bytes)
 | 
			
		||||
            pad_start += 4
 | 
			
		||||
 | 
			
		||||
        debug("pad %d" % pad_bytes)
 | 
			
		||||
        pad = 0
 | 
			
		||||
        while pad < pad_bytes:
 | 
			
		||||
            struct.pack_into('B', self._bytes, pad_start + pad, 0xff)
 | 
			
		||||
            pad = pad + 1
 | 
			
		||||
 | 
			
		||||
    def update_key(self, src_pem, dst_filename):
 | 
			
		||||
        """
 | 
			
		||||
        Replaces the specified public key entry with the public key values extracted
 | 
			
		||||
        from the source PEM file.
 | 
			
		||||
        """
 | 
			
		||||
        pubkey_bytes = pemtobin(src_pem)
 | 
			
		||||
        self.update(pubkey_bytes, dst_filename)
 | 
			
		||||
 | 
			
		||||
    def update_file(self, src_filename, dst_filename):
 | 
			
		||||
        """
 | 
			
		||||
        Replaces the contents of dst_filename in the EEPROM with the contents of src_file.
 | 
			
		||||
        """
 | 
			
		||||
        src_bytes = open(src_filename, 'rb').read()
 | 
			
		||||
        if len(src_bytes) > MAX_FILE_SIZE:
 | 
			
		||||
            raise Exception("src file %s is too large (%d bytes). The maximum size is %d bytes."
 | 
			
		||||
                            % (src_filename, len(src_bytes), MAX_FILE_SIZE))
 | 
			
		||||
        self.update(src_bytes, dst_filename)
 | 
			
		||||
 | 
			
		||||
    def write(self):
 | 
			
		||||
        """
 | 
			
		||||
        Writes the updated EEPROM image to stdout or the specified output file.
 | 
			
		||||
        """
 | 
			
		||||
        if self._out is not None:
 | 
			
		||||
            self._out.write(self._bytes)
 | 
			
		||||
            self._out.close()
 | 
			
		||||
        else:
 | 
			
		||||
            if hasattr(sys.stdout, 'buffer'):
 | 
			
		||||
                sys.stdout.buffer.write(self._bytes)
 | 
			
		||||
            else:
 | 
			
		||||
                sys.stdout.write(self._bytes)
 | 
			
		||||
 | 
			
		||||
    def get_file(self, filename):
 | 
			
		||||
        hdr_offset, length, is_last, next_offset = self.find_file(filename)
 | 
			
		||||
        offset = hdr_offset + 4 + FILE_HDR_LEN
 | 
			
		||||
        file_bytes = self._bytes[offset:offset+length-FILENAME_LEN-4]
 | 
			
		||||
        return file_bytes
 | 
			
		||||
 | 
			
		||||
    def extract_files(self):
 | 
			
		||||
        for i in range(0, len(self._sections)):
 | 
			
		||||
            s = self._sections[i]
 | 
			
		||||
            if s.magic == FILE_MAGIC:
 | 
			
		||||
                file_bytes = self.get_file(s.filename)
 | 
			
		||||
                open(s.filename, 'wb').write(file_bytes)
 | 
			
		||||
 | 
			
		||||
    def read(self):
 | 
			
		||||
        config_bytes = self.get_file('bootconf.txt')
 | 
			
		||||
        if self._out is not None:
 | 
			
		||||
            self._out.write(config_bytes)
 | 
			
		||||
            self._out.close()
 | 
			
		||||
        else:
 | 
			
		||||
            if hasattr(sys.stdout, 'buffer'):
 | 
			
		||||
                sys.stdout.buffer.write(config_bytes)
 | 
			
		||||
            else:
 | 
			
		||||
                sys.stdout.write(config_bytes)
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    """
 | 
			
		||||
    Utility for reading and writing the configuration file in the
 | 
			
		||||
    Raspberry Pi bootloader EEPROM image.
 | 
			
		||||
    """
 | 
			
		||||
    description = """\
 | 
			
		||||
Bootloader EEPROM configuration tool for the Raspberry Pi 4 and Raspberry Pi 5.
 | 
			
		||||
Operating modes:
 | 
			
		||||
 | 
			
		||||
1. Outputs the current bootloader configuration to STDOUT if no arguments are
 | 
			
		||||
   specified OR the given output file if --out is specified.
 | 
			
		||||
 | 
			
		||||
   rpi-eeprom-config [--out boot.conf]
 | 
			
		||||
 | 
			
		||||
2. Extracts the configuration file from the given 'eeprom' file and outputs
 | 
			
		||||
   the result to STDOUT or the output file if --output is specified.
 | 
			
		||||
 | 
			
		||||
   rpi-eeprom-config pieeprom.bin [--out boot.conf]
 | 
			
		||||
 | 
			
		||||
3. Writes a new EEPROM image replacing the configuration file with the contents
 | 
			
		||||
   of the file specified by --config.
 | 
			
		||||
 | 
			
		||||
   rpi-eeprom-config --config boot.conf --out newimage.bin pieeprom.bin
 | 
			
		||||
 | 
			
		||||
   The new image file can be installed via rpi-eeprom-update
 | 
			
		||||
   rpi-eeprom-update -d -f newimage.bin
 | 
			
		||||
 | 
			
		||||
4. Applies a given config file to an EEPROM image and invokes rpi-eeprom-update
 | 
			
		||||
   to schedule an update of the bootloader when the system is rebooted.
 | 
			
		||||
 | 
			
		||||
   Since this command launches rpi-eeprom-update to schedule the EEPROM update
 | 
			
		||||
   it must be run as root.
 | 
			
		||||
 | 
			
		||||
   sudo rpi-eeprom-config --apply boot.conf [pieeprom.bin]
 | 
			
		||||
 | 
			
		||||
   If the 'eeprom' argument is not specified then the latest available image
 | 
			
		||||
   is selected by calling 'rpi-eeprom-update -l'.
 | 
			
		||||
 | 
			
		||||
5. The '--edit' parameter behaves the same as '--apply' except that instead of
 | 
			
		||||
   applying a predefined configuration file a text editor is launched with the
 | 
			
		||||
   contents of the current EEPROM configuration.
 | 
			
		||||
 | 
			
		||||
   Since this command launches rpi-eeprom-update to schedule the EEPROM update
 | 
			
		||||
   it must be run as root.
 | 
			
		||||
 | 
			
		||||
   The configuration file will be taken from:
 | 
			
		||||
       * The blconfig reserved memory nvmem device
 | 
			
		||||
       * The cached bootloader configuration 'vcgencmd bootloader_config'
 | 
			
		||||
       * The current pending update - typically /boot/pieeprom.upd
 | 
			
		||||
 | 
			
		||||
   sudo -E rpi-eeprom-config --edit [pieeprom.bin]
 | 
			
		||||
 | 
			
		||||
   To cancel the pending update run 'sudo rpi-eeprom-update -r'
 | 
			
		||||
 | 
			
		||||
   The default text editor is nano and may be overridden by setting the 'EDITOR'
 | 
			
		||||
   environment variable and passing '-E' to 'sudo' to preserve the environment.
 | 
			
		||||
 | 
			
		||||
6. Signing the bootloader config file.
 | 
			
		||||
   Updates an EEPROM binary with a signed config file (created by rpi-eeprom-digest) plus
 | 
			
		||||
   the corresponding RSA public key.
 | 
			
		||||
 | 
			
		||||
   Requires Python Cryptodomex libraries and OpenSSL. To install on Raspberry Pi OS run:-
 | 
			
		||||
   sudo apt install openssl python-pip
 | 
			
		||||
   sudo python3 -m pip install cryptodomex
 | 
			
		||||
 | 
			
		||||
   rpi-eeprom-digest -k private.pem -i bootconf.txt -o bootconf.sig
 | 
			
		||||
   rpi-eeprom-config --config bootconf.txt --digest bootconf.sig --pubkey public.pem --out pieeprom-signed.bin pieeprom.bin
 | 
			
		||||
 | 
			
		||||
   Currently, the signing process is a separate step so can't be used with the --edit or --apply modes.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
See 'rpi-eeprom-update -h' for more information about the available EEPROM images.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
    if os.getuid() != 0:
 | 
			
		||||
        exit_error("Please run as root")
 | 
			
		||||
    elif not argon_rpisupported():
 | 
			
		||||
        # Skip
 | 
			
		||||
        sys.exit(0)
 | 
			
		||||
    argon_edit_config()
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    atexit.register(exit_handler)
 | 
			
		||||
    main()
 | 
			
		||||
							
								
								
									
										22
									
								
								source/scripts/argon-shutdown.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								source/scripts/argon-shutdown.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
pythonbin=/usr/bin/python3
 | 
			
		||||
argononefanscript=/etc/argon/argononed.py
 | 
			
		||||
argoneonrtcscript=/etc/argon/argoneond.py
 | 
			
		||||
argonirconfigscript=/etc/argon/argonone-ir
 | 
			
		||||
 | 
			
		||||
if [ ! -z "$1" ]
 | 
			
		||||
then
 | 
			
		||||
	$pythonbin $argononefanscript FANOFF
 | 
			
		||||
	if [ "$1" = "poweroff" ] || [ "$1" = "halt" ]
 | 
			
		||||
	then
 | 
			
		||||
		if [ -f $argonirconfigscript ]
 | 
			
		||||
		then
 | 
			
		||||
			if [ -f $argoneonrtcscript ]
 | 
			
		||||
			then
 | 
			
		||||
				$pythonbin $argoneonrtcscript SHUTDOWN
 | 
			
		||||
			fi
 | 
			
		||||
			$pythonbin $argononefanscript SHUTDOWN
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										106
									
								
								source/scripts/argon-status.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								source/scripts/argon-status.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 100 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
INSTALLATIONFOLDER=/etc/argon
 | 
			
		||||
pythonbin="sudo /usr/bin/python3"
 | 
			
		||||
argonstatusscript=$INSTALLATIONFOLDER/argonstatus.py
 | 
			
		||||
argondashboardscript=$INSTALLATIONFOLDER/argondashboard.py
 | 
			
		||||
argononefanscript=$INSTALLATIONFOLDER/argononed.py
 | 
			
		||||
argoneonrtcscript=$INSTALLATIONFOLDER/argoneond.py
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
echo "--------------------------"
 | 
			
		||||
echo " Argon System Information"
 | 
			
		||||
echo "--------------------------"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
loopflag=1
 | 
			
		||||
while [ $loopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	echo
 | 
			
		||||
	echo "  1. Temperatures"
 | 
			
		||||
	echo "  2. CPU Utilization"
 | 
			
		||||
	echo "  3. Storage Capacity"
 | 
			
		||||
	echo "  4. RAM"
 | 
			
		||||
	echo "  5. IP Address"
 | 
			
		||||
	lastoption=5
 | 
			
		||||
	if [ -f $argononefanscript ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "  6. Fan Speed"
 | 
			
		||||
		lastoption=6
 | 
			
		||||
	fi
 | 
			
		||||
	if [ -f "$argoneonrtcscript" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "  7. RTC Schedules"
 | 
			
		||||
		echo "  8. RAID"
 | 
			
		||||
		lastoption=8
 | 
			
		||||
	fi
 | 
			
		||||
	lastoption=$((lastoption + 1))
 | 
			
		||||
	echo "  ${lastoption}. Dashboard"
 | 
			
		||||
	echo
 | 
			
		||||
	echo "  0. Back"
 | 
			
		||||
	echo -n "Enter Number (0-${lastoption}):"
 | 
			
		||||
 | 
			
		||||
	newmode=$( get_number )
 | 
			
		||||
	if [ $newmode -eq 0 ]
 | 
			
		||||
	then
 | 
			
		||||
		loopflag=0
 | 
			
		||||
	elif [ $newmode -gt 0 ] && [ $newmode -le $lastoption ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "--------------------------"
 | 
			
		||||
		if [ $newmode -eq $lastoption ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argondashboardscript
 | 
			
		||||
		elif [ $newmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "temperature"
 | 
			
		||||
		elif [ $newmode -eq 2 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "cpu usage"
 | 
			
		||||
		elif [ $newmode -eq 3 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "storage"
 | 
			
		||||
		elif [ $newmode -eq 4 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "ram"
 | 
			
		||||
		elif [ $newmode -eq 5 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "ip"
 | 
			
		||||
		elif [ $newmode -eq 6 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "temperature" "fan configuration" "fan speed"
 | 
			
		||||
		elif [ $newmode -eq 7 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argoneonrtcscript GETSCHEDULELIST
 | 
			
		||||
		elif [ $newmode -eq 8 ]
 | 
			
		||||
		then
 | 
			
		||||
			$pythonbin $argonstatusscript "raid"
 | 
			
		||||
		fi
 | 
			
		||||
		echo "--------------------------"
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										131
									
								
								source/scripts/argon-uninstall.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								source/scripts/argon-uninstall.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
echo "----------------------"
 | 
			
		||||
echo " Argon Uninstall Tool"
 | 
			
		||||
echo "----------------------"
 | 
			
		||||
echo -n "Press Y to continue:"
 | 
			
		||||
read -n 1 confirm
 | 
			
		||||
echo
 | 
			
		||||
if [ "$confirm" = "y" ]
 | 
			
		||||
then
 | 
			
		||||
	confirm="Y"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "$confirm" != "Y" ]
 | 
			
		||||
then
 | 
			
		||||
	echo "Cancelled"
 | 
			
		||||
	exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
destfoldername=$USERNAME
 | 
			
		||||
if [ -z "$destfoldername" ]
 | 
			
		||||
then
 | 
			
		||||
	destfoldername=$USER
 | 
			
		||||
fi
 | 
			
		||||
if [ "$destfoldername" = "root" ]
 | 
			
		||||
then
 | 
			
		||||
	destfoldername=""
 | 
			
		||||
fi
 | 
			
		||||
if [ -z "$destfoldername" ]
 | 
			
		||||
then
 | 
			
		||||
	destfoldername="pi"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
shortcutfile="/home/$destfoldername/Desktop/argonone-config.desktop"
 | 
			
		||||
if [ -f "$shortcutfile" ]; then
 | 
			
		||||
	sudo rm $shortcutfile
 | 
			
		||||
	if [ -f "/usr/share/pixmaps/ar1config.png" ]; then
 | 
			
		||||
		sudo rm /usr/share/pixmaps/ar1config.png
 | 
			
		||||
	fi
 | 
			
		||||
	if [ -f "/usr/share/pixmaps/argoneon.png" ]; then
 | 
			
		||||
		sudo rm /usr/share/pixmaps/argoneon.png
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
INSTALLATIONFOLDER=/etc/argon
 | 
			
		||||
 | 
			
		||||
argononefanscript=$INSTALLATIONFOLDER/argononed.py
 | 
			
		||||
 | 
			
		||||
if [ -f $argononefanscript ]; then
 | 
			
		||||
	sudo systemctl stop argononed.service
 | 
			
		||||
	sudo systemctl disable argononed.service
 | 
			
		||||
 | 
			
		||||
	# Turn off the fan
 | 
			
		||||
	/usr/bin/python3 $argononefanscript FANOFF
 | 
			
		||||
 | 
			
		||||
	# Remove files
 | 
			
		||||
	sudo rm /lib/systemd/system/argononed.service
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Remove RTC if any
 | 
			
		||||
argoneonrtcscript=$INSTALLATIONFOLDER/argoneond.py
 | 
			
		||||
if [ -f "$argoneonrtcscript" ]
 | 
			
		||||
then
 | 
			
		||||
	# Disable Services
 | 
			
		||||
	sudo systemctl stop argoneond.service
 | 
			
		||||
	sudo systemctl disable argoneond.service
 | 
			
		||||
 | 
			
		||||
	# No need for sudo
 | 
			
		||||
	/usr/bin/python3 $argoneonrtcscript CLEAN
 | 
			
		||||
	/usr/bin/python3 $argoneonrtcscript SHUTDOWN
 | 
			
		||||
 | 
			
		||||
	# Remove files
 | 
			
		||||
	sudo rm /lib/systemd/system/argoneond.service
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Remove UPS daemon if any
 | 
			
		||||
argononeupsscript=$INSTALLATIONFOLDER/argononeupsd.py
 | 
			
		||||
if [ -f "$argononeupsscript" ]
 | 
			
		||||
then
 | 
			
		||||
	sudo rmmod argonbatteryicon
 | 
			
		||||
	# Disable Services
 | 
			
		||||
	sudo systemctl stop argononeupsd.service
 | 
			
		||||
	sudo systemctl disable argononeupsd.service
 | 
			
		||||
 | 
			
		||||
	sudo systemctl stop argonupsrtcd.service
 | 
			
		||||
	sudo systemctl disable argonupsrtcd.service
 | 
			
		||||
 | 
			
		||||
	# Remove files
 | 
			
		||||
	sudo rm /lib/systemd/system/argononeupsd.service
 | 
			
		||||
	sudo rm /lib/systemd/system/argonupsrtcd.service
 | 
			
		||||
 | 
			
		||||
	find "/home" -maxdepth 1 -type  d | while read line; do
 | 
			
		||||
		shortcutfile="$line/Desktop/argonone-ups.desktop"
 | 
			
		||||
		if [ -f "$shortcutfile" ]; then
 | 
			
		||||
			sudo rm $shortcutfile
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
sudo rm /usr/bin/argon-config
 | 
			
		||||
 | 
			
		||||
if [ -f "/usr/bin/argonone-config" ]
 | 
			
		||||
then
 | 
			
		||||
		sudo rm /usr/bin/argonone-config
 | 
			
		||||
		sudo rm /usr/bin/argonone-uninstall
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ -f "/usr/bin/argonone-ir" ]
 | 
			
		||||
then
 | 
			
		||||
		sudo rm /usr/bin/argonone-ir
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Delete config files
 | 
			
		||||
for configfile in argonunits argononed argononed-hdd argoneonrtc argoneonoled argonupsrtc
 | 
			
		||||
do
 | 
			
		||||
	if [ -f "/etc/${configfile}.conf" ]
 | 
			
		||||
	then
 | 
			
		||||
		sudo rm "/etc/${configfile}.conf"
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sudo rm /lib/systemd/system-shutdown/argon-shutdown.sh
 | 
			
		||||
 | 
			
		||||
sudo rm -R -f $INSTALLATIONFOLDER
 | 
			
		||||
 | 
			
		||||
echo "Removed Argon Services."
 | 
			
		||||
echo "Cleanup will complete after restarting the device."
 | 
			
		||||
							
								
								
									
										105
									
								
								source/scripts/argon-unitconfig.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								source/scripts/argon-unitconfig.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
unitconfigfile=/etc/argonunits.conf
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 100 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
saveconfig () {
 | 
			
		||||
	echo "#" > $unitconfigfile
 | 
			
		||||
	echo "# Argon Unit Configuration" >> $unitconfigfile
 | 
			
		||||
	echo "#" >> $unitconfigfile
 | 
			
		||||
	echo "temperature=$1" >> $unitconfigfile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
updateconfig=1
 | 
			
		||||
unitloopflag=1
 | 
			
		||||
while [ $unitloopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	if [ $updateconfig -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		. $unitconfigfile
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	updateconfig=0
 | 
			
		||||
	if [ -z "$temperature" ]
 | 
			
		||||
	then
 | 
			
		||||
		temperature="C"
 | 
			
		||||
		updateconfig=1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	# Write default values to config file, daemon already uses default so no need to restart service
 | 
			
		||||
	if [ $updateconfig -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		saveconfig $temperature
 | 
			
		||||
		updateconfig=0
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	echo "-----------------------------"
 | 
			
		||||
	echo "Argon Display Units"
 | 
			
		||||
	echo "-----------------------------"
 | 
			
		||||
	echo "Choose from the list:"
 | 
			
		||||
	echo "  1. Temperature: $temperature"
 | 
			
		||||
	echo
 | 
			
		||||
	echo "  0. Back"
 | 
			
		||||
	echo -n "Enter Number (0-1):"
 | 
			
		||||
 | 
			
		||||
	newmode=$( get_number )
 | 
			
		||||
	if [ $newmode -eq 0 ]
 | 
			
		||||
	then
 | 
			
		||||
		unitloopflag=0
 | 
			
		||||
	elif [ $newmode -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo
 | 
			
		||||
		echo "-----------------------------"
 | 
			
		||||
		echo "Temperature Display"
 | 
			
		||||
		echo "-----------------------------"
 | 
			
		||||
		echo "Choose from the list:"
 | 
			
		||||
		echo "  1. Celsius"
 | 
			
		||||
		echo "  2. Fahrenheit"
 | 
			
		||||
		echo
 | 
			
		||||
		echo "  0. Cancel"
 | 
			
		||||
		echo -n "Enter Number (0-2):"
 | 
			
		||||
 | 
			
		||||
		cmdmode=$( get_number )
 | 
			
		||||
		if [ $cmdmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			temperature="C"
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
		elif [ $cmdmode -eq 2 ]
 | 
			
		||||
		then
 | 
			
		||||
			temperature="F"
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ $updateconfig -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		saveconfig $temperature
 | 
			
		||||
		sudo systemctl restart argononed.service
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
							
								
								
									
										14
									
								
								source/scripts/argon-versioninfo.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								source/scripts/argon-versioninfo.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
VERSIONINFO="2505003"
 | 
			
		||||
 | 
			
		||||
echo "Version $VERSIONINFO"
 | 
			
		||||
if [ -z "$1" ]
 | 
			
		||||
then
 | 
			
		||||
	echo
 | 
			
		||||
	echo "We acknowledge the valuable feedback of the following:"
 | 
			
		||||
	echo "ghalfacree, NHHiker"
 | 
			
		||||
	echo
 | 
			
		||||
	echo "Feel free to join the discussions at https://forum.argon40.com"
 | 
			
		||||
	echo
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										371
									
								
								source/scripts/argondashboard.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										371
									
								
								source/scripts/argondashboard.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,371 @@
 | 
			
		||||
#!/bin/python3
 | 
			
		||||
 | 
			
		||||
import time
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import signal
 | 
			
		||||
import curses
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sys.path.append("/etc/argon/")
 | 
			
		||||
from argonsysinfo import *
 | 
			
		||||
from argonregister import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
############
 | 
			
		||||
# Constants
 | 
			
		||||
############
 | 
			
		||||
COLORPAIRID_DEFAULT=1
 | 
			
		||||
COLORPAIRID_LOGO=2
 | 
			
		||||
COLORPAIRID_DEFAULTINVERSE=3
 | 
			
		||||
COLORPAIRID_ALERT=4
 | 
			
		||||
COLORPAIRID_WARNING=5
 | 
			
		||||
COLORPAIRID_GOOD=6
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
INPUTREFRESHMS=100
 | 
			
		||||
DISPLAYREFRESHMS=5000
 | 
			
		||||
UPS_LOGFILE="/dev/shm/upslog.txt"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################
 | 
			
		||||
# Display Elements
 | 
			
		||||
###################
 | 
			
		||||
 | 
			
		||||
def displaydatetime(stdscr):
 | 
			
		||||
	try:
 | 
			
		||||
		curtimenow = time.localtime()
 | 
			
		||||
 | 
			
		||||
		stdscr.addstr(1, 1, time.strftime("%A", curtimenow), curses.color_pair(COLORPAIRID_DEFAULT))
 | 
			
		||||
		stdscr.addstr(2, 1, time.strftime("%b %d,%Y", curtimenow), curses.color_pair(COLORPAIRID_DEFAULT))
 | 
			
		||||
		stdscr.addstr(3, 1, time.strftime("%I:%M%p", curtimenow), curses.color_pair(COLORPAIRID_DEFAULT))
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
def displayipbattery(stdscr):
 | 
			
		||||
	try:
 | 
			
		||||
		displaytextright(stdscr,1, argonsysinfo_getip()+" ", COLORPAIRID_DEFAULT)
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
	try:
 | 
			
		||||
		status = ""
 | 
			
		||||
		level = ""
 | 
			
		||||
		outobj = {}
 | 
			
		||||
		# Load status
 | 
			
		||||
		fp = open(UPS_LOGFILE, "r")
 | 
			
		||||
		logdata = fp.read()
 | 
			
		||||
		alllines = logdata.split("\n")
 | 
			
		||||
		ctr = 0
 | 
			
		||||
		while ctr < len(alllines):
 | 
			
		||||
			tmpval = alllines[ctr].strip()
 | 
			
		||||
			curinfo = tmpval.split(":")
 | 
			
		||||
			if len(curinfo) > 1:
 | 
			
		||||
				tmpattrib = curinfo[0].lower().split(" ")
 | 
			
		||||
				# The rest are assumed to be value
 | 
			
		||||
				outobj[tmpattrib[0]] = tmpval[(len(curinfo[0])+1):].strip()
 | 
			
		||||
			ctr = ctr + 1
 | 
			
		||||
 | 
			
		||||
		# Map to data
 | 
			
		||||
		try:
 | 
			
		||||
			statuslist = outobj["power"].lower().split(" ")
 | 
			
		||||
			if statuslist[0] == "battery":
 | 
			
		||||
				tmp_charging = 0
 | 
			
		||||
			else:
 | 
			
		||||
				tmp_charging = 1
 | 
			
		||||
			tmp_battery = int(statuslist[1].replace("%",""))
 | 
			
		||||
 | 
			
		||||
			colorpairidx = COLORPAIRID_DEFAULT
 | 
			
		||||
			if tmp_charging:
 | 
			
		||||
				if tmp_battery > 99:
 | 
			
		||||
					status="Plugged"
 | 
			
		||||
					level=""
 | 
			
		||||
				else:
 | 
			
		||||
					status="Charging"
 | 
			
		||||
					level=str(tmp_battery)+"%"
 | 
			
		||||
			else:
 | 
			
		||||
				status="Battery"
 | 
			
		||||
				level=str(tmp_battery)+"%"
 | 
			
		||||
				if tmp_battery <= 20:
 | 
			
		||||
					colorpairidx = COLORPAIRID_ALERT
 | 
			
		||||
				elif tmp_battery <= 50:
 | 
			
		||||
					colorpairidx = COLORPAIRID_WARNING
 | 
			
		||||
				else:
 | 
			
		||||
					colorpairidx = COLORPAIRID_GOOD
 | 
			
		||||
 | 
			
		||||
			displaytextright(stdscr,2, status+" ", colorpairidx)
 | 
			
		||||
			displaytextright(stdscr,3, level+" ", colorpairidx)
 | 
			
		||||
		except:
 | 
			
		||||
			pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def displayramcpu(stdscr, refcpu, rowstart, colstart):
 | 
			
		||||
	curusage_b = argonsysinfo_getcpuusagesnapshot()
 | 
			
		||||
	try:
 | 
			
		||||
		outputlist = []
 | 
			
		||||
		tmpraminfo = argonsysinfo_getram()
 | 
			
		||||
		outputlist.append({"title": "ram ", "value": tmpraminfo[1]+" "+tmpraminfo[0]+" Free"})
 | 
			
		||||
 | 
			
		||||
		for cpuname in refcpu:
 | 
			
		||||
			if cpuname == "cpu":
 | 
			
		||||
				continue
 | 
			
		||||
			if refcpu[cpuname]["total"] == curusage_b[cpuname]["total"]:
 | 
			
		||||
				outputlist.append({"title": cpuname, "value": "Loading"})
 | 
			
		||||
			else:
 | 
			
		||||
				total = curusage_b[cpuname]["total"]-refcpu[cpuname]["total"]
 | 
			
		||||
				idle = curusage_b[cpuname]["idle"]-refcpu[cpuname]["idle"]
 | 
			
		||||
				outputlist.append({"title": cpuname, "value": str(int(100*(total-idle)/(total)))+"% Used"})
 | 
			
		||||
		displaytitlevaluelist(stdscr, rowstart, colstart, outputlist)
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
	return curusage_b
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def displaytempfan(stdscr, rowstart, colstart):
 | 
			
		||||
	try:
 | 
			
		||||
		outputlist = []
 | 
			
		||||
		try:
 | 
			
		||||
			if busobj is not None:
 | 
			
		||||
				fanspeed = argonregister_getfanspeed(busobj)
 | 
			
		||||
				fanspeedstr = "Off"
 | 
			
		||||
				if fanspeed > 0:
 | 
			
		||||
					fanspeedstr = str(fanspeed)+"%"
 | 
			
		||||
				outputlist.append({"title": "Fan ", "value": fanspeedstr})
 | 
			
		||||
		except:
 | 
			
		||||
			pass
 | 
			
		||||
		# Todo load from config
 | 
			
		||||
		temperature = "C"
 | 
			
		||||
		hddtempctr = 0
 | 
			
		||||
		maxcval = 0
 | 
			
		||||
		mincval = 200
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		# Get min/max of hdd temp
 | 
			
		||||
		hddtempobj = argonsysinfo_gethddtemp()
 | 
			
		||||
		for curdev in hddtempobj:
 | 
			
		||||
			if hddtempobj[curdev] < mincval:
 | 
			
		||||
				mincval = hddtempobj[curdev]
 | 
			
		||||
			if hddtempobj[curdev] > maxcval:
 | 
			
		||||
				maxcval = hddtempobj[curdev]
 | 
			
		||||
			hddtempctr = hddtempctr + 1
 | 
			
		||||
 | 
			
		||||
		cpucval = argonsysinfo_getcputemp()
 | 
			
		||||
		if hddtempctr > 0:
 | 
			
		||||
			alltempobj = {"cpu": cpucval,"hdd min": mincval, "hdd max": maxcval}
 | 
			
		||||
			# Update max C val to CPU Temp if necessary
 | 
			
		||||
			if maxcval < cpucval:
 | 
			
		||||
				maxcval = cpucval
 | 
			
		||||
 | 
			
		||||
			displayrowht = 8
 | 
			
		||||
			displayrow = 8
 | 
			
		||||
			for curdev in alltempobj:
 | 
			
		||||
				if temperature == "C":
 | 
			
		||||
					# Celsius
 | 
			
		||||
					tmpstr = str(alltempobj[curdev])
 | 
			
		||||
					if len(tmpstr) > 4:
 | 
			
		||||
						tmpstr = tmpstr[0:4]
 | 
			
		||||
				else:
 | 
			
		||||
					# Fahrenheit
 | 
			
		||||
					tmpstr = str(32+9*(alltempobj[curdev])/5)
 | 
			
		||||
					if len(tmpstr) > 5:
 | 
			
		||||
						tmpstr = tmpstr[0:5]
 | 
			
		||||
				if len(curdev) <= 3:
 | 
			
		||||
					outputlist.append({"title": curdev.upper(), "value": tmpstr +temperature})
 | 
			
		||||
				else:
 | 
			
		||||
					outputlist.append({"title": curdev.upper(), "value": tmpstr +temperature})
 | 
			
		||||
		else:
 | 
			
		||||
			maxcval = cpucval
 | 
			
		||||
			if temperature == "C":
 | 
			
		||||
				# Celsius
 | 
			
		||||
				tmpstr = str(cpucval)
 | 
			
		||||
				if len(tmpstr) > 4:
 | 
			
		||||
					tmpstr = tmpstr[0:4]
 | 
			
		||||
			else:
 | 
			
		||||
				# Fahrenheit
 | 
			
		||||
				tmpstr = str(32+9*(cpucval)/5)
 | 
			
		||||
				if len(tmpstr) > 5:
 | 
			
		||||
					tmpstr = tmpstr[0:5]
 | 
			
		||||
 | 
			
		||||
			outputlist.append({"title": "Temp", "value": tmpstr +temperature})
 | 
			
		||||
		displaytitlevaluelist(stdscr, rowstart, colstart, outputlist)
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def displaystorage(stdscr, rowstart, colstart):
 | 
			
		||||
	try:
 | 
			
		||||
		outputlist = []
 | 
			
		||||
		tmpobj = argonsysinfo_listhddusage()
 | 
			
		||||
		for curdev in tmpobj:
 | 
			
		||||
			outputlist.append({"title": curdev, "value": argonsysinfo_kbstr(tmpobj[curdev]['total'])+ " "+ str(int(100*tmpobj[curdev]['used']/tmpobj[curdev]['total']))+"% Used" })
 | 
			
		||||
		displaytitlevaluelist(stdscr, rowstart, colstart, outputlist)
 | 
			
		||||
	except:
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
##################
 | 
			
		||||
# Helpers
 | 
			
		||||
##################
 | 
			
		||||
 | 
			
		||||
# Initialize I2C Bus
 | 
			
		||||
bus = argonregister_initializebusobj()
 | 
			
		||||
 | 
			
		||||
def handle_resize(signum, frame):
 | 
			
		||||
	# TODO: Not working?
 | 
			
		||||
	curses.update_lines_cols()
 | 
			
		||||
	# Ideally redraw here
 | 
			
		||||
 | 
			
		||||
def displaytitlevaluelist(stdscr, rowstart, leftoffset, curlist):
 | 
			
		||||
	rowidx = rowstart
 | 
			
		||||
	while rowidx < curses.LINES and len(curlist) > 0:
 | 
			
		||||
		curline = ""
 | 
			
		||||
		tmpitem = curlist.pop(0)
 | 
			
		||||
		curline = tmpitem["title"]+": "+str(tmpitem["value"])
 | 
			
		||||
 | 
			
		||||
		stdscr.addstr(rowidx, leftoffset, curline)
 | 
			
		||||
		rowidx = rowidx + 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def displaytextcentered(stdscr, rownum, strval, colorpairidx = COLORPAIRID_DEFAULT):
 | 
			
		||||
	leftoffset = 0
 | 
			
		||||
	numchars = len(strval)
 | 
			
		||||
	if numchars < 1:
 | 
			
		||||
		return
 | 
			
		||||
	elif (numchars > curses.COLS):
 | 
			
		||||
		leftoffset = 0
 | 
			
		||||
		strval = strval[0:curses.COLS]
 | 
			
		||||
	else:
 | 
			
		||||
		leftoffset = (curses.COLS - numchars)>>1
 | 
			
		||||
 | 
			
		||||
	stdscr.addstr(rownum, leftoffset, strval, curses.color_pair(colorpairidx))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def displaytextright(stdscr, rownum, strval, colorpairidx = COLORPAIRID_DEFAULT):
 | 
			
		||||
	leftoffset = 0
 | 
			
		||||
	numchars = len(strval)
 | 
			
		||||
	if numchars < 1:
 | 
			
		||||
		return
 | 
			
		||||
	elif (numchars > curses.COLS):
 | 
			
		||||
		leftoffset = 0
 | 
			
		||||
		strval = strval[0:curses.COLS]
 | 
			
		||||
	else:
 | 
			
		||||
		leftoffset = curses.COLS - numchars
 | 
			
		||||
 | 
			
		||||
	stdscr.addstr(rownum, leftoffset, strval, curses.color_pair(colorpairidx))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def displaylinebreak(stdscr, rownum, colorpairidx = COLORPAIRID_DEFAULTINVERSE):
 | 
			
		||||
	strval = " "
 | 
			
		||||
	while len(strval) < curses.COLS:
 | 
			
		||||
		strval = strval + " "
 | 
			
		||||
	stdscr.addstr(rownum, 0, strval, curses.color_pair(colorpairidx))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##################
 | 
			
		||||
# Main Loop
 | 
			
		||||
##################
 | 
			
		||||
 | 
			
		||||
def mainloop(stdscr):
 | 
			
		||||
	try:
 | 
			
		||||
		# Set up signal handler
 | 
			
		||||
		signal.signal(signal.SIGWINCH, handle_resize)
 | 
			
		||||
 | 
			
		||||
		maxloopctr = int(DISPLAYREFRESHMS/INPUTREFRESHMS)
 | 
			
		||||
		sleepsecs = INPUTREFRESHMS/1000
 | 
			
		||||
 | 
			
		||||
		loopctr = maxloopctr
 | 
			
		||||
		loopmode = True
 | 
			
		||||
 | 
			
		||||
		stdscr = curses.initscr()
 | 
			
		||||
 | 
			
		||||
		# Turn off echoing of keys, and enter cbreak mode,
 | 
			
		||||
		# where no buffering is performed on keyboard input
 | 
			
		||||
		curses.noecho()
 | 
			
		||||
		curses.cbreak()
 | 
			
		||||
		curses.curs_set(0)
 | 
			
		||||
		curses.start_color()
 | 
			
		||||
 | 
			
		||||
		#curses.COLOR_BLACK
 | 
			
		||||
		#curses.COLOR_BLUE
 | 
			
		||||
		#curses.COLOR_CYAN
 | 
			
		||||
		#curses.COLOR_GREEN
 | 
			
		||||
		#curses.COLOR_MAGENTA
 | 
			
		||||
		#curses.COLOR_RED
 | 
			
		||||
		#curses.COLOR_WHITE
 | 
			
		||||
		#curses.COLOR_YELLOW
 | 
			
		||||
 | 
			
		||||
		curses.init_pair(COLORPAIRID_DEFAULT, curses.COLOR_WHITE, curses.COLOR_BLACK)
 | 
			
		||||
		curses.init_pair(COLORPAIRID_LOGO, curses.COLOR_WHITE, curses.COLOR_RED)
 | 
			
		||||
		curses.init_pair(COLORPAIRID_DEFAULTINVERSE, curses.COLOR_BLACK, curses.COLOR_WHITE)
 | 
			
		||||
		curses.init_pair(COLORPAIRID_ALERT, curses.COLOR_RED, curses.COLOR_BLACK)
 | 
			
		||||
		curses.init_pair(COLORPAIRID_WARNING, curses.COLOR_YELLOW, curses.COLOR_BLACK)
 | 
			
		||||
		curses.init_pair(COLORPAIRID_GOOD, curses.COLOR_GREEN, curses.COLOR_BLACK)
 | 
			
		||||
 | 
			
		||||
		stdscr.nodelay(True)
 | 
			
		||||
 | 
			
		||||
		refcpu = argonsysinfo_getcpuusagesnapshot()
 | 
			
		||||
		while True:
 | 
			
		||||
			try:
 | 
			
		||||
				key = stdscr.getch()
 | 
			
		||||
				# if key == ord('x') or key == ord('X'):
 | 
			
		||||
				# Any key
 | 
			
		||||
				if key > 0:
 | 
			
		||||
					break
 | 
			
		||||
			except curses.error:
 | 
			
		||||
				# No key was pressed
 | 
			
		||||
				pass
 | 
			
		||||
 | 
			
		||||
			loopctr = loopctr + 1
 | 
			
		||||
			if loopctr >= maxloopctr:
 | 
			
		||||
				loopctr = 0
 | 
			
		||||
				# Screen refresh loop
 | 
			
		||||
				# Clear screen
 | 
			
		||||
				stdscr.clear()
 | 
			
		||||
 | 
			
		||||
				displaytextcentered(stdscr, 0, "                     ", COLORPAIRID_LOGO)
 | 
			
		||||
				displaytextcentered(stdscr, 1, "  Argon40 Dashboard  ", COLORPAIRID_LOGO)
 | 
			
		||||
				displaytextcentered(stdscr, 2, "                     ", COLORPAIRID_LOGO)
 | 
			
		||||
				displaytextcentered(stdscr, 3, "Press any key to close")
 | 
			
		||||
				displaylinebreak(stdscr, 5)
 | 
			
		||||
 | 
			
		||||
				# Display Elements
 | 
			
		||||
				displaydatetime(stdscr)
 | 
			
		||||
				displayipbattery(stdscr)
 | 
			
		||||
 | 
			
		||||
				# Data Columns
 | 
			
		||||
				rowstart = 7
 | 
			
		||||
				colstart = 20
 | 
			
		||||
				refcpu = displayramcpu(stdscr, refcpu, rowstart, colstart)
 | 
			
		||||
				displaystorage(stdscr, rowstart, colstart+30)
 | 
			
		||||
				displaytempfan(stdscr, rowstart, colstart+60)
 | 
			
		||||
 | 
			
		||||
				# Main refresh even
 | 
			
		||||
				stdscr.refresh()
 | 
			
		||||
 | 
			
		||||
			time.sleep(sleepsecs)
 | 
			
		||||
 | 
			
		||||
	except Exception as initerr:
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	##########
 | 
			
		||||
	# Cleanup
 | 
			
		||||
	##########
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		curses.curs_set(1)
 | 
			
		||||
		curses.echo()
 | 
			
		||||
		curses.nocbreak()
 | 
			
		||||
		curses.endwin()
 | 
			
		||||
	except Exception as closeerr:
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
curses.wrapper(mainloop)
 | 
			
		||||
							
								
								
									
										294
									
								
								source/scripts/argoneon-oledconfig.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								source/scripts/argoneon-oledconfig.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,294 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
oledconfigfile=/etc/argoneonoled.conf
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 100 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
get_pagename() {
 | 
			
		||||
	if [ "$1" == "clock" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="Current Date/Time"
 | 
			
		||||
	elif [ "$1" == "cpu" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="CPU Utilization"
 | 
			
		||||
	elif [ "$1" == "storage" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="Storage Utilization"
 | 
			
		||||
	elif [ "$1" == "raid" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="RAID Information"
 | 
			
		||||
	elif [ "$1" == "ram" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="Available RAM"
 | 
			
		||||
	elif [ "$1" == "temp" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="CPU/HDD Temperature"
 | 
			
		||||
	elif [ "$1" == "ip" ]
 | 
			
		||||
	then
 | 
			
		||||
		pagename="IP Address"
 | 
			
		||||
	else
 | 
			
		||||
		pagename="Invalid"
 | 
			
		||||
	fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configure_pagelist () {
 | 
			
		||||
	pagemasterlist="clock cpu storage raid ram temp ip"
 | 
			
		||||
	newscreenlist="$1"
 | 
			
		||||
	pageloopflag=1
 | 
			
		||||
	while [ $pageloopflag -eq 1 ]
 | 
			
		||||
	do
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo " OLED Pages "
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		i=1
 | 
			
		||||
		for curpage in $newscreenlist
 | 
			
		||||
		do
 | 
			
		||||
			get_pagename $curpage
 | 
			
		||||
			echo "  $i. Remove $pagename"
 | 
			
		||||
			i=$((i+1))
 | 
			
		||||
		done
 | 
			
		||||
		if [ $i -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo " No page configured"
 | 
			
		||||
		fi
 | 
			
		||||
		echo
 | 
			
		||||
		echo "  $i. Add Page"
 | 
			
		||||
		echo
 | 
			
		||||
		echo "  0. Done"
 | 
			
		||||
		echo -n "Enter Number (0-$i):"
 | 
			
		||||
 | 
			
		||||
		cmdmode=$( get_number )
 | 
			
		||||
		if [ $cmdmode -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			pageloopflag=0
 | 
			
		||||
		elif [[ $cmdmode -eq $i ]]
 | 
			
		||||
		then
 | 
			
		||||
 | 
			
		||||
			echo "--------------------------------"
 | 
			
		||||
			echo " Choose Page to Add"
 | 
			
		||||
			echo "--------------------------------"
 | 
			
		||||
			echo
 | 
			
		||||
			i=1
 | 
			
		||||
			for curpage in $pagemasterlist
 | 
			
		||||
			do
 | 
			
		||||
				get_pagename $curpage
 | 
			
		||||
				echo "  $i. $pagename"
 | 
			
		||||
				i=$((i+1))
 | 
			
		||||
			done
 | 
			
		||||
 | 
			
		||||
			echo
 | 
			
		||||
			echo "  0. Cancel"
 | 
			
		||||
			echo -n "Enter Number (0-$i):"
 | 
			
		||||
			pagenum=$( get_number )
 | 
			
		||||
			if [[ $pagenum -ge 1 && $pagenum -le $i ]]
 | 
			
		||||
			then
 | 
			
		||||
				i=1
 | 
			
		||||
				for curpage in $pagemasterlist
 | 
			
		||||
				do
 | 
			
		||||
					if [ $i -eq $pagenum ]
 | 
			
		||||
					then
 | 
			
		||||
						if [ "$newscreenlist" == "" ]
 | 
			
		||||
						then
 | 
			
		||||
							newscreenlist="$curpage"
 | 
			
		||||
						else
 | 
			
		||||
							newscreenlist="$newscreenlist $curpage"
 | 
			
		||||
						fi
 | 
			
		||||
					fi
 | 
			
		||||
					i=$((i+1))
 | 
			
		||||
				done
 | 
			
		||||
			fi
 | 
			
		||||
		elif [[ $cmdmode -ge 1 && $cmdmode -lt $i ]]
 | 
			
		||||
		then
 | 
			
		||||
			tmpscreenlist=""
 | 
			
		||||
			i=1
 | 
			
		||||
			for curpage in $newscreenlist
 | 
			
		||||
			do
 | 
			
		||||
				if [ ! $i -eq $cmdmode ]
 | 
			
		||||
				then
 | 
			
		||||
					tmpscreenlist="$tmpscreenlist $curpage"
 | 
			
		||||
				fi
 | 
			
		||||
				i=$((i+1))
 | 
			
		||||
			done
 | 
			
		||||
			if [ "$tmpscreenlist" == "" ]
 | 
			
		||||
			then
 | 
			
		||||
				newscreenlist="$tmpscreenlist"
 | 
			
		||||
			else
 | 
			
		||||
				# Remove leading space
 | 
			
		||||
				newscreenlist="${tmpscreenlist:1}"
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
saveconfig () {
 | 
			
		||||
	echo "#" > $oledconfigfile
 | 
			
		||||
	echo "# Argon OLED Configuration" >> $oledconfigfile
 | 
			
		||||
	echo "#" >> $oledconfigfile
 | 
			
		||||
	echo "enabled=$1" >> $oledconfigfile
 | 
			
		||||
	echo "switchduration=$2" >> $oledconfigfile
 | 
			
		||||
	echo "screensaver=$3" >> $oledconfigfile
 | 
			
		||||
	echo "screenlist=\"$4\"" >> $oledconfigfile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
updateconfig=1
 | 
			
		||||
oledloopflag=1
 | 
			
		||||
while [ $oledloopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	if [ $updateconfig -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		. $oledconfigfile
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	updateconfig=0
 | 
			
		||||
	if [ -z "$enabled" ]
 | 
			
		||||
	then
 | 
			
		||||
		enabled="Y"
 | 
			
		||||
		updateconfig=1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ -z "$screenlist" ]
 | 
			
		||||
	then
 | 
			
		||||
		screenlist="clock ip"
 | 
			
		||||
		updateconfig=1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ -z "$screensaver" ]
 | 
			
		||||
	then
 | 
			
		||||
		screensaver=120
 | 
			
		||||
		updateconfig=1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ -z "$switchduration" ]
 | 
			
		||||
	then
 | 
			
		||||
		switchduration=0
 | 
			
		||||
		updateconfig=1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	# Write default values to config file, daemon already uses default so no need to restart service
 | 
			
		||||
	if [ $updateconfig -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		saveconfig $enabled $switchduration $screensaver "$screenlist"
 | 
			
		||||
		updateconfig=0
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	displaystring=": Manually"
 | 
			
		||||
	if [ $switchduration -gt 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		displaystring="Every $switchduration secs"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	echo "-----------------------------"
 | 
			
		||||
	echo "Argon OLED Configuration Tool"
 | 
			
		||||
	echo "-----------------------------"
 | 
			
		||||
	echo "Choose from the list:"
 | 
			
		||||
	echo "  1. Switch Page $displaystring"
 | 
			
		||||
	echo "  2. Configure Pages"
 | 
			
		||||
	echo "  3. Turn OFF OLED Screen when unchanged after $screensaver secs"
 | 
			
		||||
	echo "  4. Enable OLED Pages: $enabled"
 | 
			
		||||
	echo
 | 
			
		||||
	echo "  0. Back"
 | 
			
		||||
	echo -n "Enter Number (0-3):"
 | 
			
		||||
 | 
			
		||||
	newmode=$( get_number )
 | 
			
		||||
	if [ $newmode -eq 0 ]
 | 
			
		||||
	then
 | 
			
		||||
		oledloopflag=0
 | 
			
		||||
	elif [ $newmode -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo
 | 
			
		||||
		echo -n "Enter # of Seconds (10-60, Manual if 0):"
 | 
			
		||||
 | 
			
		||||
		cmdmode=$( get_number )
 | 
			
		||||
		if [ $cmdmode -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			switchduration=0
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
		elif [[ $cmdmode -ge 10 && $cmdmode -le 60 ]]
 | 
			
		||||
		then
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
			switchduration=$cmdmode
 | 
			
		||||
		else
 | 
			
		||||
			echo
 | 
			
		||||
			echo "Invalid duration"
 | 
			
		||||
			echo
 | 
			
		||||
		fi
 | 
			
		||||
	elif [ $newmode -eq 3 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo
 | 
			
		||||
		echo -n "Enter # of Seconds (60 or above, Manual if 0):"
 | 
			
		||||
 | 
			
		||||
		cmdmode=$( get_number )
 | 
			
		||||
		if [ $cmdmode -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			screensaver=0
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
		elif [ $cmdmode -ge 60 ]
 | 
			
		||||
		then
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
			screensaver=$cmdmode
 | 
			
		||||
		else
 | 
			
		||||
			echo
 | 
			
		||||
			echo "Invalid duration"
 | 
			
		||||
			echo
 | 
			
		||||
		fi
 | 
			
		||||
	elif [ $newmode -eq 2 ]
 | 
			
		||||
	then
 | 
			
		||||
		configure_pagelist "$screenlist"
 | 
			
		||||
		if [ ! "$screenlist" == "$newscreenlist" ]
 | 
			
		||||
		then
 | 
			
		||||
			screenlist="$newscreenlist"
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
		fi
 | 
			
		||||
	elif [ $newmode -eq 4 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo
 | 
			
		||||
		echo -n "Enable OLED Pages (Y/n)?:"
 | 
			
		||||
		read -n 1 confirm
 | 
			
		||||
		tmpenabled="$enabled"
 | 
			
		||||
		if [[ "$confirm" == "n" || "$confirm" == "N" ]]
 | 
			
		||||
		then
 | 
			
		||||
			tmpenabled="N"
 | 
			
		||||
		elif [[ "$confirm" == "y" || "$confirm" == "Y" ]]
 | 
			
		||||
		then
 | 
			
		||||
			tmpenabled="Y"
 | 
			
		||||
		else
 | 
			
		||||
			echo "Invalid response"
 | 
			
		||||
		fi
 | 
			
		||||
		if [ ! "$enabled" == "$tmpenabled" ]
 | 
			
		||||
		then
 | 
			
		||||
			enabled="$tmpenabled"
 | 
			
		||||
			updateconfig=1
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ $updateconfig -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		saveconfig $enabled $switchduration $screensaver "$screenlist"
 | 
			
		||||
		sudo systemctl restart argononed.service
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
							
								
								
									
										421
									
								
								source/scripts/argoneon-rtcconfig.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								source/scripts/argoneon-rtcconfig.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,421 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
if [ -z "$1" ]
 | 
			
		||||
then
 | 
			
		||||
	rtcdaemonname=argoneond
 | 
			
		||||
	rtcconfigfile=/etc/argoneonrtc.conf
 | 
			
		||||
else
 | 
			
		||||
	rtcdaemonname=${1}d
 | 
			
		||||
	rtcconfigfile=/etc/${1}.conf
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pythonbin=/usr/bin/python3
 | 
			
		||||
argonrtcscript=/etc/argon/$rtcdaemonname.py
 | 
			
		||||
 | 
			
		||||
CHECKPLATFORM="Others"
 | 
			
		||||
# Check if Raspbian
 | 
			
		||||
grep -q -F 'Raspbian' /etc/os-release &> /dev/null
 | 
			
		||||
if [ $? -eq 0 ]
 | 
			
		||||
then
 | 
			
		||||
	CHECKPLATFORM="Raspbian"
 | 
			
		||||
else
 | 
			
		||||
	# Ubuntu needs elevated access for SMBus
 | 
			
		||||
	pythonbin="sudo /usr/bin/python3"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 100 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configure_schedule () {
 | 
			
		||||
	scheduleloopflag=1
 | 
			
		||||
	while [ $scheduleloopflag -eq 1 ]
 | 
			
		||||
	do
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo " Configure Schedule "
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo "  1. Add Schedule"
 | 
			
		||||
		echo "  or"
 | 
			
		||||
		echo "  Remove Schedule"
 | 
			
		||||
		$pythonbin $argonrtcscript GETSCHEDULELIST
 | 
			
		||||
		echo
 | 
			
		||||
		echo " 99. Main Menu"
 | 
			
		||||
		echo "  0. Back"
 | 
			
		||||
		#echo "NOTE: You can also edit $rtcconfigfile directly"
 | 
			
		||||
		echo -n "Enter Number:"
 | 
			
		||||
 | 
			
		||||
		newmode=$( get_number )
 | 
			
		||||
		if [ $newmode -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			scheduleloopflag=0
 | 
			
		||||
		elif [ $newmode -eq 99 ]
 | 
			
		||||
		then
 | 
			
		||||
			scheduleloopflag=0
 | 
			
		||||
			rtcloopflag=2
 | 
			
		||||
		elif [ $newmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			configure_newschedule
 | 
			
		||||
		elif [ $newmode -gt 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "CONFIRM SCHEDULE REMOVAL"
 | 
			
		||||
			$pythonbin $argonrtcscript SHOWSCHEDULE $newmode
 | 
			
		||||
			echo -n "Press Y to remove schedule #$newmode:"
 | 
			
		||||
			read -n 1 confirm
 | 
			
		||||
			if [ "$confirm" = "y" ]
 | 
			
		||||
			then
 | 
			
		||||
				confirm="Y"
 | 
			
		||||
			fi
 | 
			
		||||
			if [ "$confirm" = "Y" ]
 | 
			
		||||
			then
 | 
			
		||||
				$pythonbin $argonrtcscript REMOVESCHEDULE $newmode
 | 
			
		||||
				sudo systemctl restart $rtcdaemonname.service
 | 
			
		||||
			fi
 | 
			
		||||
			echo ""
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configure_newschedule () {
 | 
			
		||||
 | 
			
		||||
	cmdmode=1
 | 
			
		||||
	hour=8
 | 
			
		||||
	minute=0
 | 
			
		||||
	minuteprefix=":0"
 | 
			
		||||
	dayidx=0
 | 
			
		||||
	repeat=1
 | 
			
		||||
 | 
			
		||||
	subloopflag=1
 | 
			
		||||
	while [ $subloopflag -eq 1 ]
 | 
			
		||||
	do
 | 
			
		||||
		minuteprefix=":0"
 | 
			
		||||
		if [ $minute -ge 10 ]
 | 
			
		||||
		then
 | 
			
		||||
			minuteprefix=":"
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		typestr="Shutdown"
 | 
			
		||||
		if [ $cmdmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			typestr="Startup"
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		daystr="Daily"
 | 
			
		||||
		if [ $dayidx -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Mon"
 | 
			
		||||
		elif [ $dayidx -eq 2 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Tue"
 | 
			
		||||
		elif [ $dayidx -eq 3 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Wed"
 | 
			
		||||
		elif [ $dayidx -eq 4 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Thu"
 | 
			
		||||
		elif [ $dayidx -eq 5 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Fri"
 | 
			
		||||
		elif [ $dayidx -eq 6 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Sat"
 | 
			
		||||
		elif [ $dayidx -eq 7 ]
 | 
			
		||||
		then
 | 
			
		||||
			daystr="Sun"
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		repeatstr="Yes"
 | 
			
		||||
		if [ $repeat -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			repeatstr="Once"
 | 
			
		||||
			if [ $dayidx -eq 0 ]
 | 
			
		||||
			then
 | 
			
		||||
				daystr="Next Occurence"
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo " Configure Schedule"
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo "  1. Type: $typestr"
 | 
			
		||||
		echo "  2. Set Time: $hour$minuteprefix$minute"
 | 
			
		||||
		echo "  3. Repeating: $repeatstr"
 | 
			
		||||
		echo "  4. Day: $daystr"
 | 
			
		||||
		echo
 | 
			
		||||
		echo "  5. Add Schedule"
 | 
			
		||||
		echo
 | 
			
		||||
		echo "  0. Cancel"
 | 
			
		||||
		echo -n "Enter Number (0-5):"
 | 
			
		||||
 | 
			
		||||
		setmode=$( get_number )
 | 
			
		||||
		if [ $setmode -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			subloopflag=0
 | 
			
		||||
		elif [ $setmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "--------------------------------"
 | 
			
		||||
			echo " Schedule Type "
 | 
			
		||||
			echo "--------------------------------"
 | 
			
		||||
			echo "  1. Startup"
 | 
			
		||||
			echo "  2. Shutdown"
 | 
			
		||||
			echo
 | 
			
		||||
			echo -n "Enter Number (1-2):"
 | 
			
		||||
 | 
			
		||||
			tmpval=$( get_number )
 | 
			
		||||
			if [ $tmpval -eq 1 ]
 | 
			
		||||
			then
 | 
			
		||||
				cmdmode=1
 | 
			
		||||
			elif [ $tmpval -eq 2 ]
 | 
			
		||||
			then
 | 
			
		||||
				cmdmode=0
 | 
			
		||||
			else
 | 
			
		||||
				echo "Invalid Option"
 | 
			
		||||
			fi
 | 
			
		||||
		elif [ $setmode -eq 2 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo -n "Enter Hour (0-23):"
 | 
			
		||||
			tmphour=$( get_number )
 | 
			
		||||
			echo -n "Enter Minute (0-59):"
 | 
			
		||||
			tmpminute=$( get_number )
 | 
			
		||||
			if [[ $tmpminute -ge 0 && $tmpminute -le 59 && $tmphour -ge 0 && $tmphour -le 23 ]]
 | 
			
		||||
			then
 | 
			
		||||
				minute=$tmpminute
 | 
			
		||||
				hour=$tmphour
 | 
			
		||||
			else
 | 
			
		||||
				echo "Invalid value(s)"
 | 
			
		||||
			fi
 | 
			
		||||
		elif [ $setmode -eq 3 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo -n "Repeat schedule (Y/n)?:"
 | 
			
		||||
			read -n 1 confirm
 | 
			
		||||
			if [ "$confirm" = "y" ]
 | 
			
		||||
			then
 | 
			
		||||
				repeat=1
 | 
			
		||||
			else
 | 
			
		||||
				repeat=0
 | 
			
		||||
			fi
 | 
			
		||||
		elif [ $setmode -eq 4 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "Select Day of the Week:"
 | 
			
		||||
			echo "  0. Daily"
 | 
			
		||||
			echo "  1. Monday"
 | 
			
		||||
			echo "  2. Tuesday"
 | 
			
		||||
			echo "  3. Wednesday"
 | 
			
		||||
			echo "  4. Thursday"
 | 
			
		||||
			echo "  5. Friday"
 | 
			
		||||
			echo "  6. Saturday"
 | 
			
		||||
			echo "  7. Sunday"
 | 
			
		||||
 | 
			
		||||
			echo -n "Enter Number (0-7):"
 | 
			
		||||
			tmpval=$( get_number )
 | 
			
		||||
			if [[ $tmpval -ge 0 && $tmpval -le 7 ]]
 | 
			
		||||
			then
 | 
			
		||||
				dayidx=$tmpval
 | 
			
		||||
			else
 | 
			
		||||
				echo "Invalid Option"
 | 
			
		||||
			fi
 | 
			
		||||
		elif [ $setmode -eq 5 ]
 | 
			
		||||
		then
 | 
			
		||||
			if [ $dayidx -eq 0 ]
 | 
			
		||||
			then
 | 
			
		||||
				cronweekday="*"
 | 
			
		||||
			elif [ $dayidx -eq 7 ]
 | 
			
		||||
			then
 | 
			
		||||
				cronweekday="7"
 | 
			
		||||
			else
 | 
			
		||||
				cronweekday=$dayidx
 | 
			
		||||
			fi
 | 
			
		||||
			cmdcode="off"
 | 
			
		||||
			if [ $cmdmode -eq 1 ]
 | 
			
		||||
			then
 | 
			
		||||
				cmdcode="on"
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			echo "$minute $hour * * $cronweekday $cmdcode" >> $rtcconfigfile
 | 
			
		||||
			sudo systemctl restart $rtcdaemonname.service
 | 
			
		||||
			subloopflag=0
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
configure_newcron () {
 | 
			
		||||
	subloopflag=1
 | 
			
		||||
	while [ $subloopflag -eq 1 ]
 | 
			
		||||
	do
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo " Schedule Type "
 | 
			
		||||
		echo "--------------------------------"
 | 
			
		||||
		echo "  1. Startup"
 | 
			
		||||
		echo "  2. Shutdown"
 | 
			
		||||
		echo
 | 
			
		||||
		echo "  0. Cancel"
 | 
			
		||||
		echo -n "Enter Number (0-2):"
 | 
			
		||||
 | 
			
		||||
		cmdmode=$( get_number )
 | 
			
		||||
		if [ $cmdmode -eq 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			subloopflag=0
 | 
			
		||||
		elif [[ $cmdmode -ge 1 && $cmdmode -le 2 ]]
 | 
			
		||||
		then
 | 
			
		||||
			cmdcode="on"
 | 
			
		||||
			echo "--------------------------------"
 | 
			
		||||
			if [ $cmdmode -eq 1 ]
 | 
			
		||||
			then
 | 
			
		||||
				echo " Schedule Startup"
 | 
			
		||||
			else
 | 
			
		||||
				echo " Schedule Shutdown"
 | 
			
		||||
				cmdcode="off"
 | 
			
		||||
			fi
 | 
			
		||||
			echo "--------------------------------"
 | 
			
		||||
			echo "Select Schedule:"
 | 
			
		||||
			echo "  1. Hourly"
 | 
			
		||||
			echo "  2. Daily"
 | 
			
		||||
			echo "  3. Weekly"
 | 
			
		||||
			echo "  4. Monthly"
 | 
			
		||||
			echo
 | 
			
		||||
			echo "  0. Back"
 | 
			
		||||
			echo -n "Enter Number (0-4):"
 | 
			
		||||
 | 
			
		||||
			newmode=$( get_number )
 | 
			
		||||
			if [[ $newmode -ge 1 && $newmode -le 4 ]]
 | 
			
		||||
			then
 | 
			
		||||
				echo ""
 | 
			
		||||
				if [ $cmdmode -eq 1 ]
 | 
			
		||||
				then
 | 
			
		||||
					echo "New Startup Schedule"
 | 
			
		||||
				else
 | 
			
		||||
					echo "New Shutdown Schedule"
 | 
			
		||||
				fi
 | 
			
		||||
 | 
			
		||||
				if [ $newmode -eq 1 ]
 | 
			
		||||
				then
 | 
			
		||||
					echo -n "Enter Minute (0-59):"
 | 
			
		||||
					minute=$( get_number )
 | 
			
		||||
					if [[ $minute -ge 0 && $minute -le 59 ]]
 | 
			
		||||
					then
 | 
			
		||||
						echo "$minute * * * * $cmdcode" >> $rtcconfigfile
 | 
			
		||||
						sudo systemctl restart $rtcdaemonname.service
 | 
			
		||||
						subloopflag=0
 | 
			
		||||
					else
 | 
			
		||||
						echo "Invalid value"
 | 
			
		||||
					fi
 | 
			
		||||
				elif [ $newmode -eq 2 ]
 | 
			
		||||
				then
 | 
			
		||||
					echo -n "Enter Hour (0-23):"
 | 
			
		||||
					hour=$( get_number )
 | 
			
		||||
					echo -n "Enter Minute (0-59):"
 | 
			
		||||
					minute=$( get_number )
 | 
			
		||||
					if [[ $minute -ge 0 && $minute -le 59 && $hour -ge 0 && $hour -le 23 ]]
 | 
			
		||||
					then
 | 
			
		||||
						echo "$minute $hour * * * $cmdcode" >> $rtcconfigfile
 | 
			
		||||
						sudo systemctl restart $rtcdaemonname.service
 | 
			
		||||
						subloopflag=0
 | 
			
		||||
					else
 | 
			
		||||
						echo "Invalid value(s)"
 | 
			
		||||
					fi
 | 
			
		||||
				elif [ $newmode -eq 3 ]
 | 
			
		||||
				then
 | 
			
		||||
					echo "Select Day of the Week:"
 | 
			
		||||
					echo "  0. Sunday"
 | 
			
		||||
					echo "  1. Monday"
 | 
			
		||||
					echo "  2. Tuesday"
 | 
			
		||||
					echo "  3. Wednesday"
 | 
			
		||||
					echo "  4. Thursday"
 | 
			
		||||
					echo "  5. Friday"
 | 
			
		||||
					echo "  6. Saturday"
 | 
			
		||||
 | 
			
		||||
					echo -n "Enter Number (0-6):"
 | 
			
		||||
					weekday=$( get_number )
 | 
			
		||||
					echo -n "Enter Hour (0-23):"
 | 
			
		||||
					hour=$( get_number )
 | 
			
		||||
					echo -n "Enter Minute (0-59):"
 | 
			
		||||
					minute=$( get_number )
 | 
			
		||||
 | 
			
		||||
					if [[ $minute -ge 0 && $minute -le 59 && $hour -ge 0 && $hour -le 23 && $weekday -ge 0 && $weekday -le 6 ]]
 | 
			
		||||
					then
 | 
			
		||||
						echo "$minute $hour * * $weekday $cmdcode" >> $rtcconfigfile
 | 
			
		||||
						sudo systemctl restart $rtcdaemonname.service
 | 
			
		||||
						subloopflag=0
 | 
			
		||||
					else
 | 
			
		||||
						echo "Invalid value(s)"
 | 
			
		||||
					fi
 | 
			
		||||
				elif [ $newmode -eq 4 ]
 | 
			
		||||
				then
 | 
			
		||||
					echo -n "Enter Date (1-31):"
 | 
			
		||||
					monthday=$( get_number )
 | 
			
		||||
					if [[ $monthday -ge 29 ]]
 | 
			
		||||
					then
 | 
			
		||||
						echo "WARNING: This schedule will not trigger for certain months"
 | 
			
		||||
					fi
 | 
			
		||||
					echo -n "Enter Hour (0-23):"
 | 
			
		||||
					hour=$( get_number )
 | 
			
		||||
					echo -n "Enter Minute (0-59):"
 | 
			
		||||
					minute=$( get_number )
 | 
			
		||||
 | 
			
		||||
					if [[ $minute -ge 0 && $minute -le 59 && $hour -ge 0 && $hour -le 23 && $monthday -ge 1 && $monthday -le 31 ]]
 | 
			
		||||
					then
 | 
			
		||||
						echo "$minute $hour $monthday * * $cmdcode" >> $rtcconfigfile
 | 
			
		||||
						sudo systemctl restart $rtcdaemonname.service
 | 
			
		||||
						subloopflag=0
 | 
			
		||||
					else
 | 
			
		||||
						echo "Invalid value(s)"
 | 
			
		||||
					fi
 | 
			
		||||
				fi
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
	done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rtcloopflag=1
 | 
			
		||||
while [ $rtcloopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	echo "----------------------------"
 | 
			
		||||
	echo "Argon RTC Configuration Tool"
 | 
			
		||||
	echo "----------------------------"
 | 
			
		||||
	$pythonbin $argonrtcscript GETRTCTIME
 | 
			
		||||
	echo "Choose from the list:"
 | 
			
		||||
	echo "  1. Update RTC Time"
 | 
			
		||||
	echo "  2. Configure Startup/Shutdown Schedules"
 | 
			
		||||
	echo
 | 
			
		||||
	echo "  0. Exit"
 | 
			
		||||
	echo -n "Enter Number (0-2):"
 | 
			
		||||
 | 
			
		||||
	newmode=$( get_number )
 | 
			
		||||
	if [ $newmode -eq 0 ]
 | 
			
		||||
	then
 | 
			
		||||
		rtcloopflag=0
 | 
			
		||||
	elif [[ $newmode -ge 1 && $newmode -le 2 ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $newmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "Matching RTC Time to System Time..."
 | 
			
		||||
			$pythonbin $argonrtcscript UPDATERTCTIME
 | 
			
		||||
		elif [ $newmode -eq 2 ]
 | 
			
		||||
		then
 | 
			
		||||
			configure_schedule
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
							
								
								
									
										487
									
								
								source/scripts/argoneond.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										487
									
								
								source/scripts/argoneond.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,487 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import datetime
 | 
			
		||||
import math
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
sys.path.append("/etc/argon/")
 | 
			
		||||
from argonregister import argonregister_initializebusobj
 | 
			
		||||
import argonrtc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Initialize I2C Bus
 | 
			
		||||
bus = argonregister_initializebusobj()
 | 
			
		||||
 | 
			
		||||
ADDR_RTC=0x51
 | 
			
		||||
 | 
			
		||||
#################
 | 
			
		||||
# Common/Helpers
 | 
			
		||||
#################
 | 
			
		||||
 | 
			
		||||
RTC_CONFIGFILE = "/etc/argoneonrtc.conf"
 | 
			
		||||
 | 
			
		||||
RTC_ALARM_BIT = 0x8
 | 
			
		||||
RTC_TIMER_BIT = 0x4
 | 
			
		||||
 | 
			
		||||
# PCF8563 number system Binary Coded Decimal (BCD)
 | 
			
		||||
 | 
			
		||||
# BCD to Decimal
 | 
			
		||||
def numBCDtoDEC(val):
 | 
			
		||||
	return (val & 0xf)+(((val >> 4) & 0xf)*10)
 | 
			
		||||
 | 
			
		||||
# Decimal to BCD
 | 
			
		||||
def numDECtoBCD(val):
 | 
			
		||||
	return (math.floor(val/10)<<4) + (val % 10)
 | 
			
		||||
 | 
			
		||||
# Check if Event Bit is raised
 | 
			
		||||
def hasRTCEventFlag(flagbit):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return False
 | 
			
		||||
	bus.write_byte(ADDR_RTC,1)
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 1)
 | 
			
		||||
	return (out & flagbit) != 0
 | 
			
		||||
 | 
			
		||||
# Clear Event Bit if raised
 | 
			
		||||
def clearRTCEventFlag(flagbit):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return False
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 1)
 | 
			
		||||
	if (out & flagbit) != 0:
 | 
			
		||||
		# Unset only if fired
 | 
			
		||||
		bus.write_byte_data(ADDR_RTC, 1, out&(0xff-flagbit))
 | 
			
		||||
		return True
 | 
			
		||||
	return False
 | 
			
		||||
 | 
			
		||||
# Enable Event Flag
 | 
			
		||||
def setRTCEventFlag(flagbit, enabled):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	# 0x10 = TI_TP flag, 0 by default
 | 
			
		||||
	ti_tp_flag = 0x10
 | 
			
		||||
	# flagbit=0x4 for timer flag, 0x1 for enable timer flag
 | 
			
		||||
	# flagbit=0x8 for alarm flag, 0x2 for enable alarm flag
 | 
			
		||||
	enableflagbit = flagbit>>2
 | 
			
		||||
	disableflagbit = 0
 | 
			
		||||
	if enabled == False:
 | 
			
		||||
		disableflagbit = enableflagbit
 | 
			
		||||
		enableflagbit = 0
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 1)
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, 1, (out&(0xff-flagbit-disableflagbit - ti_tp_flag))|enableflagbit)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Describe Methods
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Describe Timer Setting
 | 
			
		||||
def describeTimer(showsetting):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return "Error"
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 14)
 | 
			
		||||
	tmp = out & 3
 | 
			
		||||
	if tmp == 3:
 | 
			
		||||
		outstr = " Minute(s)"
 | 
			
		||||
	elif tmp == 2:
 | 
			
		||||
		outstr = " Second(s)"
 | 
			
		||||
	elif tmp == 1:
 | 
			
		||||
		outstr = "/64th Second"
 | 
			
		||||
	elif tmp == 0:
 | 
			
		||||
		outstr = "/4096th Second"
 | 
			
		||||
 | 
			
		||||
	if (out & 0x80) != 0:
 | 
			
		||||
		out = bus.read_byte_data(ADDR_RTC, 15)
 | 
			
		||||
		return "Every "+(numBCDtoDEC(out)+1)+outstr
 | 
			
		||||
	elif showsetting == True:
 | 
			
		||||
		return "Disabled (Interval every 1"+outstr+")"
 | 
			
		||||
	# Setting might matter to save resources
 | 
			
		||||
	return "None"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Describe Alarm Setting
 | 
			
		||||
def describeAlarm():
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return "Error"
 | 
			
		||||
 | 
			
		||||
	minute = -1
 | 
			
		||||
	hour = -1
 | 
			
		||||
	caldate = -1
 | 
			
		||||
	weekday = -1
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 9)
 | 
			
		||||
	if (out & 0x80) == 0:
 | 
			
		||||
		minute = numBCDtoDEC(out & 0x7f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 10)
 | 
			
		||||
	if (out & 0x80) == 0:
 | 
			
		||||
		hour = numBCDtoDEC(out & 0x3f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 11)
 | 
			
		||||
	if (out & 0x80) == 0:
 | 
			
		||||
		caldate = numBCDtoDEC(out & 0x3f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 12)
 | 
			
		||||
	if (out & 0x80) == 0:
 | 
			
		||||
		weekday = numBCDtoDEC(out & 0x7)
 | 
			
		||||
 | 
			
		||||
	if weekday < 0 and caldate < 0 and hour < 0 and minute < 0:
 | 
			
		||||
		return "None"
 | 
			
		||||
 | 
			
		||||
	# Convert from UTC
 | 
			
		||||
	utcschedule = argonrtc.describeSchedule([-1], [weekday], [caldate], [hour], [minute])
 | 
			
		||||
	weekday, caldate, hour, minute = argonrtc.convertAlarmTimezone(weekday, caldate, hour, minute, False)
 | 
			
		||||
 | 
			
		||||
	return argonrtc.describeSchedule([-1], [weekday], [caldate], [hour], [minute]) + " Local (RTC Schedule: "+utcschedule+" UTC)"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Describe Control Flags
 | 
			
		||||
def describeControlRegisters():
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		print("Error")
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte_data(ADDR_RTC, 1)
 | 
			
		||||
 | 
			
		||||
	print("\n***************")
 | 
			
		||||
	print("Control Status 2")
 | 
			
		||||
	print("\tTI_TP Flag:", ((out & 0x10) != 0))
 | 
			
		||||
	print("\tAlarm Flag:", ((out & RTC_ALARM_BIT) != 0),"( Enabled =", (out & (RTC_ALARM_BIT>>2)) != 0, ")")
 | 
			
		||||
	print("\tTimer Flag:", ((out & RTC_TIMER_BIT) != 0),"( Enabled =", (out & (RTC_TIMER_BIT>>2)) != 0, ")")
 | 
			
		||||
 | 
			
		||||
	print("Alarm Setting:")
 | 
			
		||||
	print("\t"+describeAlarm())
 | 
			
		||||
 | 
			
		||||
	print("Timer Setting:")
 | 
			
		||||
	print("\t"+describeTimer(True))
 | 
			
		||||
 | 
			
		||||
	print("***************\n")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Alarm
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Check if RTC Alarm Flag is ON
 | 
			
		||||
def hasRTCAlarmFlag():
 | 
			
		||||
	return hasRTCEventFlag(RTC_ALARM_BIT)
 | 
			
		||||
 | 
			
		||||
# Clear RTC Alarm Flag
 | 
			
		||||
def clearRTCAlarmFlag():
 | 
			
		||||
	return clearRTCEventFlag(RTC_ALARM_BIT)
 | 
			
		||||
 | 
			
		||||
# Enables RTC Alarm Register
 | 
			
		||||
def enableAlarm(registeraddr, value, mask):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	# 0x00 is Enabled
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, registeraddr, (numDECtoBCD(value)&mask))
 | 
			
		||||
 | 
			
		||||
# Disables RTC Alarm Register
 | 
			
		||||
def disableAlarm(registeraddr):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	# 0x80 is disabled
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, registeraddr, 0x80)
 | 
			
		||||
 | 
			
		||||
# Removes all alarm settings
 | 
			
		||||
def removeRTCAlarm():
 | 
			
		||||
	setRTCEventFlag(RTC_ALARM_BIT, False)
 | 
			
		||||
 | 
			
		||||
	disableAlarm(9)
 | 
			
		||||
	disableAlarm(10)
 | 
			
		||||
	disableAlarm(11)
 | 
			
		||||
	disableAlarm(12)
 | 
			
		||||
 | 
			
		||||
# Set RTC Alarm (Negative values ignored)
 | 
			
		||||
def setRTCAlarm(enableflag, weekday, caldate, hour, minute):
 | 
			
		||||
 | 
			
		||||
	weekday, caldate, hour, minute = argonrtc.getRTCAlarm(weekday, caldate, hour, minute)
 | 
			
		||||
	if caldate < 1 and weekday < 0 and hour < 0 and minute < 0:
 | 
			
		||||
		return -1
 | 
			
		||||
 | 
			
		||||
	clearRTCAlarmFlag()
 | 
			
		||||
	setRTCEventFlag(RTC_ALARM_BIT, enableflag)
 | 
			
		||||
 | 
			
		||||
	if minute >= 0:
 | 
			
		||||
		enableAlarm(9, minute, 0x7f)
 | 
			
		||||
	else:
 | 
			
		||||
		disableAlarm(9)
 | 
			
		||||
 | 
			
		||||
	if hour >= 0:
 | 
			
		||||
		enableAlarm(10, hour, 0x7f)
 | 
			
		||||
	else:
 | 
			
		||||
		disableAlarm(10)
 | 
			
		||||
 | 
			
		||||
	if caldate >= 0:
 | 
			
		||||
		enableAlarm(11, caldate, 0x7f)
 | 
			
		||||
	else:
 | 
			
		||||
		disableAlarm(11)
 | 
			
		||||
 | 
			
		||||
	if weekday >= 0:
 | 
			
		||||
		# 0 - Sun (datetime 0 - Mon)
 | 
			
		||||
		if weekday > 5:
 | 
			
		||||
			weekday = 0
 | 
			
		||||
		else:
 | 
			
		||||
			weekday = weekday + 1
 | 
			
		||||
		enableAlarm(12, weekday, 0x7f)
 | 
			
		||||
	else:
 | 
			
		||||
		disableAlarm(12)
 | 
			
		||||
 | 
			
		||||
	return 0
 | 
			
		||||
 | 
			
		||||
# Set RTC Hourly Alarm
 | 
			
		||||
def setRTCAlarmHourly(enableflag, minute):
 | 
			
		||||
	return setRTCAlarm(enableflag, -1, -1, -1, minute)
 | 
			
		||||
 | 
			
		||||
# Set RTC Daily Alarm
 | 
			
		||||
def setRTCAlarmDaily(enableflag, hour, minute):
 | 
			
		||||
	return setRTCAlarm(enableflag, -1, -1, hour, minute)
 | 
			
		||||
 | 
			
		||||
# Set RTC Weekly Alarm
 | 
			
		||||
def setRTCAlarmWeekly(enableflag, dayofweek, hour, minute):
 | 
			
		||||
	return setRTCAlarm(enableflag, dayofweek, -1, hour, minute)
 | 
			
		||||
 | 
			
		||||
# Set RTC Monthly Alarm
 | 
			
		||||
def setRTCAlarmMonthly(enableflag, caldate, hour, minute):
 | 
			
		||||
	return setRTCAlarm(enableflag, -1, caldate, hour, minute)
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Timer
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Check if RTC Timer Flag is ON
 | 
			
		||||
def hasRTCTimerFlag():
 | 
			
		||||
	return hasRTCEventFlag(RTC_TIMER_BIT)
 | 
			
		||||
 | 
			
		||||
# Clear RTC Timer Flag
 | 
			
		||||
def clearRTCTimerFlag():
 | 
			
		||||
	return clearRTCEventFlag(RTC_TIMER_BIT)
 | 
			
		||||
 | 
			
		||||
# Remove RTC Timer Setting
 | 
			
		||||
def removeRTCTimer():
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	setRTCEventFlag(RTC_TIMER_BIT, False)
 | 
			
		||||
 | 
			
		||||
	# Timer disable and Set Timer frequency to lowest (0x3=1 per minute)
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, 14, 3)
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, 15, 0)
 | 
			
		||||
 | 
			
		||||
# Set RTC Timer Interval
 | 
			
		||||
def setRTCTimerInterval(enableflag, value, inSeconds = False):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return -1
 | 
			
		||||
 | 
			
		||||
	if value > 255 or value < 1:
 | 
			
		||||
		return -1
 | 
			
		||||
	clearRTCTimerFlag()
 | 
			
		||||
	setRTCEventFlag(RTC_TIMER_BIT, enableflag)
 | 
			
		||||
 | 
			
		||||
	# 0x80 Timer Enabled, mode: 0x3=1/Min, 0x2=1/Sec, 0x1=Per 64th Sec, 0=Per 4096th Sec
 | 
			
		||||
	timerconfigFlag = 0x83
 | 
			
		||||
	if inSeconds == True:
 | 
			
		||||
		timerconfigFlag = 0x82
 | 
			
		||||
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, 14, timerconfigFlag)
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC, 15, numDECtoBCD(value&0xff))
 | 
			
		||||
	return 0
 | 
			
		||||
 | 
			
		||||
#############
 | 
			
		||||
# Date/Time
 | 
			
		||||
#############
 | 
			
		||||
 | 
			
		||||
# Returns RTC timestamp as datetime object
 | 
			
		||||
def getRTCdatetime():
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return datetime.datetime(2000, 1, 1, 0, 0, 0)
 | 
			
		||||
 | 
			
		||||
	# Data Sheet Recommends to read this manner (instead of from registers)
 | 
			
		||||
	bus.write_byte(ADDR_RTC,2)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	out = numBCDtoDEC(out & 0x7f)
 | 
			
		||||
	second = out
 | 
			
		||||
	#warningflag = (out & 0x80)>>7
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	minute = numBCDtoDEC(out & 0x7f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	hour = numBCDtoDEC(out & 0x3f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	caldate = numBCDtoDEC(out & 0x3f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	#weekDay = numBCDtoDEC(out & 7)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	month = numBCDtoDEC(out & 0x1f)
 | 
			
		||||
 | 
			
		||||
	out = bus.read_byte(ADDR_RTC)
 | 
			
		||||
	year = numBCDtoDEC(out)
 | 
			
		||||
 | 
			
		||||
	#print({"year":year, "month": month, "date": caldate, "hour": hour, "minute": minute, "second": second})
 | 
			
		||||
 | 
			
		||||
	if month == 0:
 | 
			
		||||
		# Reset, uninitialized RTC
 | 
			
		||||
		month = 1
 | 
			
		||||
 | 
			
		||||
	# Timezone is GMT/UTC +0
 | 
			
		||||
	# Year is from 2000
 | 
			
		||||
	try:
 | 
			
		||||
		return datetime.datetime(year+2000, month, caldate, hour, minute, second)+argonrtc.getLocaltimeOffset()
 | 
			
		||||
	except:
 | 
			
		||||
		return datetime.datetime(2000, 1, 1, 0, 0, 0)
 | 
			
		||||
 | 
			
		||||
# set RTC time using datetime object (Local time)
 | 
			
		||||
def setRTCdatetime(localdatetime):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	# Set local time to UTC
 | 
			
		||||
	localdatetime = localdatetime - argonrtc.getLocaltimeOffset()
 | 
			
		||||
 | 
			
		||||
	# python Sunday = 6, RTC Sunday = 0
 | 
			
		||||
	weekDay = localdatetime.weekday()
 | 
			
		||||
	if weekDay == 6:
 | 
			
		||||
		weekDay = 0
 | 
			
		||||
	else:
 | 
			
		||||
		weekDay = weekDay + 1
 | 
			
		||||
 | 
			
		||||
	# Write to respective registers
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,2,numDECtoBCD(localdatetime.second))
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,3,numDECtoBCD(localdatetime.minute))
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,4,numDECtoBCD(localdatetime.hour))
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,5,numDECtoBCD(localdatetime.day))
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,6,numDECtoBCD(weekDay))
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,7,numDECtoBCD(localdatetime.month))
 | 
			
		||||
 | 
			
		||||
	# Year is from 2000
 | 
			
		||||
	bus.write_byte_data(ADDR_RTC,8,numDECtoBCD(localdatetime.year-2000))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Config
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Set Next Alarm on RTC
 | 
			
		||||
def setNextAlarm(commandschedulelist, prevdatetime):
 | 
			
		||||
	nextcommandtime, weekday, caldate, hour, minute = argonrtc.getNextAlarm(commandschedulelist, prevdatetime)
 | 
			
		||||
	if prevdatetime >= nextcommandtime:
 | 
			
		||||
		return prevdatetime
 | 
			
		||||
	if weekday < 0 and caldate < 0 and hour < 0 and minute < 0:
 | 
			
		||||
		# No schedule
 | 
			
		||||
		# nextcommandtime is current time, which will be replaced/checked next iteration
 | 
			
		||||
		removeRTCAlarm()
 | 
			
		||||
		return nextcommandtime
 | 
			
		||||
 | 
			
		||||
	setRTCAlarm(True, nextcommandtime.weekday(), nextcommandtime.day, nextcommandtime.hour, nextcommandtime.minute)
 | 
			
		||||
	return nextcommandtime
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def allowshutdown():
 | 
			
		||||
	uptime = 0.0
 | 
			
		||||
	errorflag = False
 | 
			
		||||
	try:
 | 
			
		||||
		cpuctr = 0
 | 
			
		||||
		tempfp = open("/proc/uptime", "r")
 | 
			
		||||
		alllines = tempfp.readlines()
 | 
			
		||||
		for temp in alllines:
 | 
			
		||||
			infolist = temp.split(" ")
 | 
			
		||||
			if len(infolist) > 1:
 | 
			
		||||
				uptime = float(infolist[0])
 | 
			
		||||
				break
 | 
			
		||||
		tempfp.close()
 | 
			
		||||
	except IOError:
 | 
			
		||||
		errorflag = True
 | 
			
		||||
	# 120=2mins minimum up time
 | 
			
		||||
	return uptime > 120
 | 
			
		||||
 | 
			
		||||
######
 | 
			
		||||
if len(sys.argv) > 1:
 | 
			
		||||
	cmd = sys.argv[1].upper()
 | 
			
		||||
 | 
			
		||||
	# Enable Alarm/Timer Flags
 | 
			
		||||
	enableflag = True
 | 
			
		||||
 | 
			
		||||
	if cmd == "CLEAN":
 | 
			
		||||
		removeRTCAlarm()
 | 
			
		||||
		removeRTCTimer()
 | 
			
		||||
	elif cmd == "SHUTDOWN":
 | 
			
		||||
		clearRTCAlarmFlag()
 | 
			
		||||
		clearRTCTimerFlag()
 | 
			
		||||
 | 
			
		||||
	elif cmd == "GETRTCSCHEDULE":
 | 
			
		||||
		print("Alarm Setting:")
 | 
			
		||||
		print("\t"+describeAlarm())
 | 
			
		||||
		#print("Timer Setting:")
 | 
			
		||||
		#print("\t"+describeTimer(True))
 | 
			
		||||
 | 
			
		||||
	elif cmd == "GETRTCTIME":
 | 
			
		||||
		print("RTC Time:", getRTCdatetime())
 | 
			
		||||
 | 
			
		||||
	elif cmd == "UPDATERTCTIME":
 | 
			
		||||
		setRTCdatetime(datetime.datetime.now())
 | 
			
		||||
		print("RTC Time:", getRTCdatetime())
 | 
			
		||||
 | 
			
		||||
	elif cmd == "GETSCHEDULELIST":
 | 
			
		||||
		argonrtc.describeConfigList(RTC_CONFIGFILE)
 | 
			
		||||
 | 
			
		||||
	elif cmd == "SHOWSCHEDULE":
 | 
			
		||||
		if len(sys.argv) > 2:
 | 
			
		||||
			if sys.argv[2].isdigit():
 | 
			
		||||
				# Display starts at 2, maps to 0-based index
 | 
			
		||||
				configidx = int(sys.argv[2])-2
 | 
			
		||||
				configlist = argonrtc.loadConfigList(RTC_CONFIGFILE)
 | 
			
		||||
				if len(configlist) > configidx:
 | 
			
		||||
					print ("  ",argonrtc.describeConfigListEntry(configlist[configidx]))
 | 
			
		||||
				else:
 | 
			
		||||
					print("   Invalid Schedule")
 | 
			
		||||
 | 
			
		||||
	elif cmd == "REMOVESCHEDULE":
 | 
			
		||||
		if len(sys.argv) > 2:
 | 
			
		||||
			if sys.argv[2].isdigit():
 | 
			
		||||
				# Display starts at 2, maps to 0-based index
 | 
			
		||||
				configidx = int(sys.argv[2])-2
 | 
			
		||||
				argonrtc.removeConfigEntry(RTC_CONFIGFILE, configidx)
 | 
			
		||||
 | 
			
		||||
	elif cmd == "SERVICE":
 | 
			
		||||
		argonrtc.updateSystemTime(getRTCdatetime())
 | 
			
		||||
 | 
			
		||||
		commandschedulelist = argonrtc.formCommandScheduleList(argonrtc.loadConfigList(RTC_CONFIGFILE))
 | 
			
		||||
		nextrtcalarmtime = setNextAlarm(commandschedulelist, datetime.datetime.now())
 | 
			
		||||
		serviceloop = True
 | 
			
		||||
		while serviceloop==True:
 | 
			
		||||
			clearRTCAlarmFlag()
 | 
			
		||||
			clearRTCTimerFlag()
 | 
			
		||||
 | 
			
		||||
			tmpcurrenttime = datetime.datetime.now()
 | 
			
		||||
			if nextrtcalarmtime <= tmpcurrenttime:
 | 
			
		||||
				# Update RTC Alarm to next iteration
 | 
			
		||||
				nextrtcalarmtime = setNextAlarm(commandschedulelist, nextrtcalarmtime)
 | 
			
		||||
			if len(argonrtc.getCommandForTime(commandschedulelist, tmpcurrenttime, "off")) > 0:
 | 
			
		||||
				# Shutdown detected, issue command then end service loop
 | 
			
		||||
				if allowshutdown():
 | 
			
		||||
					os.system("shutdown now -h")
 | 
			
		||||
					serviceloop = False
 | 
			
		||||
				# Don't break to sleep while command executes (prevents service to restart)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			time.sleep(60)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
elif False:
 | 
			
		||||
	print("System Time: ", datetime.datetime.now())
 | 
			
		||||
	print("RTC    Time: ", getRTCdatetime())
 | 
			
		||||
 | 
			
		||||
	describeControlRegisters()
 | 
			
		||||
							
								
								
									
										10
									
								
								source/scripts/argoneond.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								source/scripts/argoneond.service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Argon EON RTC Service
 | 
			
		||||
After=multi-user.target
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
RemainAfterExit=true
 | 
			
		||||
ExecStart=/usr/bin/python3 /etc/argon/argoneond.py SERVICE
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
							
								
								
									
										345
									
								
								source/scripts/argoneonoled.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								source/scripts/argoneonoled.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,345 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import datetime
 | 
			
		||||
import math
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
# Initialize I2C Bus
 | 
			
		||||
import smbus
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
	bus=smbus.SMBus(1)
 | 
			
		||||
except Exception:
 | 
			
		||||
	try:
 | 
			
		||||
		# Older version
 | 
			
		||||
		bus=smbus.SMBus(0)
 | 
			
		||||
	except Exception:
 | 
			
		||||
		print("Unable to detect i2c")
 | 
			
		||||
		bus=None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
OLED_WD=128
 | 
			
		||||
OLED_HT=64
 | 
			
		||||
OLED_SLAVEADDRESS=0x6a
 | 
			
		||||
ADDR_OLED=0x3c
 | 
			
		||||
 | 
			
		||||
OLED_NUMFONTCHAR=256
 | 
			
		||||
 | 
			
		||||
OLED_BUFFERIZE = ((OLED_WD*OLED_HT)>>3)
 | 
			
		||||
oled_imagebuffer = [0] * OLED_BUFFERIZE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_getmaxY():
 | 
			
		||||
	return OLED_HT
 | 
			
		||||
 | 
			
		||||
def oled_getmaxX():
 | 
			
		||||
	return OLED_WD
 | 
			
		||||
 | 
			
		||||
def oled_loadbg(bgname):
 | 
			
		||||
	if bgname == "bgblack":
 | 
			
		||||
		oled_clearbuffer()
 | 
			
		||||
		return
 | 
			
		||||
	elif bgname == "bgwhite":
 | 
			
		||||
		oled_clearbuffer(1)
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		file = open("/etc/argon/oled/"+bgname+".bin", "rb")
 | 
			
		||||
		bgbytes = list(file.read())
 | 
			
		||||
		file.close()
 | 
			
		||||
		ctr = len(bgbytes)
 | 
			
		||||
		if ctr == OLED_BUFFERIZE:
 | 
			
		||||
			oled_imagebuffer[:] = bgbytes
 | 
			
		||||
		elif ctr > OLED_BUFFERIZE:
 | 
			
		||||
			oled_imagebuffer[:] = bgbytes[0:OLED_BUFFERIZE]
 | 
			
		||||
		else:
 | 
			
		||||
			oled_imagebuffer[0:ctr] = bgbytes
 | 
			
		||||
			# Clear the rest of the buffer
 | 
			
		||||
			while ctr < OLED_BUFFERIZE:
 | 
			
		||||
				oled_imagebuffer[ctr] = 0
 | 
			
		||||
				ctr=ctr+1
 | 
			
		||||
	except FileNotFoundError:
 | 
			
		||||
		oled_clearbuffer()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_clearbuffer(value = 0):
 | 
			
		||||
	if value != 0:
 | 
			
		||||
		value = 0xff
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < OLED_BUFFERIZE:
 | 
			
		||||
		oled_imagebuffer[ctr] = value
 | 
			
		||||
		ctr=ctr+1
 | 
			
		||||
 | 
			
		||||
def oled_writebyterow(x,y,bytevalue, mode = 0):
 | 
			
		||||
	bufferoffset = OLED_WD*(y>>3) + x
 | 
			
		||||
	if mode == 0:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = bytevalue
 | 
			
		||||
	elif mode == 1:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = bytevalue^oled_imagebuffer[bufferoffset]
 | 
			
		||||
	else:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = bytevalue|oled_imagebuffer[bufferoffset]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_writebuffer(x,y,value, mode = 0):
 | 
			
		||||
 | 
			
		||||
	yoffset = y>>3
 | 
			
		||||
	yshift = y&0x7
 | 
			
		||||
	ybit = (1<<yshift)
 | 
			
		||||
 | 
			
		||||
	ymask = 0xFF^ybit
 | 
			
		||||
 | 
			
		||||
	if value != 0:
 | 
			
		||||
		value = ybit
 | 
			
		||||
 | 
			
		||||
	bufferoffset = OLED_WD*yoffset + x
 | 
			
		||||
 | 
			
		||||
	curval = oled_imagebuffer[bufferoffset]
 | 
			
		||||
	if mode & 1:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = curval^value
 | 
			
		||||
	else:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = curval&ymask|value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_fill(value):
 | 
			
		||||
	oled_clearbuffer(value)
 | 
			
		||||
	oled_flushimage()
 | 
			
		||||
 | 
			
		||||
def oled_flushimage(hidescreen = True):
 | 
			
		||||
	if hidescreen == True:
 | 
			
		||||
		# Reset/Hide screen
 | 
			
		||||
		oled_power(False)
 | 
			
		||||
 | 
			
		||||
	xctr = 0
 | 
			
		||||
	while xctr < OLED_WD:
 | 
			
		||||
		yctr = 0
 | 
			
		||||
		while yctr < OLED_HT:
 | 
			
		||||
			oled_flushblock(xctr, yctr)
 | 
			
		||||
			yctr = yctr + 8
 | 
			
		||||
		xctr = xctr + 32
 | 
			
		||||
 | 
			
		||||
	if hidescreen == True:
 | 
			
		||||
		# Display
 | 
			
		||||
		oled_power(True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_flushblock(xoffset, yoffset):
 | 
			
		||||
	yoffset = yoffset>>3
 | 
			
		||||
	blocksize = 32
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		# Set COM-H Addressing
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x20)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x1)
 | 
			
		||||
 | 
			
		||||
		# Set Column range
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x21)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, xoffset)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, xoffset+blocksize-1)
 | 
			
		||||
 | 
			
		||||
		# Set Row Range
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x22)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, yoffset)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, yoffset)
 | 
			
		||||
 | 
			
		||||
		# Set Display Start Line
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x40)
 | 
			
		||||
 | 
			
		||||
		bufferoffset = OLED_WD*yoffset + xoffset
 | 
			
		||||
		# Write Out Buffer
 | 
			
		||||
		bus.write_i2c_block_data(ADDR_OLED, OLED_SLAVEADDRESS, oled_imagebuffer[bufferoffset:(bufferoffset+blocksize)])
 | 
			
		||||
	except:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
def oled_drawfilledrectangle(x, y, wd, ht, mode = 0):
 | 
			
		||||
	ymax = y + ht
 | 
			
		||||
	cury = y&0xF8
 | 
			
		||||
 | 
			
		||||
	xmax = x + wd
 | 
			
		||||
	curx = x
 | 
			
		||||
	if ((y & 0x7)) != 0:
 | 
			
		||||
		yshift = y&0x7
 | 
			
		||||
		bytevalue = (0xFF<<yshift)&0xFF
 | 
			
		||||
 | 
			
		||||
		# If 8 no additional masking needed
 | 
			
		||||
		if ymax-cury  < 8:
 | 
			
		||||
			yshift = 8-((ymax-cury)&0x7)
 | 
			
		||||
			bytevalue = bytevalue & (0xFF>>yshift)
 | 
			
		||||
 | 
			
		||||
		while curx < xmax:
 | 
			
		||||
			oled_writebyterow(curx,cury,bytevalue, mode)
 | 
			
		||||
			curx = curx + 1
 | 
			
		||||
		cury = cury + 8
 | 
			
		||||
	# Draw 8 rows at a time when possible
 | 
			
		||||
	while cury + 8 < ymax:
 | 
			
		||||
		curx = x
 | 
			
		||||
		while curx < xmax:
 | 
			
		||||
			oled_writebyterow(curx,cury,0xFF, mode)
 | 
			
		||||
			curx = curx + 1
 | 
			
		||||
		cury = cury + 8
 | 
			
		||||
 | 
			
		||||
	if cury < ymax:
 | 
			
		||||
		yshift = 8-((ymax-cury)&0x7)
 | 
			
		||||
		bytevalue = (0xFF>>yshift)
 | 
			
		||||
 | 
			
		||||
		curx = x
 | 
			
		||||
		while curx < xmax:
 | 
			
		||||
			oled_writebyterow(curx,cury,bytevalue, mode)
 | 
			
		||||
			curx = curx + 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_writetextaligned(textdata, x, y, boxwidth, alignmode, charwd = 6, mode = 0):
 | 
			
		||||
	leftoffset = 0
 | 
			
		||||
	if alignmode == 1:
 | 
			
		||||
		# Centered
 | 
			
		||||
		leftoffset = (boxwidth-len(textdata)*charwd)>>1
 | 
			
		||||
	elif alignmode == 2:
 | 
			
		||||
		# Right aligned
 | 
			
		||||
		leftoffset = (boxwidth-len(textdata)*charwd)
 | 
			
		||||
 | 
			
		||||
	oled_writetext(textdata, x+leftoffset, y, charwd, mode)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_writetext(textdata, x, y, charwd = 6, mode = 0):
 | 
			
		||||
	if charwd < 6:
 | 
			
		||||
		charwd = 6
 | 
			
		||||
 | 
			
		||||
	charht = int((charwd<<3)/6)
 | 
			
		||||
	if charht & 0x7:
 | 
			
		||||
		charht = (charht&0xF8) + 8
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		file = open("/etc/argon/oled/font"+str(charht)+"x"+str(charwd)+".bin", "rb")
 | 
			
		||||
		fontbytes = list(file.read())
 | 
			
		||||
		file.close()
 | 
			
		||||
	except FileNotFoundError:
 | 
			
		||||
		try:
 | 
			
		||||
			# Default to smallest
 | 
			
		||||
			file = open("/etc/argon/oled/font8x6.bin", "rb")
 | 
			
		||||
			fontbytes = list(file.read())
 | 
			
		||||
			file.close()
 | 
			
		||||
		except FileNotFoundError:
 | 
			
		||||
			return
 | 
			
		||||
 | 
			
		||||
	if ((y & 0x7)) == 0:
 | 
			
		||||
		# Use optimized loading
 | 
			
		||||
		oled_fastwritetext(textdata, x, y, charht, charwd, fontbytes, mode)
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	numfontrow = charht>>3
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < len(textdata):
 | 
			
		||||
		fontoffset = ord(textdata[ctr])*charwd
 | 
			
		||||
		fontcol = 0
 | 
			
		||||
		while fontcol < charwd and x < OLED_WD:
 | 
			
		||||
			fontrow = 0
 | 
			
		||||
			row = y
 | 
			
		||||
			while fontrow < numfontrow and row < OLED_HT and x >= 0:
 | 
			
		||||
				curbit = 0x80
 | 
			
		||||
				curbyte = (fontbytes[fontoffset + fontcol + (OLED_NUMFONTCHAR*charwd*fontrow)])
 | 
			
		||||
				subrow = 0
 | 
			
		||||
				while subrow < 8 and row < OLED_HT:
 | 
			
		||||
					value = 0
 | 
			
		||||
					if (curbyte&curbit) != 0:
 | 
			
		||||
						value = 1
 | 
			
		||||
					oled_writebuffer(x,row,value, mode)
 | 
			
		||||
					curbit = curbit >> 1
 | 
			
		||||
					row = row + 1
 | 
			
		||||
					subrow = subrow + 1
 | 
			
		||||
				fontrow = fontrow + 1
 | 
			
		||||
			fontcol = fontcol + 1
 | 
			
		||||
			x = x + 1
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
 | 
			
		||||
def oled_fastwritetext(textdata, x, y, charht, charwd, fontbytes, mode = 0):
 | 
			
		||||
 | 
			
		||||
	numfontrow = charht>>3
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < len(textdata):
 | 
			
		||||
		fontoffset = ord(textdata[ctr])*charwd
 | 
			
		||||
		fontcol = 0
 | 
			
		||||
		while fontcol < charwd and x < OLED_WD:
 | 
			
		||||
			fontrow = 0
 | 
			
		||||
			row = y&0xF8
 | 
			
		||||
			while fontrow < numfontrow and row < OLED_HT and x >= 0:
 | 
			
		||||
				curbyte = (fontbytes[fontoffset + fontcol + (OLED_NUMFONTCHAR*charwd*fontrow)])
 | 
			
		||||
				oled_writebyterow(x,row,curbyte, mode)
 | 
			
		||||
				fontrow = fontrow + 1
 | 
			
		||||
				row = row + 8
 | 
			
		||||
			fontcol = fontcol + 1
 | 
			
		||||
			x = x + 1
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_power(turnon = True):
 | 
			
		||||
	cmd = 0xAE
 | 
			
		||||
	if turnon == True:
 | 
			
		||||
		cmd = cmd|1
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, cmd)
 | 
			
		||||
	except:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_inverse(enable = True):
 | 
			
		||||
	cmd = 0xA6
 | 
			
		||||
	if enable == True:
 | 
			
		||||
		cmd = cmd|1
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, cmd)
 | 
			
		||||
	except:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_fullwhite(enable = True):
 | 
			
		||||
	cmd = 0xA4
 | 
			
		||||
	if enable == True:
 | 
			
		||||
		cmd = cmd|1
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, cmd)
 | 
			
		||||
	except:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_reset():
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		# Set COM-H Addressing
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x20)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x1)
 | 
			
		||||
 | 
			
		||||
		# Set Column range
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x21)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, OLED_WD-1)
 | 
			
		||||
 | 
			
		||||
		# Set Row Range
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x22)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, (OLED_HT>>3)-1)
 | 
			
		||||
 | 
			
		||||
		# Set Page Addressing
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x20)
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x2)
 | 
			
		||||
		# Set GDDRAM Address
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0xB0)
 | 
			
		||||
 | 
			
		||||
		# Set Display Start Line
 | 
			
		||||
		bus.write_byte_data(ADDR_OLED, 0, 0x40)
 | 
			
		||||
	except:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										254
									
								
								source/scripts/argonone-fanconfig.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								source/scripts/argonone-fanconfig.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
daemonconfigfile=/etc/argononed.conf
 | 
			
		||||
unitconfigfile=/etc/argonunits.conf
 | 
			
		||||
fanmode="CPU"
 | 
			
		||||
 | 
			
		||||
if [ "$1" == "hdd" ]
 | 
			
		||||
then
 | 
			
		||||
	daemonconfigfile=/etc/argononed-hdd.conf
 | 
			
		||||
	fanmode="HDD"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -f "$unitconfigfile" ]
 | 
			
		||||
then
 | 
			
		||||
	. $unitconfigfile
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ -z "$temperature" ]
 | 
			
		||||
then
 | 
			
		||||
	temperature="C"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "------------------------------------------"
 | 
			
		||||
echo " Argon Fan Speed Configuration Tool ($fanmode)"
 | 
			
		||||
echo "------------------------------------------"
 | 
			
		||||
echo "WARNING: This will remove existing configuration."
 | 
			
		||||
echo -n "Press Y to continue:"
 | 
			
		||||
read -n 1 confirm
 | 
			
		||||
echo
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
fanloopflag=1
 | 
			
		||||
newmode=0
 | 
			
		||||
if [ "$confirm" = "y" ]
 | 
			
		||||
then
 | 
			
		||||
	confirm="Y"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ "$confirm" != "Y" ]
 | 
			
		||||
then
 | 
			
		||||
	fanloopflag=0
 | 
			
		||||
	echo "Cancelled."
 | 
			
		||||
else
 | 
			
		||||
	echo "Thank you."
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 212 ]
 | 
			
		||||
		then
 | 
			
		||||
			# 212F = 100C
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
while [ $fanloopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	echo
 | 
			
		||||
	echo "Select fan mode:"
 | 
			
		||||
	echo "  1. Always on"
 | 
			
		||||
	if [ "$fanmode" == "HDD" ]
 | 
			
		||||
	then
 | 
			
		||||
		if [ "$temperature" == "C" ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "  2. Adjust to temperatures (35C, 40C, and 45C)"
 | 
			
		||||
		else
 | 
			
		||||
			echo "  2. Adjust to temperatures (95F, 104F, and 113F)"
 | 
			
		||||
		fi
 | 
			
		||||
	else
 | 
			
		||||
		if [ "$temperature" == "C" ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "  2. Adjust to temperatures (55C, 60C, and 65C)"
 | 
			
		||||
		else
 | 
			
		||||
			echo "  2. Adjust to temperatures (130F, 140F, and 150F)"
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
	echo "  3. Customize temperature cut-offs"
 | 
			
		||||
	echo
 | 
			
		||||
	echo "  0. Exit"
 | 
			
		||||
	echo "NOTE: You can also edit $daemonconfigfile directly"
 | 
			
		||||
	echo -n "Enter Number (0-3):"
 | 
			
		||||
	newmode=$( get_number )
 | 
			
		||||
 | 
			
		||||
	if [[ $newmode -eq 0 ]]
 | 
			
		||||
	then
 | 
			
		||||
		fanloopflag=0
 | 
			
		||||
	elif [ $newmode -eq 1 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "#" > $daemonconfigfile
 | 
			
		||||
		echo "# Argon Fan Speed Configuration $fanmode" >> $daemonconfigfile
 | 
			
		||||
		echo "#" >> $daemonconfigfile
 | 
			
		||||
		echo "# Min Temp=Fan Speed" >> $daemonconfigfile
 | 
			
		||||
 | 
			
		||||
		errorfanflag=1
 | 
			
		||||
		while [ $errorfanflag -eq 1 ]
 | 
			
		||||
		do
 | 
			
		||||
			echo -n "Please provide fan speed (30-100 only):"
 | 
			
		||||
 | 
			
		||||
			curfan=$( get_number )
 | 
			
		||||
			if [ $curfan -ge 30 ]
 | 
			
		||||
			then
 | 
			
		||||
				errorfanflag=0
 | 
			
		||||
			elif [ $curfan -gt 100 ]
 | 
			
		||||
			then
 | 
			
		||||
				errorfanflag=0
 | 
			
		||||
			fi
 | 
			
		||||
		done
 | 
			
		||||
 | 
			
		||||
		echo "1="$curfan >> $daemonconfigfile
 | 
			
		||||
		sudo systemctl restart argononed.service
 | 
			
		||||
		echo "Fan always on."
 | 
			
		||||
	elif [ $newmode -eq 2 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "#" > $daemonconfigfile
 | 
			
		||||
		echo "# Argon Fan Speed Configuration $fanmode" >> $daemonconfigfile
 | 
			
		||||
		echo "#" >> $daemonconfigfile
 | 
			
		||||
		echo "# Min Temp=Fan Speed" >> $daemonconfigfile
 | 
			
		||||
 | 
			
		||||
		echo "Please provide fan speeds for the following temperatures:"
 | 
			
		||||
		curtemp=55
 | 
			
		||||
		maxtemp=70
 | 
			
		||||
		if [ "$fanmode" == "HDD" ]
 | 
			
		||||
		then
 | 
			
		||||
			curtemp=30
 | 
			
		||||
			maxtemp=60
 | 
			
		||||
		fi
 | 
			
		||||
		while [ $curtemp -lt $maxtemp ]
 | 
			
		||||
		do
 | 
			
		||||
			errorfanflag=1
 | 
			
		||||
			while [ $errorfanflag -eq 1 ]
 | 
			
		||||
			do
 | 
			
		||||
				displaytemp=$curtemp
 | 
			
		||||
				if [ "$temperature" == "F" ]
 | 
			
		||||
				then
 | 
			
		||||
					# Convert C to F
 | 
			
		||||
					displaytemp=$((($curtemp*9/5)+32))
 | 
			
		||||
				fi
 | 
			
		||||
				echo -n ""$displaytemp"$temperature (30-100 only):"
 | 
			
		||||
 | 
			
		||||
				curfan=$( get_number )
 | 
			
		||||
				if [ $curfan -ge 30 ]
 | 
			
		||||
				then
 | 
			
		||||
					errorfanflag=0
 | 
			
		||||
				elif [ $curfan -gt 100 ]
 | 
			
		||||
				then
 | 
			
		||||
					errorfanflag=0
 | 
			
		||||
				fi
 | 
			
		||||
			done
 | 
			
		||||
			echo $curtemp"="$curfan >> $daemonconfigfile
 | 
			
		||||
			curtemp=$((curtemp+5))
 | 
			
		||||
		done
 | 
			
		||||
 | 
			
		||||
		sudo systemctl restart argononed.service
 | 
			
		||||
		echo "Configuration updated."
 | 
			
		||||
	elif [ $newmode -eq 3 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "Please provide fan speeds and temperature pairs"
 | 
			
		||||
		echo
 | 
			
		||||
 | 
			
		||||
		subloopflag=1
 | 
			
		||||
		paircounter=0
 | 
			
		||||
		while [ $subloopflag -eq 1 ]
 | 
			
		||||
		do
 | 
			
		||||
			errortempflag=1
 | 
			
		||||
			errorfanflag=1
 | 
			
		||||
			echo "(You may set a blank value to end configuration)"
 | 
			
		||||
			while [ $errortempflag -eq 1 ]
 | 
			
		||||
			do
 | 
			
		||||
				echo -n "Provide minimum temperature of $fanmode (in $temperature) then [ENTER]:"
 | 
			
		||||
 | 
			
		||||
				curtemp=$( get_number )
 | 
			
		||||
				if [ $curtemp -ge 0 ]
 | 
			
		||||
				then
 | 
			
		||||
					errortempflag=0
 | 
			
		||||
				elif [ $curtemp -eq -2 ]
 | 
			
		||||
				then
 | 
			
		||||
					# Blank
 | 
			
		||||
					errortempflag=0
 | 
			
		||||
					errorfanflag=0
 | 
			
		||||
					subloopflag=0
 | 
			
		||||
				fi
 | 
			
		||||
			done
 | 
			
		||||
			while [ $errorfanflag -eq 1 ]
 | 
			
		||||
			do
 | 
			
		||||
				echo -n "Provide fan speed for "$curtemp"$temperature (30-100) then [ENTER]:"
 | 
			
		||||
				curfan=$( get_number )
 | 
			
		||||
				if [ $curfan -ge 30 ]
 | 
			
		||||
				then
 | 
			
		||||
					errorfanflag=0
 | 
			
		||||
				elif [ $curfan -gt 100 ]
 | 
			
		||||
				then
 | 
			
		||||
					errorfanflag=0
 | 
			
		||||
				elif [ $curfan -eq -2 ]
 | 
			
		||||
				then
 | 
			
		||||
					# Blank
 | 
			
		||||
					errortempflag=0
 | 
			
		||||
					errorfanflag=0
 | 
			
		||||
					subloopflag=0
 | 
			
		||||
				fi
 | 
			
		||||
			done
 | 
			
		||||
			if [ $subloopflag -eq 1 ]
 | 
			
		||||
			then
 | 
			
		||||
				if [ $paircounter -eq 0 ]
 | 
			
		||||
				then
 | 
			
		||||
					echo "#" > $daemonconfigfile
 | 
			
		||||
					echo "# Argon Fan Configuration" >> $daemonconfigfile
 | 
			
		||||
					echo "#" >> $daemonconfigfile
 | 
			
		||||
					echo "# Min Temp=Fan Speed" >> $daemonconfigfile
 | 
			
		||||
				fi
 | 
			
		||||
 | 
			
		||||
				displaytemp=$curtemp
 | 
			
		||||
				paircounter=$((paircounter+1))
 | 
			
		||||
				if [ "$temperature" == "F" ]
 | 
			
		||||
				then
 | 
			
		||||
					# Convert to F to C
 | 
			
		||||
					curtemp=$((($curtemp-32)*5/9))
 | 
			
		||||
				fi
 | 
			
		||||
				echo $curtemp"="$curfan >> $daemonconfigfile
 | 
			
		||||
 | 
			
		||||
				echo "* Fan speed will be set to "$curfan" once $fanmode temperature reaches "$displaytemp"$temperature"
 | 
			
		||||
				echo
 | 
			
		||||
			fi
 | 
			
		||||
		done
 | 
			
		||||
 | 
			
		||||
		echo
 | 
			
		||||
		if [ $paircounter -gt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "Thank you!  We saved "$paircounter" pairs."
 | 
			
		||||
			sudo systemctl restart argononed.service
 | 
			
		||||
			echo "Changes should take effect now."
 | 
			
		||||
		else
 | 
			
		||||
			echo "Cancelled, no data saved."
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
echo
 | 
			
		||||
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ -e /boot/firmware/config.txt ] ; then
 | 
			
		||||
  FIRMWARE=/firmware
 | 
			
		||||
else
 | 
			
		||||
@@ -24,9 +25,10 @@ then
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
echo "--------------------------------"
 | 
			
		||||
echo "Argon One IR Configuration Tool"
 | 
			
		||||
echo "--------------------------------"
 | 
			
		||||
 | 
			
		||||
echo "-----------------------------"
 | 
			
		||||
echo " Argon IR Configuration Tool"
 | 
			
		||||
echo "------------------------------"
 | 
			
		||||
echo "WARNING: This only supports NEC"
 | 
			
		||||
echo "         protocol only."
 | 
			
		||||
echo -n "Press Y to continue:"
 | 
			
		||||
@@ -70,8 +72,8 @@ get_number () {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
irexecrcfile=/etc/lirc/irexec.lircrc
 | 
			
		||||
irexecshfile=/usr/bin/argonirexec
 | 
			
		||||
irdecodefile=/usr/bin/argonirdecoder
 | 
			
		||||
irexecshfile=/etc/argon/argonirexec
 | 
			
		||||
irdecodefile=/etc/argon/argonirdecoder
 | 
			
		||||
kodiuserdatafolder="$HOME/.kodi/userdata"
 | 
			
		||||
kodilircmapfile="$kodiuserdatafolder/Lircmap.xml"
 | 
			
		||||
remotemode=""
 | 
			
		||||
@@ -176,9 +178,9 @@ then
 | 
			
		||||
	fi
 | 
			
		||||
elif [ $newmode -eq 2 ]
 | 
			
		||||
then
 | 
			
		||||
	echo "--------------------------------"
 | 
			
		||||
	echo "Argon One IR Configuration Tool"
 | 
			
		||||
	echo "--------------------------------"
 | 
			
		||||
	echo "-----------------------------"
 | 
			
		||||
	echo " Argon IR Configuration Tool"
 | 
			
		||||
	echo "-----------------------------"
 | 
			
		||||
	echo "WARNING: This will install LIRC"
 | 
			
		||||
	echo "         and related libraries."
 | 
			
		||||
	echo -n "Press Y to agree:"
 | 
			
		||||
@@ -320,7 +322,10 @@ then
 | 
			
		||||
	echo '        <down>KEY_DOWN</down>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <select>KEY_OK</select>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <start>KEY_HOME</start>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <rootmenu>KEY_MENUBACK</rootmenu>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	# 20240611: User reported mapping is incorrect
 | 
			
		||||
	#echo '        <rootmenu>KEY_MENUBACK</rootmenu>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <rootmenu>KEY_MENU</rootmenu>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <back>KEY_BACK</back>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <volumeplus>KEY_VOLUMEUP</volumeplus>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '        <volumeminus>KEY_VOLUMEDOWN</volumeminus>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
	echo '    </remote>' | tee -a $kodilircmapfile 1> /dev/null
 | 
			
		||||
							
								
								
									
										305
									
								
								source/scripts/argonone-upsconfig.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								source/scripts/argonone-upsconfig.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,305 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if [ -e /boot/firmware/config.txt ] ; then
 | 
			
		||||
  FIRMWARE=/firmware
 | 
			
		||||
else
 | 
			
		||||
  FIRMWARE=
 | 
			
		||||
fi
 | 
			
		||||
CONFIG=/boot${FIRMWARE}/config.txt
 | 
			
		||||
 | 
			
		||||
CHECKGPIOMODE="libgpiod" # gpiod or rpigpio
 | 
			
		||||
 | 
			
		||||
# Check if Raspbian, Ubuntu, others
 | 
			
		||||
CHECKPLATFORM="Others"
 | 
			
		||||
CHECKPLATFORMVERSION=""
 | 
			
		||||
CHECKPLATFORMVERSIONNUM=""
 | 
			
		||||
if [ -f "/etc/os-release" ]
 | 
			
		||||
then
 | 
			
		||||
	source /etc/os-release
 | 
			
		||||
	if [ "$ID" = "raspbian" ]
 | 
			
		||||
	then
 | 
			
		||||
		CHECKPLATFORM="Raspbian"
 | 
			
		||||
		CHECKPLATFORMVERSION=$VERSION_ID
 | 
			
		||||
	elif [ "$ID" = "debian" ]
 | 
			
		||||
	then
 | 
			
		||||
		# For backwards compatibility, continue using raspbian
 | 
			
		||||
		CHECKPLATFORM="Raspbian"
 | 
			
		||||
		CHECKPLATFORMVERSION=$VERSION_ID
 | 
			
		||||
	elif [ "$ID" = "ubuntu" ]
 | 
			
		||||
	then
 | 
			
		||||
		CHECKPLATFORM="Ubuntu"
 | 
			
		||||
		CHECKPLATFORMVERSION=$VERSION_ID
 | 
			
		||||
	fi
 | 
			
		||||
	echo ${CHECKPLATFORMVERSION} | grep -e "\." > /dev/null
 | 
			
		||||
	if [ $? -eq 0 ]
 | 
			
		||||
	then
 | 
			
		||||
		CHECKPLATFORMVERSIONNUM=`cut -d "." -f2 <<< $CHECKPLATFORMVERSION `
 | 
			
		||||
		CHECKPLATFORMVERSION=`cut -d "." -f1 <<< $CHECKPLATFORMVERSION `
 | 
			
		||||
	fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
pythonbin=/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
#  Files
 | 
			
		||||
ARGONDOWNLOADSERVER=https://download.argon40.com
 | 
			
		||||
INSTALLATIONFOLDER=/etc/argon
 | 
			
		||||
basename="argononeups"
 | 
			
		||||
daemonname=$basename"d"
 | 
			
		||||
 | 
			
		||||
daemonupsservice=/lib/systemd/system/$daemonname.service
 | 
			
		||||
upsdaemonscript=$INSTALLATIONFOLDER/$daemonname.py
 | 
			
		||||
 | 
			
		||||
rtcdaemonname="argonupsrtcd"
 | 
			
		||||
 | 
			
		||||
daemonrtcservice=/lib/systemd/system/$rtcdaemonname.service
 | 
			
		||||
rtcdaemonscript=$INSTALLATIONFOLDER/$rtcdaemonname.py
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
requireinstall=0
 | 
			
		||||
newmode=0
 | 
			
		||||
echo "-----------------------------------"
 | 
			
		||||
echo " Argon Industria UPS Configuration"
 | 
			
		||||
echo "-----------------------------------"
 | 
			
		||||
if [ ! -f "$upsdaemonscript" ]
 | 
			
		||||
then
 | 
			
		||||
	echo "Install Argon Industria UPS Tools"
 | 
			
		||||
	echo -n "Press Y to continue:"
 | 
			
		||||
	read -n 1 confirm
 | 
			
		||||
	echo
 | 
			
		||||
 | 
			
		||||
	if [ "$confirm" = "y" ]
 | 
			
		||||
	then
 | 
			
		||||
		confirm="Y"
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ "$confirm" != "Y" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "Cancelled"
 | 
			
		||||
		exit
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	requireinstall=1
 | 
			
		||||
	newmode=3	# Reinstall
 | 
			
		||||
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
get_number () {
 | 
			
		||||
	read curnumber
 | 
			
		||||
	if [ -z "$curnumber" ]
 | 
			
		||||
	then
 | 
			
		||||
		echo "-2"
 | 
			
		||||
		return
 | 
			
		||||
	elif [[ $curnumber =~ ^[+-]?[0-9]+$ ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $curnumber -lt 0 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		elif [ $curnumber -gt 100 ]
 | 
			
		||||
		then
 | 
			
		||||
			echo "-1"
 | 
			
		||||
			return
 | 
			
		||||
		fi
 | 
			
		||||
		echo $curnumber
 | 
			
		||||
		return
 | 
			
		||||
	fi
 | 
			
		||||
	echo "-1"
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UPSCMDFILE="/dev/shm/upscmd.txt"
 | 
			
		||||
UPSSTATUSFILE="/dev/shm/upslog.txt"
 | 
			
		||||
rtcconfigscript=$INSTALLATIONFOLDER/argonups-rtcconfig.sh
 | 
			
		||||
 | 
			
		||||
if [ -f "$UPSSTATUSFILE" ]
 | 
			
		||||
then
 | 
			
		||||
#	cat $UPSSTATUSFILE
 | 
			
		||||
	sudo $pythonbin $rtcdaemonscript GETBATTERY
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
loopflag=1
 | 
			
		||||
while [ $loopflag -eq 1 ]
 | 
			
		||||
do
 | 
			
		||||
	if [ $requireinstall -eq 0 ]
 | 
			
		||||
	then
 | 
			
		||||
		echo
 | 
			
		||||
		echo "Select option:"
 | 
			
		||||
		echo "  1. UPS Battery Status"
 | 
			
		||||
		echo "  2. Configure RTC and/or Schedule"
 | 
			
		||||
		echo "  3. Reinstall UPS Tools"
 | 
			
		||||
		echo "  4. Uninstall UPS Tools"
 | 
			
		||||
		echo ""
 | 
			
		||||
		echo "  0. Back"
 | 
			
		||||
 | 
			
		||||
		echo -n "Enter Number (0-4):"
 | 
			
		||||
 | 
			
		||||
		newmode=$( get_number )
 | 
			
		||||
	fi
 | 
			
		||||
	if [[ $newmode -ge 0 && $newmode -le 4 ]]
 | 
			
		||||
	then
 | 
			
		||||
		if [ $newmode -eq 1 ]
 | 
			
		||||
		then
 | 
			
		||||
			sudo $pythonbin $rtcdaemonscript GETBATTERY
 | 
			
		||||
			#if [ -f "$UPSSTATUSFILE" ]
 | 
			
		||||
			#then
 | 
			
		||||
			#	cat $UPSSTATUSFILE
 | 
			
		||||
			#else
 | 
			
		||||
			#	echo "Unable to retrieve status"
 | 
			
		||||
			#fi
 | 
			
		||||
		elif [ $newmode -eq 2 ]
 | 
			
		||||
		then
 | 
			
		||||
			$rtcconfigscript "argonupsrtc"
 | 
			
		||||
			#TMPTIMESTR=`date +"%Y%d%m%H%M%S"`
 | 
			
		||||
			#TMPDATASTR=`date +"%Y %m %d %H %M %S"`
 | 
			
		||||
 | 
			
		||||
			#echo "$TMPTIMESTR" > $UPSCMDFILE
 | 
			
		||||
			#echo "3 $TMPDATASTR" >> $UPSCMDFILE
 | 
			
		||||
		elif [ $newmode -eq 3 ]
 | 
			
		||||
		then
 | 
			
		||||
			# Start installation
 | 
			
		||||
			if [ ! -d "$INSTALLATIONFOLDER/ups" ]
 | 
			
		||||
			then
 | 
			
		||||
				sudo mkdir $INSTALLATIONFOLDER/ups
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			rtcconfigfile=/etc/argonupsrtc.conf
 | 
			
		||||
			# Generate default RTC config file if non-existent
 | 
			
		||||
			if [ ! -f $rtcconfigfile ]; then
 | 
			
		||||
				sudo touch $rtcconfigfile
 | 
			
		||||
				sudo chmod 666 $rtcconfigfile
 | 
			
		||||
 | 
			
		||||
				echo '#' >> $rtcconfigfile
 | 
			
		||||
				echo '# Argon RTC Configuration' >> $rtcconfigfile
 | 
			
		||||
				echo '#' >> $rtcconfigfile
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			for iconfile in battery_0 battery_2 battery_4 battery_charging battery_unknown battery_1 battery_3 battery_alert battery_plug
 | 
			
		||||
			do
 | 
			
		||||
				sudo wget $ARGONDOWNLOADSERVER/ups/${iconfile}.png -O $INSTALLATIONFOLDER/ups/${iconfile}.png --quiet
 | 
			
		||||
			done
 | 
			
		||||
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/ups/upsimg.tar.gz -O $INSTALLATIONFOLDER/ups/upsimg.tar.gz --quiet
 | 
			
		||||
			sudo tar xfz $INSTALLATIONFOLDER/ups/upsimg.tar.gz -C $INSTALLATIONFOLDER/ups/
 | 
			
		||||
			sudo rm -Rf $INSTALLATIONFOLDER/ups/upsimg.tar.gz
 | 
			
		||||
 | 
			
		||||
			# Desktop Icon
 | 
			
		||||
			destfoldername=$USERNAME
 | 
			
		||||
			if [ -z "$destfoldername" ]
 | 
			
		||||
			then
 | 
			
		||||
				destfoldername=$USER
 | 
			
		||||
			fi
 | 
			
		||||
			if [ -z "$destfoldername" ]
 | 
			
		||||
			then
 | 
			
		||||
				destfoldername="pi"
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			shortcutfile="/home/$destfoldername/Desktop/argonone-ups.desktop"
 | 
			
		||||
			if [ -d "/home/$destfoldername/Desktop" ]
 | 
			
		||||
			then
 | 
			
		||||
				terminalcmd="lxterminal --working-directory=/home/$destfoldername/ -t"
 | 
			
		||||
				if  [ -f "/home/$destfoldername/.twisteros.twid" ]
 | 
			
		||||
				then
 | 
			
		||||
					terminalcmd="xfce4-terminal --default-working-directory=/home/$destfoldername/ -T"
 | 
			
		||||
				fi
 | 
			
		||||
 | 
			
		||||
				echo "[Desktop Entry]" > $shortcutfile
 | 
			
		||||
				echo "Name=Argon UPS" >> $shortcutfile
 | 
			
		||||
				echo "Comment=Argon UPS" >> $shortcutfile
 | 
			
		||||
				echo "Icon=/etc/argon/ups/loading_0.png" >> $shortcutfile
 | 
			
		||||
				echo 'Exec='$terminalcmd' "Argon UPS" -e "'$rtcconfigscript' argonupsrtc"' >> $shortcutfile
 | 
			
		||||
				echo "Type=Application" >> $shortcutfile
 | 
			
		||||
				echo "Encoding=UTF-8" >> $shortcutfile
 | 
			
		||||
				echo "Terminal=false" >> $shortcutfile
 | 
			
		||||
				echo "Categories=None;" >> $shortcutfile
 | 
			
		||||
				chmod 755 $shortcutfile
 | 
			
		||||
			fi
 | 
			
		||||
 | 
			
		||||
			# Stopped using default battery indicator
 | 
			
		||||
			## Build Kernel Module
 | 
			
		||||
			#sourcecodefolder=$INSTALLATIONFOLDER/tmp
 | 
			
		||||
			#buildfolder=$sourcecodefolder/build
 | 
			
		||||
			#if [ -d $sourcecodefolder ]
 | 
			
		||||
			#then
 | 
			
		||||
			#		sudo rm -rf $sourcecodefolder
 | 
			
		||||
			#fi
 | 
			
		||||
			#if [ "$CHECKPLATFORM" = "Ubuntu" ]
 | 
			
		||||
			#then
 | 
			
		||||
			#		sudo apt-get install build-essential
 | 
			
		||||
			#fi
 | 
			
		||||
			#sudo mkdir -p $buildfolder
 | 
			
		||||
			#sudo chmod -R 755 $buildfolder
 | 
			
		||||
 | 
			
		||||
			#FILELIST="COPYING Makefile argonbatteryicon.c"
 | 
			
		||||
			#for fname in $FILELIST
 | 
			
		||||
			#do
 | 
			
		||||
			#		sudo wget $ARGONDOWNLOADSERVER/modules/argonbatteryicon/$fname -O $buildfolder/#$fname --quiet
 | 
			
		||||
			#done
 | 
			
		||||
 | 
			
		||||
			## Start Build
 | 
			
		||||
			#cd $buildfolder/
 | 
			
		||||
			#sudo make
 | 
			
		||||
			#sudo cp "$buildfolder/argonbatteryicon.ko" "$INSTALLATIONFOLDER/ups/"
 | 
			
		||||
 | 
			
		||||
			## Cleanup
 | 
			
		||||
			#cd $INSTALLATIONFOLDER/
 | 
			
		||||
			#sudo rm -Rf "$sourcecodefolder"
 | 
			
		||||
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/scripts/argononeupsd.py -O "$upsdaemonscript" --quiet
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/scripts/argononeupsd.service -O "$daemonupsservice" --quiet
 | 
			
		||||
			sudo chmod 666 $daemonupsservice
 | 
			
		||||
			#echo "User=$destfoldername" >> "$daemonupsservice"
 | 
			
		||||
			#echo "Group=$destfoldername" >> "$daemonupsservice"
 | 
			
		||||
 | 
			
		||||
			sudo chmod 644 $daemonupsservice
 | 
			
		||||
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/scripts/argoneon-rtcconfig.sh -O $rtcconfigscript --quiet
 | 
			
		||||
			sudo chmod 755 $rtcconfigscript
 | 
			
		||||
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/scripts/argonrtc.py -O $INSTALLATIONFOLDER/argonrtc.py --quiet
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/scripts/argonupsrtcd.py -O "$rtcdaemonscript" --quiet
 | 
			
		||||
			sudo wget $ARGONDOWNLOADSERVER/scripts/argonupsrtcd.service -O "$daemonrtcservice" --quiet
 | 
			
		||||
			sudo chmod 644 $daemonrtcservice
 | 
			
		||||
 | 
			
		||||
			if [ $requireinstall -eq 1 ]
 | 
			
		||||
			then
 | 
			
		||||
				requireinstall=0
 | 
			
		||||
				sudo systemctl enable "$daemonname.service"
 | 
			
		||||
				sudo systemctl start "$daemonname.service"
 | 
			
		||||
 | 
			
		||||
				sudo systemctl enable "$rtcdaemonname.service"
 | 
			
		||||
				sudo systemctl start "$rtcdaemonname.service"
 | 
			
		||||
			else
 | 
			
		||||
				sudo systemctl restart "$daemonname.service"
 | 
			
		||||
				sudo systemctl restart "$rtcdaemonname.service"
 | 
			
		||||
				loopflag=0
 | 
			
		||||
			fi
 | 
			
		||||
			# Serial I/O is here
 | 
			
		||||
			sudo systemctl restart argononed.service
 | 
			
		||||
		elif [ $newmode -eq 4 ]
 | 
			
		||||
		then
 | 
			
		||||
			sudo systemctl stop "$daemonname.service"
 | 
			
		||||
			sudo systemctl disable "$daemonname.service"
 | 
			
		||||
			sudo rm $daemonupsservice
 | 
			
		||||
			sudo rm $upsdaemonscript
 | 
			
		||||
 | 
			
		||||
			sudo systemctl stop "$rtcdaemonname.service"
 | 
			
		||||
			sudo systemctl disable "$rtcdaemonname.service"
 | 
			
		||||
			sudo rm $daemonrtcservice
 | 
			
		||||
			sudo rm $rtcdaemonscript
 | 
			
		||||
 | 
			
		||||
			sudo rm -R -f $INSTALLATIONFOLDER/ups
 | 
			
		||||
 | 
			
		||||
			echo "Uninstall Completed"
 | 
			
		||||
			loopflag=0
 | 
			
		||||
		else
 | 
			
		||||
			echo "Cancelled"
 | 
			
		||||
			loopflag=0
 | 
			
		||||
		fi
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										600
									
								
								source/scripts/argononed.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										600
									
								
								source/scripts/argononed.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,600 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# This script set fan speed and monitor power button events.
 | 
			
		||||
#
 | 
			
		||||
# Fan Speed is set by sending 0 to 100 to the MCU (Micro Controller Unit)
 | 
			
		||||
# The values will be interpreted as the percentage of fan speed, 100% being maximum
 | 
			
		||||
#
 | 
			
		||||
# Power button events are sent as a pulse signal to BCM Pin 4 (BOARD P7)
 | 
			
		||||
# A pulse width of 20-30ms indicates reboot request (double-tap)
 | 
			
		||||
# A pulse width of 40-50ms indicates shutdown request (hold and release after 3 secs)
 | 
			
		||||
#
 | 
			
		||||
# Additional comments are found in each function below
 | 
			
		||||
#
 | 
			
		||||
# Standard Deployment/Triggers:
 | 
			
		||||
#  * Raspbian, OSMC: Runs as service via /lib/systemd/system/argononed.service
 | 
			
		||||
#  * lakka, libreelec: Runs as service via /storage/.config/system.d/argononed.service
 | 
			
		||||
#  * recalbox: Runs as service via /etc/init.d/
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
from threading import Thread
 | 
			
		||||
from queue import Queue
 | 
			
		||||
 | 
			
		||||
sys.path.append("/etc/argon/")
 | 
			
		||||
from argonsysinfo import *
 | 
			
		||||
from argonregister import *
 | 
			
		||||
from argonpowerbutton import *
 | 
			
		||||
 | 
			
		||||
# Initialize I2C Bus
 | 
			
		||||
bus = argonregister_initializebusobj()
 | 
			
		||||
 | 
			
		||||
OLED_ENABLED=False
 | 
			
		||||
 | 
			
		||||
if os.path.exists("/etc/argon/argoneonoled.py"):
 | 
			
		||||
	import datetime
 | 
			
		||||
	from argoneonoled import *
 | 
			
		||||
	OLED_ENABLED=True
 | 
			
		||||
 | 
			
		||||
OLED_CONFIGFILE = "/etc/argoneonoled.conf"
 | 
			
		||||
UNIT_CONFIGFILE = "/etc/argonunits.conf"
 | 
			
		||||
 | 
			
		||||
# This function converts the corresponding fanspeed for the given temperature
 | 
			
		||||
# The configuration data is a list of strings in the form "<temperature>=<speed>"
 | 
			
		||||
 | 
			
		||||
def get_fanspeed(tempval, configlist):
 | 
			
		||||
	for curconfig in configlist:
 | 
			
		||||
		curpair = curconfig.split("=")
 | 
			
		||||
		tempcfg = float(curpair[0])
 | 
			
		||||
		fancfg = int(float(curpair[1]))
 | 
			
		||||
		if tempval >= tempcfg:
 | 
			
		||||
			if fancfg < 1:
 | 
			
		||||
				return 0
 | 
			
		||||
			elif fancfg < 25:
 | 
			
		||||
				return 25
 | 
			
		||||
			return fancfg
 | 
			
		||||
	return 0
 | 
			
		||||
 | 
			
		||||
# This function retrieves the fanspeed configuration list from a file, arranged by temperature
 | 
			
		||||
# It ignores lines beginning with "#" and checks if the line is a valid temperature-speed pair
 | 
			
		||||
# The temperature values are formatted to uniform length, so the lines can be sorted properly
 | 
			
		||||
 | 
			
		||||
def load_config(fname):
 | 
			
		||||
	newconfig = []
 | 
			
		||||
	try:
 | 
			
		||||
		with open(fname, "r") as fp:
 | 
			
		||||
			for curline in fp:
 | 
			
		||||
				if not curline:
 | 
			
		||||
					continue
 | 
			
		||||
				tmpline = curline.strip()
 | 
			
		||||
				if not tmpline:
 | 
			
		||||
					continue
 | 
			
		||||
				if tmpline[0] == "#":
 | 
			
		||||
					continue
 | 
			
		||||
				tmppair = tmpline.split("=")
 | 
			
		||||
				if len(tmppair) != 2:
 | 
			
		||||
					continue
 | 
			
		||||
				tempval = 0
 | 
			
		||||
				fanval = 0
 | 
			
		||||
				try:
 | 
			
		||||
					tempval = float(tmppair[0])
 | 
			
		||||
					if tempval < 0 or tempval > 100:
 | 
			
		||||
						continue
 | 
			
		||||
				except:
 | 
			
		||||
					continue
 | 
			
		||||
				try:
 | 
			
		||||
					fanval = int(float(tmppair[1]))
 | 
			
		||||
					if fanval < 0 or fanval > 100:
 | 
			
		||||
						continue
 | 
			
		||||
				except:
 | 
			
		||||
					continue
 | 
			
		||||
				newconfig.append( "{:5.1f}={}".format(tempval,fanval))
 | 
			
		||||
		if len(newconfig) > 0:
 | 
			
		||||
			newconfig.sort(reverse=True)
 | 
			
		||||
	except:
 | 
			
		||||
		return []
 | 
			
		||||
	return newconfig
 | 
			
		||||
 | 
			
		||||
# Load OLED Config file
 | 
			
		||||
def load_oledconfig(fname):
 | 
			
		||||
	output={}
 | 
			
		||||
	screenduration=-1
 | 
			
		||||
	screenlist=[]
 | 
			
		||||
	try:
 | 
			
		||||
		with open(fname, "r") as fp:
 | 
			
		||||
			for curline in fp:
 | 
			
		||||
				if not curline:
 | 
			
		||||
					continue
 | 
			
		||||
				tmpline = curline.strip()
 | 
			
		||||
				if not tmpline:
 | 
			
		||||
					continue
 | 
			
		||||
				if tmpline[0] == "#":
 | 
			
		||||
					continue
 | 
			
		||||
				tmppair = tmpline.split("=")
 | 
			
		||||
				if len(tmppair) != 2:
 | 
			
		||||
					continue
 | 
			
		||||
				if tmppair[0] == "switchduration":
 | 
			
		||||
					output['screenduration']=int(tmppair[1])
 | 
			
		||||
				elif tmppair[0] == "screensaver":
 | 
			
		||||
					output['screensaver']=int(tmppair[1])
 | 
			
		||||
				elif tmppair[0] == "screenlist":
 | 
			
		||||
					output['screenlist']=tmppair[1].replace("\"", "").split(" ")
 | 
			
		||||
				elif tmppair[0] == "enabled":
 | 
			
		||||
					output['enabled']=tmppair[1].replace("\"", "")
 | 
			
		||||
	except:
 | 
			
		||||
		return {}
 | 
			
		||||
	return output
 | 
			
		||||
 | 
			
		||||
# Load Unit Config file
 | 
			
		||||
def load_unitconfig(fname):
 | 
			
		||||
	output={"temperature": "C"}
 | 
			
		||||
	try:
 | 
			
		||||
		with open(fname, "r") as fp:
 | 
			
		||||
			for curline in fp:
 | 
			
		||||
				if not curline:
 | 
			
		||||
					continue
 | 
			
		||||
				tmpline = curline.strip()
 | 
			
		||||
				if not tmpline:
 | 
			
		||||
					continue
 | 
			
		||||
				if tmpline[0] == "#":
 | 
			
		||||
					continue
 | 
			
		||||
				tmppair = tmpline.split("=")
 | 
			
		||||
				if len(tmppair) != 2:
 | 
			
		||||
					continue
 | 
			
		||||
				if tmppair[0] == "temperature":
 | 
			
		||||
					output['temperature']=tmppair[1].replace("\"", "")
 | 
			
		||||
	except:
 | 
			
		||||
		return {}
 | 
			
		||||
	return output
 | 
			
		||||
 | 
			
		||||
def load_fancpuconfig():
 | 
			
		||||
	fanconfig = ["65=100", "60=55", "55=30"]
 | 
			
		||||
	tmpconfig = load_config("/etc/argononed.conf")
 | 
			
		||||
	if len(tmpconfig) > 0:
 | 
			
		||||
		fanconfig = tmpconfig
 | 
			
		||||
	return fanconfig
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def load_fanhddconfig():
 | 
			
		||||
	fanhddconfig = ["50=100", "40=55", "30=30"]
 | 
			
		||||
	fanhddconfigfile = "/etc/argononed-hdd.conf"
 | 
			
		||||
 | 
			
		||||
	if os.path.isfile(fanhddconfigfile):
 | 
			
		||||
		tmpconfig = load_config(fanhddconfigfile)
 | 
			
		||||
		if len(tmpconfig) > 0:
 | 
			
		||||
			fanhddconfig = tmpconfig
 | 
			
		||||
	else:
 | 
			
		||||
		fanhddconfig = []
 | 
			
		||||
	return fanhddconfig
 | 
			
		||||
 | 
			
		||||
# This function is the thread that monitors temperature and sets the fan speed
 | 
			
		||||
# The value is fed to get_fanspeed to get the new fan speed
 | 
			
		||||
# To prevent unnecessary fluctuations, lowering fan speed is delayed by 30 seconds
 | 
			
		||||
#
 | 
			
		||||
# Location of config file varies based on OS
 | 
			
		||||
#
 | 
			
		||||
def temp_check():
 | 
			
		||||
	INITIALSPEEDVAL = 200	# ensures fan speed gets set during initialization (e.g. change settings)
 | 
			
		||||
	argonregsupport = argonregister_checksupport(bus)
 | 
			
		||||
 | 
			
		||||
	fanconfig = load_fancpuconfig()
 | 
			
		||||
	fanhddconfig = load_fanhddconfig()
 | 
			
		||||
 | 
			
		||||
	prevspeed=INITIALSPEEDVAL
 | 
			
		||||
	while True:
 | 
			
		||||
		# Speed based on CPU Temp
 | 
			
		||||
		val = argonsysinfo_getcputemp()
 | 
			
		||||
		newspeed = get_fanspeed(val, fanconfig)
 | 
			
		||||
		# Speed based on HDD Temp
 | 
			
		||||
		val = argonsysinfo_getmaxhddtemp()
 | 
			
		||||
		tmpspeed = get_fanspeed(val, fanhddconfig)
 | 
			
		||||
 | 
			
		||||
		# Use faster fan speed
 | 
			
		||||
		if tmpspeed > newspeed:
 | 
			
		||||
			newspeed = tmpspeed
 | 
			
		||||
 | 
			
		||||
		if prevspeed == newspeed:
 | 
			
		||||
			time.sleep(30)
 | 
			
		||||
			continue
 | 
			
		||||
		elif newspeed < prevspeed and prevspeed != INITIALSPEEDVAL:
 | 
			
		||||
			# Pause 30s before speed reduction to prevent fluctuations
 | 
			
		||||
			time.sleep(30)
 | 
			
		||||
		prevspeed = newspeed
 | 
			
		||||
		try:
 | 
			
		||||
			if newspeed > 0:
 | 
			
		||||
				# Spin up to prevent issues on older units
 | 
			
		||||
				argonregister_setfanspeed(bus, 100, argonregsupport)
 | 
			
		||||
				# Set fan speed has sleep
 | 
			
		||||
			argonregister_setfanspeed(bus, newspeed, argonregsupport)
 | 
			
		||||
			time.sleep(30)
 | 
			
		||||
		except IOError:
 | 
			
		||||
			time.sleep(60)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# This function is the thread that updates OLED
 | 
			
		||||
#
 | 
			
		||||
def display_loop(readq):
 | 
			
		||||
	weekdaynamelist = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
 | 
			
		||||
	monthlist = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"]
 | 
			
		||||
	oledscreenwidth = oled_getmaxX()
 | 
			
		||||
 | 
			
		||||
	fontwdSml = 6	# Maps to 6x8
 | 
			
		||||
	fontwdReg = 8	# Maps to 8x16
 | 
			
		||||
	stdleftoffset = 54
 | 
			
		||||
 | 
			
		||||
	temperature="C"
 | 
			
		||||
	tmpconfig=load_unitconfig(UNIT_CONFIGFILE)
 | 
			
		||||
	if "temperature" in tmpconfig:
 | 
			
		||||
		temperature = tmpconfig["temperature"]
 | 
			
		||||
 | 
			
		||||
	screensavermode = False
 | 
			
		||||
	screensaversec = 120
 | 
			
		||||
	screensaverctr = 0
 | 
			
		||||
 | 
			
		||||
	screenenabled = ["clock", "ip"]
 | 
			
		||||
	prevscreen = ""
 | 
			
		||||
	curscreen = ""
 | 
			
		||||
	screenid = 0
 | 
			
		||||
	screenjogtime = 0
 | 
			
		||||
	screenjogflag = 0	# start with screenid 0
 | 
			
		||||
	cpuusagelist = []
 | 
			
		||||
	curlist = []
 | 
			
		||||
 | 
			
		||||
	tmpconfig=load_oledconfig(OLED_CONFIGFILE)
 | 
			
		||||
 | 
			
		||||
	if "screensaver" in tmpconfig:
 | 
			
		||||
		screensaversec = tmpconfig["screensaver"]
 | 
			
		||||
	if "screenduration" in tmpconfig:
 | 
			
		||||
		screenjogtime = tmpconfig["screenduration"]
 | 
			
		||||
	if "screenlist" in tmpconfig:
 | 
			
		||||
		screenenabled = tmpconfig["screenlist"]
 | 
			
		||||
 | 
			
		||||
	if "enabled" in tmpconfig:
 | 
			
		||||
		if tmpconfig["enabled"] == "N":
 | 
			
		||||
			screenenabled = []
 | 
			
		||||
 | 
			
		||||
	while len(screenenabled) > 0:
 | 
			
		||||
		if len(curlist) == 0 and screenjogflag == 1:
 | 
			
		||||
			# Reset Screen Saver
 | 
			
		||||
			screensavermode = False
 | 
			
		||||
			screensaverctr = 0
 | 
			
		||||
 | 
			
		||||
			# Update screen info
 | 
			
		||||
			screenid = screenid + screenjogflag
 | 
			
		||||
			if screenid >= len(screenenabled):
 | 
			
		||||
				screenid = 0
 | 
			
		||||
		prevscreen = curscreen
 | 
			
		||||
		curscreen = screenenabled[screenid]
 | 
			
		||||
 | 
			
		||||
		if screenjogtime == 0:
 | 
			
		||||
			# Resets jogflag (if switched manually)
 | 
			
		||||
			screenjogflag = 0
 | 
			
		||||
		else:
 | 
			
		||||
			screenjogflag = 1
 | 
			
		||||
 | 
			
		||||
		needsUpdate = False
 | 
			
		||||
		if curscreen == "cpu":
 | 
			
		||||
			# CPU Usage
 | 
			
		||||
			if len(curlist) == 0:
 | 
			
		||||
				try:
 | 
			
		||||
					if len(cpuusagelist) == 0:
 | 
			
		||||
						cpuusagelist = argonsysinfo_listcpuusage()
 | 
			
		||||
					curlist = cpuusagelist
 | 
			
		||||
				except:
 | 
			
		||||
					curlist = []
 | 
			
		||||
			if len(curlist) > 0:
 | 
			
		||||
				oled_loadbg("bgcpu")
 | 
			
		||||
 | 
			
		||||
				# Display List
 | 
			
		||||
				yoffset = 0
 | 
			
		||||
				tmpmax = 4
 | 
			
		||||
				while tmpmax > 0 and len(curlist) > 0:
 | 
			
		||||
					curline = ""
 | 
			
		||||
					tmpitem = curlist.pop(0)
 | 
			
		||||
					curline = tmpitem["title"]+": "+str(tmpitem["value"])+"%"
 | 
			
		||||
					oled_writetext(curline, stdleftoffset, yoffset, fontwdSml)
 | 
			
		||||
					oled_drawfilledrectangle(stdleftoffset, yoffset+12, int((oledscreenwidth-stdleftoffset-4)*tmpitem["value"]/100), 2)
 | 
			
		||||
					tmpmax = tmpmax - 1
 | 
			
		||||
					yoffset = yoffset + 16
 | 
			
		||||
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			else:
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
		elif curscreen == "storage":
 | 
			
		||||
			# Storage Info
 | 
			
		||||
			if len(curlist) == 0:
 | 
			
		||||
				try:
 | 
			
		||||
					tmpobj = argonsysinfo_listhddusage()
 | 
			
		||||
					for curdev in tmpobj:
 | 
			
		||||
						curlist.append({"title": curdev, "value": argonsysinfo_kbstr(tmpobj[curdev]['total']), "usage": int(100*tmpobj[curdev]['used']/tmpobj[curdev]['total']) })
 | 
			
		||||
					#curlist = argonsysinfo_liststoragetotal()
 | 
			
		||||
				except:
 | 
			
		||||
					curlist = []
 | 
			
		||||
			if len(curlist) > 0:
 | 
			
		||||
				oled_loadbg("bgstorage")
 | 
			
		||||
 | 
			
		||||
				yoffset = 16
 | 
			
		||||
				tmpmax = 3
 | 
			
		||||
				while tmpmax > 0 and len(curlist) > 0:
 | 
			
		||||
					tmpitem = curlist.pop(0)
 | 
			
		||||
					# Right column first, safer to overwrite white space
 | 
			
		||||
					oled_writetextaligned(tmpitem["value"], 77, yoffset, oledscreenwidth-77, 2, fontwdSml)
 | 
			
		||||
					oled_writetextaligned(str(tmpitem["usage"])+"%", 50, yoffset, 74-50, 2, fontwdSml)
 | 
			
		||||
					tmpname = tmpitem["title"]
 | 
			
		||||
					if len(tmpname) > 8:
 | 
			
		||||
						tmpname = tmpname[0:8]
 | 
			
		||||
					oled_writetext(tmpname, 0, yoffset, fontwdSml)
 | 
			
		||||
 | 
			
		||||
					tmpmax = tmpmax - 1
 | 
			
		||||
					yoffset = yoffset + 16
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			else:
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
 | 
			
		||||
		elif curscreen == "raid":
 | 
			
		||||
			# Raid Info
 | 
			
		||||
			if len(curlist) == 0:
 | 
			
		||||
				try:
 | 
			
		||||
					tmpobj = argonsysinfo_listraid()
 | 
			
		||||
					curlist = tmpobj['raidlist']
 | 
			
		||||
				except:
 | 
			
		||||
					curlist = []
 | 
			
		||||
			if len(curlist) > 0:
 | 
			
		||||
				oled_loadbg("bgraid")
 | 
			
		||||
				tmpitem = curlist.pop(0)
 | 
			
		||||
				oled_writetextaligned(tmpitem["title"], 0, 0, stdleftoffset, 1, fontwdSml)
 | 
			
		||||
				oled_writetextaligned(tmpitem["value"], 0, 8, stdleftoffset, 1, fontwdSml)
 | 
			
		||||
				oled_writetextaligned(argonsysinfo_kbstr(tmpitem["info"]["size"]), 0, 56, stdleftoffset, 1, fontwdSml)
 | 
			
		||||
 | 
			
		||||
				if len(tmpitem['info']['state']) > 0:
 | 
			
		||||
					oled_writetext( tmpitem['info']['state'], stdleftoffset, 8, fontwdSml )
 | 
			
		||||
 | 
			
		||||
				if len(tmpitem['info']['rebuildstat']) > 0:
 | 
			
		||||
					oled_writetext("Rebuild:" + tmpitem['info']['rebuildstat'], stdleftoffset, 16, fontwdSml)
 | 
			
		||||
 | 
			
		||||
				# TODO: May need to use different method for each raid type (i.e. check raidlist['raidlist'][raidctr]['value'])
 | 
			
		||||
				#oled_writetext("Used:"+str(int(100*tmpitem["info"]["used"]/tmpitem["info"]["size"]))+"%", stdleftoffset, 24, fontwdSml)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				oled_writetext("Active:"+str(int(tmpitem["info"]["active"]))+"/"+str(int(tmpitem["info"]["devices"])), stdleftoffset, 32, fontwdSml)
 | 
			
		||||
				oled_writetext("Working:"+str(int(tmpitem["info"]["working"]))+"/"+str(int(tmpitem["info"]["devices"])), stdleftoffset, 40, fontwdSml)
 | 
			
		||||
				oled_writetext("Failed:"+str(int(tmpitem["info"]["failed"]))+"/"+str(int(tmpitem["info"]["devices"])), stdleftoffset, 48, fontwdSml)
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			else:
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
 | 
			
		||||
		elif curscreen == "ram":
 | 
			
		||||
			# RAM
 | 
			
		||||
			try:
 | 
			
		||||
				oled_loadbg("bgram")
 | 
			
		||||
				tmpraminfo = argonsysinfo_getram()
 | 
			
		||||
				oled_writetextaligned(tmpraminfo[0], stdleftoffset, 8, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
				oled_writetextaligned("of", stdleftoffset, 24, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
				oled_writetextaligned(tmpraminfo[1], stdleftoffset, 40, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			except:
 | 
			
		||||
				needsUpdate = False
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
		elif curscreen == "temp":
 | 
			
		||||
			# Temp
 | 
			
		||||
			try:
 | 
			
		||||
				oled_loadbg("bgtemp")
 | 
			
		||||
				hddtempctr = 0
 | 
			
		||||
				maxcval = 0
 | 
			
		||||
				mincval = 200
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				# Get min/max of hdd temp
 | 
			
		||||
				hddtempobj = argonsysinfo_gethddtemp()
 | 
			
		||||
				for curdev in hddtempobj:
 | 
			
		||||
					if hddtempobj[curdev] < mincval:
 | 
			
		||||
						mincval = hddtempobj[curdev]
 | 
			
		||||
					if hddtempobj[curdev] > maxcval:
 | 
			
		||||
						maxcval = hddtempobj[curdev]
 | 
			
		||||
					hddtempctr = hddtempctr + 1
 | 
			
		||||
 | 
			
		||||
				cpucval = argonsysinfo_getcputemp()
 | 
			
		||||
				if hddtempctr > 0:
 | 
			
		||||
					alltempobj = {"cpu": cpucval,"hdd min": mincval, "hdd max": maxcval}
 | 
			
		||||
					# Update max C val to CPU Temp if necessary
 | 
			
		||||
					if maxcval < cpucval:
 | 
			
		||||
						maxcval = cpucval
 | 
			
		||||
 | 
			
		||||
					displayrowht = 8
 | 
			
		||||
					displayrow = 8
 | 
			
		||||
					for curdev in alltempobj:
 | 
			
		||||
						if temperature == "C":
 | 
			
		||||
							# Celsius
 | 
			
		||||
							tmpstr = str(alltempobj[curdev])
 | 
			
		||||
							if len(tmpstr) > 4:
 | 
			
		||||
								tmpstr = tmpstr[0:4]
 | 
			
		||||
						else:
 | 
			
		||||
							# Fahrenheit
 | 
			
		||||
							tmpstr = str(32+9*(alltempobj[curdev])/5)
 | 
			
		||||
							if len(tmpstr) > 5:
 | 
			
		||||
								tmpstr = tmpstr[0:5]
 | 
			
		||||
						if len(curdev) <= 3:
 | 
			
		||||
							oled_writetext(curdev.upper()+": "+ tmpstr+ chr(167) +temperature, stdleftoffset, displayrow, fontwdSml)
 | 
			
		||||
 | 
			
		||||
						else:
 | 
			
		||||
							oled_writetext(curdev.upper()+":", stdleftoffset, displayrow, fontwdSml)
 | 
			
		||||
 | 
			
		||||
							oled_writetext("     "+ tmpstr+ chr(167) +temperature, stdleftoffset, displayrow+displayrowht, fontwdSml)
 | 
			
		||||
						displayrow = displayrow + displayrowht*2
 | 
			
		||||
				else:
 | 
			
		||||
					maxcval = cpucval
 | 
			
		||||
					if temperature == "C":
 | 
			
		||||
						# Celsius
 | 
			
		||||
						tmpstr = str(cpucval)
 | 
			
		||||
						if len(tmpstr) > 4:
 | 
			
		||||
							tmpstr = tmpstr[0:4]
 | 
			
		||||
					else:
 | 
			
		||||
						# Fahrenheit
 | 
			
		||||
						tmpstr = str(32+9*(cpucval)/5)
 | 
			
		||||
						if len(tmpstr) > 5:
 | 
			
		||||
							tmpstr = tmpstr[0:5]
 | 
			
		||||
 | 
			
		||||
					oled_writetextaligned(tmpstr+ chr(167) +temperature, stdleftoffset, 24, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
 | 
			
		||||
				# Temperature Bar: 40C is min, 80C is max
 | 
			
		||||
				maxht = 21
 | 
			
		||||
				barht = int(maxht*(maxcval-40)/40)
 | 
			
		||||
				if barht > maxht:
 | 
			
		||||
					barht = maxht
 | 
			
		||||
				elif barht < 1:
 | 
			
		||||
					barht = 1
 | 
			
		||||
				oled_drawfilledrectangle(24, 20+(maxht-barht), 3, barht, 2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			except:
 | 
			
		||||
				needsUpdate = False
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
		elif curscreen == "ip":
 | 
			
		||||
			# IP Address
 | 
			
		||||
			try:
 | 
			
		||||
				oled_loadbg("bgip")
 | 
			
		||||
				oled_writetextaligned(argonsysinfo_getip(), 0, 8, oledscreenwidth, 1, fontwdReg)
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			except:
 | 
			
		||||
				needsUpdate = False
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
		elif curscreen == "logo1v5":
 | 
			
		||||
			# Logo
 | 
			
		||||
			try:
 | 
			
		||||
				oled_loadbg("logo1v5")
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			except:
 | 
			
		||||
				needsUpdate = False
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
		else:
 | 
			
		||||
			try:
 | 
			
		||||
				oled_loadbg("bgtime")
 | 
			
		||||
				# Date and Time HH:MM
 | 
			
		||||
				curtime = datetime.datetime.now()
 | 
			
		||||
 | 
			
		||||
				# Month/Day
 | 
			
		||||
				outstr = str(curtime.day).strip()
 | 
			
		||||
				if len(outstr) < 2:
 | 
			
		||||
					outstr = " "+outstr
 | 
			
		||||
				outstr = monthlist[curtime.month-1]+outstr
 | 
			
		||||
				oled_writetextaligned(outstr, stdleftoffset, 8, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
 | 
			
		||||
				# Day of Week
 | 
			
		||||
				oled_writetextaligned(weekdaynamelist[curtime.weekday()], stdleftoffset, 24, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
 | 
			
		||||
				# Time
 | 
			
		||||
				outstr = str(curtime.minute).strip()
 | 
			
		||||
				if len(outstr) < 2:
 | 
			
		||||
					outstr = "0"+outstr
 | 
			
		||||
				outstr = str(curtime.hour)+":"+outstr
 | 
			
		||||
				if len(outstr) < 5:
 | 
			
		||||
					outstr = "0"+outstr
 | 
			
		||||
				oled_writetextaligned(outstr, stdleftoffset, 40, oledscreenwidth-stdleftoffset, 1, fontwdReg)
 | 
			
		||||
 | 
			
		||||
				needsUpdate = True
 | 
			
		||||
			except:
 | 
			
		||||
				needsUpdate = False
 | 
			
		||||
				# Next page due to error/no data
 | 
			
		||||
				screenjogflag = 1
 | 
			
		||||
 | 
			
		||||
		if needsUpdate == True:
 | 
			
		||||
			if screensavermode == False:
 | 
			
		||||
				# Update screen if not screen saver mode
 | 
			
		||||
				oled_power(True)
 | 
			
		||||
				oled_flushimage(prevscreen != curscreen)
 | 
			
		||||
				oled_reset()
 | 
			
		||||
 | 
			
		||||
			timeoutcounter = 0
 | 
			
		||||
			while timeoutcounter<screenjogtime or screenjogtime == 0:
 | 
			
		||||
				qdata = ""
 | 
			
		||||
				if readq.empty() == False:
 | 
			
		||||
					qdata = readq.get()
 | 
			
		||||
 | 
			
		||||
				if qdata == "OLEDSWITCH":
 | 
			
		||||
					# Trigger screen switch
 | 
			
		||||
					screenjogflag = 1
 | 
			
		||||
					# Reset Screen Saver
 | 
			
		||||
					screensavermode = False
 | 
			
		||||
					screensaverctr = 0
 | 
			
		||||
 | 
			
		||||
					break
 | 
			
		||||
				elif qdata == "OLEDSTOP":
 | 
			
		||||
					# End OLED Thread
 | 
			
		||||
					display_defaultimg()
 | 
			
		||||
					return
 | 
			
		||||
				else:
 | 
			
		||||
					screensaverctr = screensaverctr + 1
 | 
			
		||||
					if screensaversec <= screensaverctr and screensavermode == False:
 | 
			
		||||
						screensavermode = True
 | 
			
		||||
						oled_fill(0)
 | 
			
		||||
						oled_reset()
 | 
			
		||||
						oled_power(False)
 | 
			
		||||
 | 
			
		||||
					if timeoutcounter == 0:
 | 
			
		||||
						# Use 1 sec sleep get CPU usage
 | 
			
		||||
						cpuusagelist = argonsysinfo_listcpuusage(1)
 | 
			
		||||
					else:
 | 
			
		||||
						time.sleep(1)
 | 
			
		||||
 | 
			
		||||
					timeoutcounter = timeoutcounter + 1
 | 
			
		||||
					if timeoutcounter >= 60 and screensavermode == False:
 | 
			
		||||
						# Refresh data every minute, unless screensaver got triggered
 | 
			
		||||
						screenjogflag = 0
 | 
			
		||||
						break
 | 
			
		||||
	display_defaultimg()
 | 
			
		||||
 | 
			
		||||
def display_defaultimg():
 | 
			
		||||
	# Load default image
 | 
			
		||||
	#oled_power(True)
 | 
			
		||||
	#oled_loadbg("bgdefault")
 | 
			
		||||
	#oled_flushimage()
 | 
			
		||||
	oled_fill(0)
 | 
			
		||||
	oled_reset()
 | 
			
		||||
 | 
			
		||||
if len(sys.argv) > 1:
 | 
			
		||||
	cmd = sys.argv[1].upper()
 | 
			
		||||
	if cmd == "SHUTDOWN":
 | 
			
		||||
		# Signal poweroff
 | 
			
		||||
		argonregister_signalpoweroff(bus)
 | 
			
		||||
 | 
			
		||||
	elif cmd == "FANOFF":
 | 
			
		||||
		# Turn off fan
 | 
			
		||||
		argonregister_setfanspeed(bus,0)
 | 
			
		||||
 | 
			
		||||
		if OLED_ENABLED == True:
 | 
			
		||||
			display_defaultimg()
 | 
			
		||||
 | 
			
		||||
	elif cmd == "SERVICE":
 | 
			
		||||
		# Starts the power button and temperature monitor threads
 | 
			
		||||
		try:
 | 
			
		||||
			ipcq = Queue()
 | 
			
		||||
			if len(sys.argv) > 2:
 | 
			
		||||
				cmd = sys.argv[2].upper()
 | 
			
		||||
			if cmd == "OLEDSWITCH":
 | 
			
		||||
				t1 = Thread(target = argonpowerbutton_monitorswitch, args =(ipcq, ))
 | 
			
		||||
			else:
 | 
			
		||||
				t1 = Thread(target = argonpowerbutton_monitor, args =(ipcq, ))
 | 
			
		||||
 | 
			
		||||
			t2 = Thread(target = temp_check)
 | 
			
		||||
			if OLED_ENABLED == True:
 | 
			
		||||
				t3 = Thread(target = display_loop, args =(ipcq, ))
 | 
			
		||||
 | 
			
		||||
			t1.start()
 | 
			
		||||
			t2.start()
 | 
			
		||||
			if OLED_ENABLED == True:
 | 
			
		||||
				t3.start()
 | 
			
		||||
 | 
			
		||||
			ipcq.join()
 | 
			
		||||
		except Exception:
 | 
			
		||||
			sys.exit(1)
 | 
			
		||||
							
								
								
									
										10
									
								
								source/scripts/argononed.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								source/scripts/argononed.service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Argon One Fan and Button Service
 | 
			
		||||
After=multi-user.target
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
RemainAfterExit=true
 | 
			
		||||
ExecStart=/usr/bin/python3 /etc/argon/argononed.py SERVICE
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
							
								
								
									
										333
									
								
								source/scripts/argononeoled.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										333
									
								
								source/scripts/argononeoled.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,333 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
from luma.core.interface.serial import i2c
 | 
			
		||||
from luma.oled.device import ssd1306
 | 
			
		||||
from PIL import Image
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import datetime
 | 
			
		||||
import math
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
# Initialize I2C Bus
 | 
			
		||||
import smbus
 | 
			
		||||
 | 
			
		||||
oledport=1
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
	bus=smbus.SMBus(1)
 | 
			
		||||
except Exception:
 | 
			
		||||
	try:
 | 
			
		||||
		oledport=0
 | 
			
		||||
		# Older version
 | 
			
		||||
		bus=smbus.SMBus(0)
 | 
			
		||||
	except Exception:
 | 
			
		||||
		print("Unable to detect i2c")
 | 
			
		||||
		bus=None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ADDR_OLED=0x3c
 | 
			
		||||
OLED_WD=1
 | 
			
		||||
OLED_HT=1
 | 
			
		||||
oled_device=None
 | 
			
		||||
try:
 | 
			
		||||
	oled_device=ssd1306(i2c(port=oledport, address=ADDR_OLED))
 | 
			
		||||
 | 
			
		||||
	OLED_WD=oled_device.bounding_box[2]+1
 | 
			
		||||
	OLED_HT=oled_device.bounding_box[3]+1
 | 
			
		||||
except Exception:
 | 
			
		||||
	print("Unable to initialize OLED")
 | 
			
		||||
	bus=None
 | 
			
		||||
 | 
			
		||||
OLED_NUMFONTCHAR=256
 | 
			
		||||
 | 
			
		||||
OLED_BUFFERIZE = ((OLED_WD*OLED_HT)>>3)
 | 
			
		||||
oled_imagebuffer = [0] * OLED_BUFFERIZE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_getmaxY():
 | 
			
		||||
	return OLED_HT
 | 
			
		||||
 | 
			
		||||
def oled_getmaxX():
 | 
			
		||||
	return OLED_WD
 | 
			
		||||
 | 
			
		||||
def oled_loadbg(bgname):
 | 
			
		||||
	if bgname == "bgblack":
 | 
			
		||||
		oled_clearbuffer()
 | 
			
		||||
		return
 | 
			
		||||
	elif bgname == "bgwhite":
 | 
			
		||||
		oled_clearbuffer(1)
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		file = open("/etc/argon/oled/"+bgname+".bin", "rb")
 | 
			
		||||
		bgbytes = list(file.read())
 | 
			
		||||
		file.close()
 | 
			
		||||
		ctr = len(bgbytes)
 | 
			
		||||
		if ctr == OLED_BUFFERIZE:
 | 
			
		||||
			oled_imagebuffer[:] = bgbytes
 | 
			
		||||
		elif ctr > OLED_BUFFERIZE:
 | 
			
		||||
			oled_imagebuffer[:] = bgbytes[0:OLED_BUFFERIZE]
 | 
			
		||||
		else:
 | 
			
		||||
			oled_imagebuffer[0:ctr] = bgbytes
 | 
			
		||||
			# Clear the rest of the buffer
 | 
			
		||||
			while ctr < OLED_BUFFERIZE:
 | 
			
		||||
				oled_imagebuffer[ctr] = 0
 | 
			
		||||
				ctr=ctr+1
 | 
			
		||||
	except FileNotFoundError:
 | 
			
		||||
		oled_clearbuffer()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_clearbuffer(value = 0):
 | 
			
		||||
	if value != 0:
 | 
			
		||||
		value = 0xff
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < OLED_BUFFERIZE:
 | 
			
		||||
		oled_imagebuffer[ctr] = value
 | 
			
		||||
		ctr=ctr+1
 | 
			
		||||
 | 
			
		||||
def oled_writebyterow(x,y,bytevalue, mode = 0):
 | 
			
		||||
	bufferoffset = OLED_WD*(y>>3) + x
 | 
			
		||||
	if mode == 0:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = bytevalue
 | 
			
		||||
	elif mode == 1:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = bytevalue^oled_imagebuffer[bufferoffset]
 | 
			
		||||
	else:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = bytevalue|oled_imagebuffer[bufferoffset]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_writebuffer(x,y,value, mode = 0):
 | 
			
		||||
 | 
			
		||||
	yoffset = y>>3
 | 
			
		||||
	yshift = y&0x7
 | 
			
		||||
	ybit = (1<<yshift)
 | 
			
		||||
 | 
			
		||||
	ymask = 0xFF^ybit
 | 
			
		||||
 | 
			
		||||
	if value != 0:
 | 
			
		||||
		value = ybit
 | 
			
		||||
 | 
			
		||||
	bufferoffset = OLED_WD*yoffset + x
 | 
			
		||||
 | 
			
		||||
	curval = oled_imagebuffer[bufferoffset]
 | 
			
		||||
	if mode & 1:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = curval^value
 | 
			
		||||
	else:
 | 
			
		||||
		oled_imagebuffer[bufferoffset] = curval&ymask|value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_fill(value):
 | 
			
		||||
	oled_clearbuffer(value)
 | 
			
		||||
	oled_flushimage()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_flushimage(hidescreen = True):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	if hidescreen == True:
 | 
			
		||||
		# Reset/Hide screen
 | 
			
		||||
		oled_power(False)
 | 
			
		||||
 | 
			
		||||
	tmplist = [0]*OLED_BUFFERIZE
 | 
			
		||||
 | 
			
		||||
	# Each byte = 1 col x 8 rows
 | 
			
		||||
 | 
			
		||||
	ymask = 0
 | 
			
		||||
	yidx = 0
 | 
			
		||||
	xmask = 0
 | 
			
		||||
	xidx = 0
 | 
			
		||||
	outbyte = 0
 | 
			
		||||
	srcidx = 0
 | 
			
		||||
	outoffsetidx = 0
 | 
			
		||||
	outyoffset = 0
 | 
			
		||||
	xoffset = 0
 | 
			
		||||
	while srcidx < OLED_BUFFERIZE:
 | 
			
		||||
		# OLED_WDx8 pixels at a time, y in reverse bit order
 | 
			
		||||
		outyoffset = 0
 | 
			
		||||
		yidx = 0
 | 
			
		||||
		ymask = 1
 | 
			
		||||
		while yidx < 8:
 | 
			
		||||
 | 
			
		||||
			outoffsetidx = 0
 | 
			
		||||
			outbyte = 0
 | 
			
		||||
			xmask = 0x80
 | 
			
		||||
			xidx = 0
 | 
			
		||||
 | 
			
		||||
			xoffset = 0
 | 
			
		||||
			while xoffset < OLED_WD:
 | 
			
		||||
				if oled_imagebuffer[srcidx+xoffset] & ymask:
 | 
			
		||||
					outbyte = outbyte | xmask
 | 
			
		||||
				xmask = xmask >> 1
 | 
			
		||||
				xidx = xidx + 1
 | 
			
		||||
				if xidx >= 8:
 | 
			
		||||
					tmplist[srcidx+outoffsetidx + outyoffset] = outbyte
 | 
			
		||||
					xmask = 0x80
 | 
			
		||||
					xidx = 0
 | 
			
		||||
					outbyte = 0
 | 
			
		||||
					outoffsetidx = outoffsetidx + 1
 | 
			
		||||
 | 
			
		||||
				xoffset = xoffset + 1
 | 
			
		||||
 | 
			
		||||
			outyoffset = outyoffset + (OLED_WD>>3)
 | 
			
		||||
			yidx = yidx + 1
 | 
			
		||||
			ymask = ymask << 1
 | 
			
		||||
 | 
			
		||||
		srcidx = srcidx + OLED_WD
 | 
			
		||||
 | 
			
		||||
	oled_device.display(Image.frombytes("1", [OLED_WD, OLED_HT], bytes(tmplist)))
 | 
			
		||||
 | 
			
		||||
	if hidescreen == True:
 | 
			
		||||
		# Display
 | 
			
		||||
		oled_power(True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_drawfilledrectangle(x, y, wd, ht, mode = 0):
 | 
			
		||||
	ymax = y + ht
 | 
			
		||||
	cury = y&0xF8
 | 
			
		||||
 | 
			
		||||
	xmax = x + wd
 | 
			
		||||
	curx = x
 | 
			
		||||
	if ((y & 0x7)) != 0:
 | 
			
		||||
		yshift = y&0x7
 | 
			
		||||
		bytevalue = (0xFF<<yshift)&0xFF
 | 
			
		||||
 | 
			
		||||
		# If 8 no additional masking needed
 | 
			
		||||
		if ymax-cury  < 8:
 | 
			
		||||
			yshift = 8-((ymax-cury)&0x7)
 | 
			
		||||
			bytevalue = bytevalue & (0xFF>>yshift)
 | 
			
		||||
 | 
			
		||||
		while curx < xmax:
 | 
			
		||||
			oled_writebyterow(curx,cury,bytevalue, mode)
 | 
			
		||||
			curx = curx + 1
 | 
			
		||||
		cury = cury + 8
 | 
			
		||||
	# Draw 8 rows at a time when possible
 | 
			
		||||
	while cury + 8 < ymax:
 | 
			
		||||
		curx = x
 | 
			
		||||
		while curx < xmax:
 | 
			
		||||
			oled_writebyterow(curx,cury,0xFF, mode)
 | 
			
		||||
			curx = curx + 1
 | 
			
		||||
		cury = cury + 8
 | 
			
		||||
 | 
			
		||||
	if cury < ymax:
 | 
			
		||||
		yshift = 8-((ymax-cury)&0x7)
 | 
			
		||||
		bytevalue = (0xFF>>yshift)
 | 
			
		||||
 | 
			
		||||
		curx = x
 | 
			
		||||
		while curx < xmax:
 | 
			
		||||
			oled_writebyterow(curx,cury,bytevalue, mode)
 | 
			
		||||
			curx = curx + 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_writetextaligned(textdata, x, y, boxwidth, alignmode, charwd = 6, mode = 0):
 | 
			
		||||
	leftoffset = 0
 | 
			
		||||
	if alignmode == 1:
 | 
			
		||||
		# Centered
 | 
			
		||||
		leftoffset = (boxwidth-len(textdata)*charwd)>>1
 | 
			
		||||
	elif alignmode == 2:
 | 
			
		||||
		# Right aligned
 | 
			
		||||
		leftoffset = (boxwidth-len(textdata)*charwd)
 | 
			
		||||
 | 
			
		||||
	oled_writetext(textdata, x+leftoffset, y, charwd, mode)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_writetext(textdata, x, y, charwd = 6, mode = 0):
 | 
			
		||||
	if charwd < 6:
 | 
			
		||||
		charwd = 6
 | 
			
		||||
 | 
			
		||||
	charht = int((charwd<<3)/6)
 | 
			
		||||
	if charht & 0x7:
 | 
			
		||||
		charht = (charht&0xF8) + 8
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		file = open("/etc/argon/oled/font"+str(charht)+"x"+str(charwd)+".bin", "rb")
 | 
			
		||||
		fontbytes = list(file.read())
 | 
			
		||||
		file.close()
 | 
			
		||||
	except FileNotFoundError:
 | 
			
		||||
		try:
 | 
			
		||||
			# Default to smallest
 | 
			
		||||
			file = open("/etc/argon/oled/font8x6.bin", "rb")
 | 
			
		||||
			fontbytes = list(file.read())
 | 
			
		||||
			file.close()
 | 
			
		||||
		except FileNotFoundError:
 | 
			
		||||
			return
 | 
			
		||||
 | 
			
		||||
	if ((y & 0x7)) == 0:
 | 
			
		||||
		# Use optimized loading
 | 
			
		||||
		oled_fastwritetext(textdata, x, y, charht, charwd, fontbytes, mode)
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	numfontrow = charht>>3
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < len(textdata):
 | 
			
		||||
		fontoffset = ord(textdata[ctr])*charwd
 | 
			
		||||
		fontcol = 0
 | 
			
		||||
		while fontcol < charwd and x < OLED_WD:
 | 
			
		||||
			fontrow = 0
 | 
			
		||||
			row = y
 | 
			
		||||
			while fontrow < numfontrow and row < OLED_HT and x >= 0:
 | 
			
		||||
				curbit = 0x80
 | 
			
		||||
				curbyte = (fontbytes[fontoffset + fontcol + (OLED_NUMFONTCHAR*charwd*fontrow)])
 | 
			
		||||
				subrow = 0
 | 
			
		||||
				while subrow < 8 and row < OLED_HT:
 | 
			
		||||
					value = 0
 | 
			
		||||
					if (curbyte&curbit) != 0:
 | 
			
		||||
						value = 1
 | 
			
		||||
					oled_writebuffer(x,row,value, mode)
 | 
			
		||||
					curbit = curbit >> 1
 | 
			
		||||
					row = row + 1
 | 
			
		||||
					subrow = subrow + 1
 | 
			
		||||
				fontrow = fontrow + 1
 | 
			
		||||
			fontcol = fontcol + 1
 | 
			
		||||
			x = x + 1
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
 | 
			
		||||
def oled_fastwritetext(textdata, x, y, charht, charwd, fontbytes, mode = 0):
 | 
			
		||||
 | 
			
		||||
	numfontrow = charht>>3
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < len(textdata):
 | 
			
		||||
		fontoffset = ord(textdata[ctr])*charwd
 | 
			
		||||
		fontcol = 0
 | 
			
		||||
		while fontcol < charwd and x < OLED_WD:
 | 
			
		||||
			fontrow = 0
 | 
			
		||||
			row = y&0xF8
 | 
			
		||||
			while fontrow < numfontrow and row < OLED_HT and x >= 0:
 | 
			
		||||
				curbyte = (fontbytes[fontoffset + fontcol + (OLED_NUMFONTCHAR*charwd*fontrow)])
 | 
			
		||||
				oled_writebyterow(x,row,curbyte, mode)
 | 
			
		||||
				fontrow = fontrow + 1
 | 
			
		||||
				row = row + 8
 | 
			
		||||
			fontcol = fontcol + 1
 | 
			
		||||
			x = x + 1
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_power(turnon = True):
 | 
			
		||||
	if bus is None:
 | 
			
		||||
		return
 | 
			
		||||
	try:
 | 
			
		||||
		if turnon == True:
 | 
			
		||||
			oled_device.show()
 | 
			
		||||
		else:
 | 
			
		||||
			oled_device.hide()
 | 
			
		||||
	except:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_inverse(enable = True):
 | 
			
		||||
	# Not supported?
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_fullwhite(enable = True):
 | 
			
		||||
	# Not supported?
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def oled_reset():
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								source/scripts/argononeoledd.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								source/scripts/argononeoledd.service
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Argon One Fan and Button Service
 | 
			
		||||
After=multi-user.target
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
Restart=always
 | 
			
		||||
RemainAfterExit=true
 | 
			
		||||
ExecStart=/usr/bin/python3 /etc/argon/argononed.py SERVICE OLEDSWITCH
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
							
								
								
									
										89
									
								
								source/scripts/argonpowerbutton-libgpiod.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								source/scripts/argonpowerbutton-libgpiod.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
			
		||||
 | 
			
		||||
# For Libreelec/Lakka, note that we need to add system paths
 | 
			
		||||
# import sys
 | 
			
		||||
# sys.path.append('/storage/.kodi/addons/virtual.rpi-tools/lib')
 | 
			
		||||
import gpiod
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
# This function is the thread that monitors activity in our shutdown pin
 | 
			
		||||
# The pulse width is measured, and the corresponding shell command will be issued
 | 
			
		||||
 | 
			
		||||
def argonpowerbutton_monitor(writeq):
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		# Reference https://github.com/brgl/libgpiod/blob/master/bindings/python/examples/gpiomon.py
 | 
			
		||||
 | 
			
		||||
		# Pin Assignments
 | 
			
		||||
		LINE_SHUTDOWN=4
 | 
			
		||||
		try:
 | 
			
		||||
			# Pi5 mapping
 | 
			
		||||
			chip = gpiod.Chip('4')
 | 
			
		||||
		except Exception as gpioerr:
 | 
			
		||||
			# Old mapping
 | 
			
		||||
			chip = gpiod.Chip('0')
 | 
			
		||||
 | 
			
		||||
		lineobj = chip.get_line(LINE_SHUTDOWN)
 | 
			
		||||
		lineobj.request(consumer="argon", type=gpiod.LINE_REQ_EV_BOTH_EDGES)
 | 
			
		||||
		while True:
 | 
			
		||||
			hasevent = lineobj.event_wait(10)
 | 
			
		||||
			if hasevent:
 | 
			
		||||
				pulsetime = 1
 | 
			
		||||
				eventdata = lineobj.event_read()
 | 
			
		||||
				if eventdata.type == gpiod.LineEvent.RISING_EDGE:
 | 
			
		||||
					# Time pulse data
 | 
			
		||||
					while lineobj.get_value() == 1:
 | 
			
		||||
						time.sleep(0.01)
 | 
			
		||||
						pulsetime += 1
 | 
			
		||||
 | 
			
		||||
					if pulsetime >=2 and pulsetime <=3:
 | 
			
		||||
						# Testing
 | 
			
		||||
						#writeq.put("OLEDSWITCH")
 | 
			
		||||
						writeq.put("OLEDSTOP")
 | 
			
		||||
						os.system("reboot")
 | 
			
		||||
						break
 | 
			
		||||
					elif pulsetime >=4 and pulsetime <=5:
 | 
			
		||||
						writeq.put("OLEDSTOP")
 | 
			
		||||
						os.system("shutdown now -h")
 | 
			
		||||
						break
 | 
			
		||||
					elif pulsetime >=6 and pulsetime <=7:
 | 
			
		||||
						writeq.put("OLEDSWITCH")
 | 
			
		||||
		lineobj.release()
 | 
			
		||||
		chip.close()
 | 
			
		||||
	except Exception:
 | 
			
		||||
		writeq.put("ERROR")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonpowerbutton_monitorswitch(writeq):
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		# Reference https://github.com/brgl/libgpiod/blob/master/bindings/python/examples/gpiomon.py
 | 
			
		||||
 | 
			
		||||
		# Pin Assignments
 | 
			
		||||
		LINE_SHUTDOWN=4
 | 
			
		||||
		try:
 | 
			
		||||
			# Pi5 mapping
 | 
			
		||||
			chip = gpiod.Chip('4')
 | 
			
		||||
		except Exception as gpioerr:
 | 
			
		||||
			# Old mapping
 | 
			
		||||
			chip = gpiod.Chip('0')
 | 
			
		||||
 | 
			
		||||
		lineobj = chip.get_line(LINE_SHUTDOWN)
 | 
			
		||||
		lineobj.request(consumer="argon", type=gpiod.LINE_REQ_EV_BOTH_EDGES)
 | 
			
		||||
		while True:
 | 
			
		||||
			hasevent = lineobj.event_wait(10)
 | 
			
		||||
			if hasevent:
 | 
			
		||||
				pulsetime = 1
 | 
			
		||||
				eventdata = lineobj.event_read()
 | 
			
		||||
				if eventdata.type == gpiod.LineEvent.RISING_EDGE:
 | 
			
		||||
					# Time pulse data
 | 
			
		||||
					while lineobj.get_value() == 1:
 | 
			
		||||
						time.sleep(0.01)
 | 
			
		||||
						pulsetime += 1
 | 
			
		||||
 | 
			
		||||
					if pulsetime >= 10:
 | 
			
		||||
						writeq.put("OLEDSWITCH")
 | 
			
		||||
		lineobj.release()
 | 
			
		||||
		chip.close()
 | 
			
		||||
	except Exception:
 | 
			
		||||
		writeq.put("ERROR")
 | 
			
		||||
							
								
								
									
										66
									
								
								source/scripts/argonpowerbutton-rpigpio.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								source/scripts/argonpowerbutton-rpigpio.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
 | 
			
		||||
# For Libreelec/Lakka, note that we need to add system paths
 | 
			
		||||
# import sys
 | 
			
		||||
# sys.path.append('/storage/.kodi/addons/virtual.rpi-tools/lib')
 | 
			
		||||
import RPi.GPIO as GPIO
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
# This function is the thread that monitors activity in our shutdown pin
 | 
			
		||||
# The pulse width is measured, and the corresponding shell command will be issued
 | 
			
		||||
 | 
			
		||||
def argonpowerbutton_monitor(writeq):
 | 
			
		||||
	try:
 | 
			
		||||
		# Pin Assignments
 | 
			
		||||
		PIN_SHUTDOWN=4
 | 
			
		||||
 | 
			
		||||
		GPIO.setwarnings(False)
 | 
			
		||||
		GPIO.setmode(GPIO.BCM)
 | 
			
		||||
		GPIO.setup(PIN_SHUTDOWN, GPIO.IN,  pull_up_down=GPIO.PUD_DOWN)
 | 
			
		||||
 | 
			
		||||
		while True:
 | 
			
		||||
			pulsetime = 1
 | 
			
		||||
			GPIO.wait_for_edge(PIN_SHUTDOWN, GPIO.RISING)
 | 
			
		||||
			time.sleep(0.01)
 | 
			
		||||
			while GPIO.input(PIN_SHUTDOWN) == GPIO.HIGH:
 | 
			
		||||
				time.sleep(0.01)
 | 
			
		||||
				pulsetime += 1
 | 
			
		||||
			if pulsetime >=2 and pulsetime <=3:
 | 
			
		||||
				# Testing
 | 
			
		||||
				#writeq.put("OLEDSWITCH")
 | 
			
		||||
				writeq.put("OLEDSTOP")
 | 
			
		||||
				os.system("reboot")
 | 
			
		||||
				break
 | 
			
		||||
			elif pulsetime >=4 and pulsetime <=5:
 | 
			
		||||
				writeq.put("OLEDSTOP")
 | 
			
		||||
				os.system("shutdown now -h")
 | 
			
		||||
				break
 | 
			
		||||
			elif pulsetime >=6 and pulsetime <=7:
 | 
			
		||||
				writeq.put("OLEDSWITCH")
 | 
			
		||||
	except Exception:
 | 
			
		||||
		writeq.put("ERROR")
 | 
			
		||||
	GPIO.cleanup()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonpowerbutton_monitorswitch(writeq):
 | 
			
		||||
	try:
 | 
			
		||||
		# Pin Assignments
 | 
			
		||||
		PIN_SHUTDOWN=4
 | 
			
		||||
 | 
			
		||||
		GPIO.setwarnings(False)
 | 
			
		||||
		GPIO.setmode(GPIO.BCM)
 | 
			
		||||
		GPIO.setup(PIN_SHUTDOWN, GPIO.IN,  pull_up_down=GPIO.PUD_DOWN)
 | 
			
		||||
 | 
			
		||||
		while True:
 | 
			
		||||
			pulsetime = 1
 | 
			
		||||
			GPIO.wait_for_edge(PIN_SHUTDOWN, GPIO.RISING)
 | 
			
		||||
			time.sleep(0.01)
 | 
			
		||||
			while GPIO.input(PIN_SHUTDOWN) == GPIO.HIGH:
 | 
			
		||||
				time.sleep(0.01)
 | 
			
		||||
				pulsetime += 1
 | 
			
		||||
			if pulsetime >= 10:
 | 
			
		||||
				writeq.put("OLEDSWITCH")
 | 
			
		||||
	except Exception:
 | 
			
		||||
		writeq.put("ERROR")
 | 
			
		||||
	GPIO.cleanup()
 | 
			
		||||
							
								
								
									
										74
									
								
								source/scripts/argonregister-v1.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								source/scripts/argonregister-v1.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Argon Register Helper methods
 | 
			
		||||
# Same as argonregister, but no support for new register commands
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import time
 | 
			
		||||
import smbus
 | 
			
		||||
 | 
			
		||||
# I2C Addresses
 | 
			
		||||
ADDR_ARGONONEFAN=0x1a
 | 
			
		||||
ADDR_ARGONONEREG=ADDR_ARGONONEFAN
 | 
			
		||||
 | 
			
		||||
# ARGONONEREG Addresses
 | 
			
		||||
ADDR_ARGONONEREG_DUTYCYCLE=0x80
 | 
			
		||||
ADDR_ARGONONEREG_FW=0x81
 | 
			
		||||
ADDR_ARGONONEREG_IR=0x82
 | 
			
		||||
ADDR_ARGONONEREG_CTRL=0x86
 | 
			
		||||
 | 
			
		||||
# Initialize bus
 | 
			
		||||
def argonregister_initializebusobj():
 | 
			
		||||
	try:
 | 
			
		||||
		return smbus.SMBus(1)
 | 
			
		||||
	except Exception:
 | 
			
		||||
		try:
 | 
			
		||||
			# Older version
 | 
			
		||||
			return smbus.SMBus(0)
 | 
			
		||||
		except Exception:
 | 
			
		||||
			print("Unable to detect i2c")
 | 
			
		||||
			return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Checks if the FW supports control registers
 | 
			
		||||
def argonregister_checksupport(busobj):
 | 
			
		||||
	return False
 | 
			
		||||
 | 
			
		||||
def argonregister_getbyte(busobj, address):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return 0
 | 
			
		||||
	return busobj.read_byte_data(ADDR_ARGONONEREG, address)
 | 
			
		||||
 | 
			
		||||
def argonregister_setbyte(busobj, address, bytevalue):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
	busobj.write_byte_data(ADDR_ARGONONEREG,address,bytevalue)
 | 
			
		||||
	time.sleep(1)
 | 
			
		||||
 | 
			
		||||
def argonregister_getfanspeed(busobj, regsupport=None):
 | 
			
		||||
	return 0
 | 
			
		||||
 | 
			
		||||
def argonregister_setfanspeed(busobj, newspeed, regsupport=None):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	if newspeed > 100:
 | 
			
		||||
		newspeed = 100
 | 
			
		||||
	elif newspeed < 0:
 | 
			
		||||
		newspeed = 0
 | 
			
		||||
 | 
			
		||||
	busobj.write_byte(ADDR_ARGONONEFAN,newspeed)
 | 
			
		||||
	time.sleep(1)
 | 
			
		||||
 | 
			
		||||
def argonregister_signalpoweroff(busobj):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	busobj.write_byte(ADDR_ARGONONEFAN,0xFF)
 | 
			
		||||
 | 
			
		||||
def argonregister_setircode(busobj, vallist):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	busobj.write_i2c_block_data(ADDR_ARGONONEREG, ADDR_ARGONONEREG_IR, vallist)
 | 
			
		||||
							
								
								
									
										109
									
								
								source/scripts/argonregister.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								source/scripts/argonregister.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Argon Register Helper methods
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import time
 | 
			
		||||
import smbus
 | 
			
		||||
 | 
			
		||||
# I2C Addresses
 | 
			
		||||
ADDR_ARGONONEFAN=0x1a
 | 
			
		||||
ADDR_ARGONONEREG=ADDR_ARGONONEFAN
 | 
			
		||||
 | 
			
		||||
# ARGONONEREG Addresses
 | 
			
		||||
ADDR_ARGONONEREG_DUTYCYCLE=0x80
 | 
			
		||||
ADDR_ARGONONEREG_FW=0x81
 | 
			
		||||
ADDR_ARGONONEREG_IR=0x82
 | 
			
		||||
ADDR_ARGONONEREG_CTRL=0x86
 | 
			
		||||
 | 
			
		||||
# Initialize bus
 | 
			
		||||
def argonregister_initializebusobj():
 | 
			
		||||
	try:
 | 
			
		||||
		return smbus.SMBus(1)
 | 
			
		||||
	except Exception:
 | 
			
		||||
		try:
 | 
			
		||||
			# Older version
 | 
			
		||||
			return smbus.SMBus(0)
 | 
			
		||||
		except Exception:
 | 
			
		||||
			print("Unable to detect i2c")
 | 
			
		||||
			return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Checks if the FW supports control registers
 | 
			
		||||
def argonregister_checksupport(busobj):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return False
 | 
			
		||||
	try:
 | 
			
		||||
		oldval = argonregister_getbyte(busobj, ADDR_ARGONONEREG_DUTYCYCLE)
 | 
			
		||||
		newval = oldval + 1
 | 
			
		||||
		if newval >= 100:
 | 
			
		||||
			newval = 98
 | 
			
		||||
		argonregister_setbyte(busobj, ADDR_ARGONONEREG_DUTYCYCLE, newval)
 | 
			
		||||
		newval = argonregister_getbyte(busobj, ADDR_ARGONONEREG_DUTYCYCLE)
 | 
			
		||||
		if newval != oldval:
 | 
			
		||||
			argonregister_setbyte(busobj, ADDR_ARGONONEREG_DUTYCYCLE, oldval)
 | 
			
		||||
			return True
 | 
			
		||||
		return False
 | 
			
		||||
	except:
 | 
			
		||||
		return False
 | 
			
		||||
 | 
			
		||||
def argonregister_getbyte(busobj, address):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return 0
 | 
			
		||||
	return busobj.read_byte_data(ADDR_ARGONONEREG, address)
 | 
			
		||||
 | 
			
		||||
def argonregister_setbyte(busobj, address, bytevalue):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
	busobj.write_byte_data(ADDR_ARGONONEREG,address,bytevalue)
 | 
			
		||||
	time.sleep(1)
 | 
			
		||||
 | 
			
		||||
def argonregister_getfanspeed(busobj, regsupport=None):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
	usereg=False
 | 
			
		||||
	if regsupport is None:
 | 
			
		||||
		usereg=argonregister_checksupport(busobj)
 | 
			
		||||
	else:
 | 
			
		||||
		usereg=regsupport
 | 
			
		||||
	if usereg == True:
 | 
			
		||||
		return argonregister_getbyte(busobj, ADDR_ARGONONEREG_DUTYCYCLE)
 | 
			
		||||
	else:
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonregister_setfanspeed(busobj, newspeed, regsupport=None):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	if newspeed > 100:
 | 
			
		||||
		newspeed = 100
 | 
			
		||||
	elif newspeed < 0:
 | 
			
		||||
		newspeed = 0
 | 
			
		||||
	usereg=False
 | 
			
		||||
	if regsupport is None:
 | 
			
		||||
		usereg=argonregister_checksupport(busobj)
 | 
			
		||||
	else:
 | 
			
		||||
		usereg=regsupport
 | 
			
		||||
	if usereg == True:
 | 
			
		||||
		argonregister_setbyte(busobj, ADDR_ARGONONEREG_DUTYCYCLE, newspeed)
 | 
			
		||||
	else:
 | 
			
		||||
		busobj.write_byte(ADDR_ARGONONEFAN,newspeed)
 | 
			
		||||
		time.sleep(1)
 | 
			
		||||
 | 
			
		||||
def argonregister_signalpoweroff(busobj):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	if argonregister_checksupport(busobj):
 | 
			
		||||
		argonregister_setbyte(busobj, ADDR_ARGONONEREG_CTRL, 1)
 | 
			
		||||
	else:
 | 
			
		||||
		busobj.write_byte(ADDR_ARGONONEFAN,0xFF)
 | 
			
		||||
 | 
			
		||||
def argonregister_setircode(busobj, vallist):
 | 
			
		||||
	if busobj is None:
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	busobj.write_i2c_block_data(ADDR_ARGONONEREG, ADDR_ARGONONEREG_IR, vallist)
 | 
			
		||||
							
								
								
									
										642
									
								
								source/scripts/argonrtc.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										642
									
								
								source/scripts/argonrtc.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,642 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import datetime
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Describe Methods
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Helper method to add proper suffix to numbers
 | 
			
		||||
def getNumberSuffix(numval):
 | 
			
		||||
	onesvalue = numval % 10
 | 
			
		||||
	if onesvalue == 1:
 | 
			
		||||
		return "st"
 | 
			
		||||
	elif onesvalue == 2:
 | 
			
		||||
		return "nd"
 | 
			
		||||
	elif onesvalue == 3:
 | 
			
		||||
		return "rd"
 | 
			
		||||
	return "th"
 | 
			
		||||
 | 
			
		||||
def describeHourMinute(hour, minute):
 | 
			
		||||
	if hour < 0:
 | 
			
		||||
		return ""
 | 
			
		||||
	outstr = ""
 | 
			
		||||
	ampmstr = ""
 | 
			
		||||
	if hour <= 0:
 | 
			
		||||
		hour = 0
 | 
			
		||||
		outstr = outstr + "12"
 | 
			
		||||
		ampmstr = "am"
 | 
			
		||||
	elif hour <= 12:
 | 
			
		||||
		outstr = outstr + str(hour)
 | 
			
		||||
		if hour == 12:
 | 
			
		||||
			ampmstr = "pm"
 | 
			
		||||
		else:
 | 
			
		||||
			ampmstr = "am"
 | 
			
		||||
	else:
 | 
			
		||||
		outstr = outstr + str(hour-12)
 | 
			
		||||
		ampmstr = "pm"
 | 
			
		||||
 | 
			
		||||
	if minute >= 10:
 | 
			
		||||
		outstr = outstr+":"
 | 
			
		||||
	elif minute > 0:
 | 
			
		||||
		outstr = outstr+":0"
 | 
			
		||||
	else:
 | 
			
		||||
		if hour == 0:
 | 
			
		||||
			ampmstr = "mn"
 | 
			
		||||
		elif hour == 12:
 | 
			
		||||
			ampmstr = "nn"
 | 
			
		||||
		return outstr+ampmstr
 | 
			
		||||
 | 
			
		||||
	if minute <= 0:
 | 
			
		||||
		minute = 0
 | 
			
		||||
	outstr = outstr+str(minute)
 | 
			
		||||
 | 
			
		||||
	return outstr+ampmstr
 | 
			
		||||
 | 
			
		||||
# Describe Schedule Parameter Values
 | 
			
		||||
def describeSchedule(monthlist, weekdaylist, datelist, hourlist, minutelist):
 | 
			
		||||
	weekdaynamelist = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
 | 
			
		||||
	monthnamelist = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
 | 
			
		||||
 | 
			
		||||
	curprefix = ""
 | 
			
		||||
	hasDate = False
 | 
			
		||||
	hasMonth = False
 | 
			
		||||
	foundvalue = False
 | 
			
		||||
	monthdatestr = ""
 | 
			
		||||
	for curmonth in monthlist:
 | 
			
		||||
		for curdate in datelist:
 | 
			
		||||
			if curdate >= 0:
 | 
			
		||||
				hasDate = True
 | 
			
		||||
				if curmonth >= 0:
 | 
			
		||||
					hasMonth = True
 | 
			
		||||
					monthdatestr = monthdatestr + "," + monthnamelist[curmonth-1]+" "+str(curdate) + getNumberSuffix(curdate)
 | 
			
		||||
				else:
 | 
			
		||||
					monthdatestr = monthdatestr + ","+str(curdate) + getNumberSuffix(curdate)
 | 
			
		||||
			else:
 | 
			
		||||
				if curmonth >= 0:
 | 
			
		||||
					monthdatestr = monthdatestr + "," + monthnamelist[curmonth-1]
 | 
			
		||||
 | 
			
		||||
	if len(monthdatestr) > 0:
 | 
			
		||||
		foundvalue = True
 | 
			
		||||
		# Remove Leading Comma
 | 
			
		||||
		monthdatestr = monthdatestr[1:]
 | 
			
		||||
		if hasMonth == True:
 | 
			
		||||
			curprefix = "Annually:"
 | 
			
		||||
		else:
 | 
			
		||||
			curprefix = "Monthly:"
 | 
			
		||||
			monthdatestr = monthdatestr + " of the Month"
 | 
			
		||||
		monthdatestr = " Every "+monthdatestr
 | 
			
		||||
 | 
			
		||||
	weekdaystr = ""
 | 
			
		||||
	for curweekday in weekdaylist:
 | 
			
		||||
		if curweekday >= 0:
 | 
			
		||||
			hasDate = True
 | 
			
		||||
			weekdaystr = weekdaystr + "," + weekdaynamelist[curweekday]
 | 
			
		||||
 | 
			
		||||
	if len(weekdaystr) > 0:
 | 
			
		||||
		foundvalue = True
 | 
			
		||||
		# Remove Leading Comma
 | 
			
		||||
		weekdaystr = weekdaystr[1:]
 | 
			
		||||
		if len(curprefix) == 0:
 | 
			
		||||
			curprefix = "Weekly:"
 | 
			
		||||
			weekdaystr = " on " + weekdaystr
 | 
			
		||||
		else:
 | 
			
		||||
			weekdaystr = ",on " + weekdaystr
 | 
			
		||||
 | 
			
		||||
	hasHour = False
 | 
			
		||||
	hasMinute = False
 | 
			
		||||
	hourminstr = ""
 | 
			
		||||
	for curhour in hourlist:
 | 
			
		||||
		for curminute in minutelist:
 | 
			
		||||
			if curhour >= 0:
 | 
			
		||||
				hasHour = True
 | 
			
		||||
				if curminute >= 0:
 | 
			
		||||
					hasMinute = True
 | 
			
		||||
				hourminstr = hourminstr + "," + describeHourMinute(curhour, curminute)
 | 
			
		||||
			elif curminute >= 0:
 | 
			
		||||
				hasMinute = True
 | 
			
		||||
				hourminstr = hourminstr + "," + str(curminute) + getNumberSuffix(curminute)
 | 
			
		||||
 | 
			
		||||
	if len(hourminstr) > 0:
 | 
			
		||||
		foundvalue = True
 | 
			
		||||
		# Remove Leading Comma
 | 
			
		||||
		hourminstr = hourminstr[1:]
 | 
			
		||||
		if hasHour == True:
 | 
			
		||||
			if hasDate == True:
 | 
			
		||||
				hourminstr = "at " + hourminstr
 | 
			
		||||
			else:
 | 
			
		||||
				hourminstr = "Daily: " + hourminstr
 | 
			
		||||
			if hasMinute == False:
 | 
			
		||||
				hourminstr = hourminstr + " every minute"
 | 
			
		||||
		else:
 | 
			
		||||
			if hourminstr == "0":
 | 
			
		||||
				hourminstr = "At the start of every hour"
 | 
			
		||||
			else:
 | 
			
		||||
				hourminstr = "Hourly: At " + hourminstr + " minute"
 | 
			
		||||
	else:
 | 
			
		||||
		hourminstr = "Every minute"
 | 
			
		||||
 | 
			
		||||
	if len(curprefix) > 0:
 | 
			
		||||
		hourminstr = ","+hourminstr
 | 
			
		||||
 | 
			
		||||
	return (curprefix + monthdatestr + weekdaystr + hourminstr).strip()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Alarm
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Alarm to UTC/Local time
 | 
			
		||||
def convertAlarmTimezone(weekday, caldate, hour, minute, toutc):
 | 
			
		||||
	utcdiffsec = getLocaltimeOffset().seconds
 | 
			
		||||
	if toutc == False:
 | 
			
		||||
		utcdiffsec = utcdiffsec*(-1)
 | 
			
		||||
 | 
			
		||||
	utcdiffsec = utcdiffsec - (utcdiffsec%60)
 | 
			
		||||
	utcdiffmin = utcdiffsec % 3600
 | 
			
		||||
	utcdiffhour = int((utcdiffsec - utcdiffmin)/3600)
 | 
			
		||||
	utcdiffmin = int(utcdiffmin/60)
 | 
			
		||||
 | 
			
		||||
	addhour = 0
 | 
			
		||||
	if minute >= 0:
 | 
			
		||||
		minute = minute - utcdiffmin
 | 
			
		||||
		if minute < 0:
 | 
			
		||||
			addhour = -1
 | 
			
		||||
			minute = minute + 60
 | 
			
		||||
		elif minute > 59:
 | 
			
		||||
			addhour = 1
 | 
			
		||||
			minute = minute - 60
 | 
			
		||||
 | 
			
		||||
	addday = 0
 | 
			
		||||
	if hour >= 0:
 | 
			
		||||
		hour = hour - utcdiffhour
 | 
			
		||||
		tmphour = hour + addhour
 | 
			
		||||
		if hour < 0:
 | 
			
		||||
			hour = hour + 24
 | 
			
		||||
		elif hour > 23:
 | 
			
		||||
			hour = hour - 24
 | 
			
		||||
		if tmphour < 0:
 | 
			
		||||
			addday = -1
 | 
			
		||||
		elif tmphour > 23:
 | 
			
		||||
			addday = 1
 | 
			
		||||
 | 
			
		||||
	if addday != 0:
 | 
			
		||||
		if weekday >= 0:
 | 
			
		||||
			weekday = weekday + addday
 | 
			
		||||
			if weekday < 0:
 | 
			
		||||
				weekday = weekday + 7
 | 
			
		||||
			elif weekday > 6:
 | 
			
		||||
				weekday = weekday - 7
 | 
			
		||||
		if caldate > 0:
 | 
			
		||||
			# Edge cases might not be handled properly though
 | 
			
		||||
			curtime = datetime.datetime.now()
 | 
			
		||||
			maxmonthdate = getLastMonthDate(curtime.year, curtime.month)
 | 
			
		||||
			caldate = caldate + addday
 | 
			
		||||
			if caldate == 0:
 | 
			
		||||
				# move to end of the month
 | 
			
		||||
				caldate = maxmonthdate
 | 
			
		||||
			elif caldate > maxmonthdate:
 | 
			
		||||
				# move to next month
 | 
			
		||||
				caldate = 1
 | 
			
		||||
 | 
			
		||||
	return [weekday, caldate, hour, minute]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Get RTC Alarm Setting (Negative values ignored)
 | 
			
		||||
def getRTCAlarm(weekday, caldate, hour, minute):
 | 
			
		||||
	hasError = False
 | 
			
		||||
	if caldate < 1 and weekday < 0 and hour < 0 and minute < 0:
 | 
			
		||||
		hasError = True
 | 
			
		||||
	elif minute > 59:
 | 
			
		||||
		hasError = True
 | 
			
		||||
	elif hour > 23:
 | 
			
		||||
		hasError = True
 | 
			
		||||
	elif weekday > 6:
 | 
			
		||||
		hasError = True
 | 
			
		||||
	elif caldate > 31:
 | 
			
		||||
		hasError = True
 | 
			
		||||
 | 
			
		||||
	if hasError == True:
 | 
			
		||||
		return [-1, -1, -1, -1]
 | 
			
		||||
	# Convert to UTC
 | 
			
		||||
	return convertAlarmTimezone(weekday, caldate, hour, minute, True)
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Date/Time tools
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Get local time vs UTC
 | 
			
		||||
def getLocaltimeOffset():
 | 
			
		||||
	localdatetime = datetime.datetime.now()
 | 
			
		||||
	utcdatetime = datetime.datetime.fromtimestamp(localdatetime.timestamp(), datetime.timezone.utc)
 | 
			
		||||
	# Remove TZ info to allow subtraction
 | 
			
		||||
	utcdatetime = utcdatetime.replace(tzinfo = None)
 | 
			
		||||
 | 
			
		||||
	return localdatetime - utcdatetime
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Sync Time to RTC Time (for Daemon use)
 | 
			
		||||
def updateSystemTime(rtctime):
 | 
			
		||||
	os.system("date -s '"+rtctime.isoformat()+"' >/dev/null 2>&1")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#########
 | 
			
		||||
# Config
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
# Load config value as array of integers
 | 
			
		||||
def getConfigValue(valuestr):
 | 
			
		||||
	try:
 | 
			
		||||
		if valuestr == "*":
 | 
			
		||||
			return [-1]
 | 
			
		||||
		tmplist = valuestr.split(",")
 | 
			
		||||
		map_object = map(int, tmplist)
 | 
			
		||||
		return list(map_object)
 | 
			
		||||
	except:
 | 
			
		||||
		return [-1]
 | 
			
		||||
 | 
			
		||||
# Load config line data as array of Command schedule
 | 
			
		||||
def newCommandSchedule(curline):
 | 
			
		||||
	result = []
 | 
			
		||||
	linedata = curline.split(" ")
 | 
			
		||||
	if len(linedata) < 6:
 | 
			
		||||
		return result
 | 
			
		||||
 | 
			
		||||
	minutelist = getConfigValue(linedata[0])
 | 
			
		||||
	hourlist = getConfigValue(linedata[1])
 | 
			
		||||
	datelist = getConfigValue(linedata[2])
 | 
			
		||||
	#monthlist = getConfigValue(linedata[3])
 | 
			
		||||
	monthlist = [-1] # Certain edge cases will not be handled properly
 | 
			
		||||
	weekdaylist = getConfigValue(linedata[4])
 | 
			
		||||
 | 
			
		||||
	cmd = ""
 | 
			
		||||
	ctr = 5
 | 
			
		||||
	while ctr < len(linedata):
 | 
			
		||||
		cmd = cmd + " " + linedata[ctr]
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
	cmd = cmd.strip()
 | 
			
		||||
 | 
			
		||||
	for curmin in minutelist:
 | 
			
		||||
		for curhour in hourlist:
 | 
			
		||||
			for curdate in datelist:
 | 
			
		||||
				for curmonth in monthlist:
 | 
			
		||||
					for curweekday in weekdaylist:
 | 
			
		||||
						result.append({ "minute": curmin, "hour": curhour, "date": curdate, "month":curmonth, "weekday": curweekday, "cmd":cmd })
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
 | 
			
		||||
# Save updated config file
 | 
			
		||||
def saveConfigList(fname, configlist):
 | 
			
		||||
	f = open(fname, "w")
 | 
			
		||||
	f.write("#\n")
 | 
			
		||||
	f.write("# Argon RTC Configuration\n")
 | 
			
		||||
	f.write("# - Follows cron general format, but with only * and csv support\n")
 | 
			
		||||
	f.write("# - Each row follows the following format:\n")
 | 
			
		||||
	f.write("#      min hour date month dayOfWeek Command\n")
 | 
			
		||||
	f.write("#      e.g. Shutdown daily at 1am\n")
 | 
			
		||||
	f.write("#            0 1 * * * off\n")
 | 
			
		||||
	f.write("#           Shutdown daily at 1am and 1pm\n")
 | 
			
		||||
	f.write("#            0 1,13 * * * off\n")
 | 
			
		||||
	f.write("# - Commands are currently on or off only\n")
 | 
			
		||||
	f.write("# - Limititations\n")
 | 
			
		||||
	f.write("#      Requires MINUTE value\n")
 | 
			
		||||
	f.write("#      Month values are ignored (edge cases not supported)\n")
 | 
			
		||||
	f.write("#\n")
 | 
			
		||||
 | 
			
		||||
	for config in configlist:
 | 
			
		||||
		f.write(config+"\n")
 | 
			
		||||
	f.close()
 | 
			
		||||
 | 
			
		||||
# Remove config line
 | 
			
		||||
def removeConfigEntry(fname, entryidx):
 | 
			
		||||
	configlist = loadConfigList(fname)
 | 
			
		||||
	if len(configlist) > entryidx:
 | 
			
		||||
		configlist.pop(entryidx)
 | 
			
		||||
	saveConfigList(fname, configlist)
 | 
			
		||||
 | 
			
		||||
# Load config list (removes invalid data)
 | 
			
		||||
def loadConfigList(fname):
 | 
			
		||||
	try:
 | 
			
		||||
		result = []
 | 
			
		||||
		with open(fname, "r") as fp:
 | 
			
		||||
			for curline in fp:
 | 
			
		||||
				if not curline:
 | 
			
		||||
					continue
 | 
			
		||||
				curline = curline.strip().replace('\t', ' ')
 | 
			
		||||
				# Handle special characters that get encoded
 | 
			
		||||
				tmpline = "".join([c if 0x20<=ord(c) and ord(c)<=0x7e else "" for c in curline])
 | 
			
		||||
 | 
			
		||||
				if not tmpline:
 | 
			
		||||
					continue
 | 
			
		||||
				if tmpline[0] == "#":
 | 
			
		||||
					continue
 | 
			
		||||
				checkdata = tmpline.split(" ")
 | 
			
		||||
				if len(checkdata) > 5:
 | 
			
		||||
					# Don't include every minute type of schedule
 | 
			
		||||
					if checkdata[0] != "*":
 | 
			
		||||
						result.append(tmpline)
 | 
			
		||||
		return result
 | 
			
		||||
	except:
 | 
			
		||||
		return []
 | 
			
		||||
 | 
			
		||||
# Form Command Schedule list from config list
 | 
			
		||||
def formCommandScheduleList(configlist):
 | 
			
		||||
	try:
 | 
			
		||||
		result = []
 | 
			
		||||
		for config in configlist:
 | 
			
		||||
			result = result + newCommandSchedule(config)
 | 
			
		||||
		return result
 | 
			
		||||
	except:
 | 
			
		||||
		return []
 | 
			
		||||
 | 
			
		||||
# Describe config list entry
 | 
			
		||||
def describeConfigListEntry(configlistitem):
 | 
			
		||||
	linedata = configlistitem.split(" ")
 | 
			
		||||
	if len(linedata) < 6:
 | 
			
		||||
		return ""
 | 
			
		||||
 | 
			
		||||
	minutelist = getConfigValue(linedata[0])
 | 
			
		||||
	hourlist = getConfigValue(linedata[1])
 | 
			
		||||
	datelist = getConfigValue(linedata[2])
 | 
			
		||||
	#monthlist = getConfigValue(linedata[3])
 | 
			
		||||
	monthlist = [-1] # Certain edge cases will not be handled properly
 | 
			
		||||
	weekdaylist = getConfigValue(linedata[4])
 | 
			
		||||
 | 
			
		||||
	cmd = ""
 | 
			
		||||
	ctr = 5
 | 
			
		||||
	while ctr < len(linedata):
 | 
			
		||||
		cmd = cmd + " " + linedata[ctr]
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
	cmd = cmd.strip().lower()
 | 
			
		||||
	if cmd == "on":
 | 
			
		||||
		cmd = "Startup"
 | 
			
		||||
	else:
 | 
			
		||||
		cmd = "Shutdown"
 | 
			
		||||
 | 
			
		||||
	return cmd+" | "+describeSchedule(monthlist, weekdaylist, datelist, hourlist, minutelist)
 | 
			
		||||
 | 
			
		||||
# Describe config list and show indices
 | 
			
		||||
def describeConfigList(fname):
 | 
			
		||||
	# 1 is reserved for New schedule
 | 
			
		||||
	ctr = 2
 | 
			
		||||
	configlist = loadConfigList(fname)
 | 
			
		||||
	for config in configlist:
 | 
			
		||||
		tmpline = describeConfigListEntry(config)
 | 
			
		||||
		if len(tmpline) > 0:
 | 
			
		||||
			print("  "+str(ctr)+". ", tmpline)
 | 
			
		||||
			ctr = ctr + 1
 | 
			
		||||
	if ctr == 2:
 | 
			
		||||
		print("  No Existing Schedules")
 | 
			
		||||
 | 
			
		||||
# Check Command schedule if it should fire for the give time
 | 
			
		||||
def checkDateForCommandSchedule(commandschedule, datetimeobj):
 | 
			
		||||
	testminute = commandschedule.get("minute", -1)
 | 
			
		||||
	testhour = commandschedule.get("hour", -1)
 | 
			
		||||
	testdate = commandschedule.get("date", -1)
 | 
			
		||||
	testmonth = commandschedule.get("month", -1)
 | 
			
		||||
	testweekday = commandschedule.get("weekday", -1)
 | 
			
		||||
 | 
			
		||||
	if testminute < 0 or testminute == datetimeobj.minute:
 | 
			
		||||
		if testhour < 0 or testhour == datetimeobj.hour:
 | 
			
		||||
			if testdate < 0 or testdate == datetimeobj.day:
 | 
			
		||||
				if testmonth < 0 or testmonth == datetimeobj.month:
 | 
			
		||||
					if testweekday < 0:
 | 
			
		||||
						return True
 | 
			
		||||
					else:
 | 
			
		||||
						# python Sunday = 6, RTC Sunday = 0
 | 
			
		||||
						weekDay = datetimeobj.weekday()
 | 
			
		||||
						if weekDay == 6:
 | 
			
		||||
							weekDay = 0
 | 
			
		||||
						else:
 | 
			
		||||
							weekDay = weekDay + 1
 | 
			
		||||
						if testweekday == weekDay:
 | 
			
		||||
							return True
 | 
			
		||||
	return False
 | 
			
		||||
 | 
			
		||||
# Get current command
 | 
			
		||||
def getCommandForTime(commandschedulelist, datetimeobj, checkcmd):
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < len(commandschedulelist):
 | 
			
		||||
		testcmd = commandschedulelist[ctr].get("cmd", "")
 | 
			
		||||
		if (testcmd.lower() == checkcmd or len(checkcmd) == 0) and len(testcmd) > 0:
 | 
			
		||||
			if checkDateForCommandSchedule(commandschedulelist[ctr], datetimeobj) == True:
 | 
			
		||||
				return testcmd
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
	return ""
 | 
			
		||||
 | 
			
		||||
# Get Last Date of Month
 | 
			
		||||
def getLastMonthDate(year, month):
 | 
			
		||||
	if month < 12:
 | 
			
		||||
		testtime = datetime.datetime(year, month+1, 1)
 | 
			
		||||
	else:
 | 
			
		||||
		testtime = datetime.datetime(year+1, 1, 1)
 | 
			
		||||
	testtime = testtime - datetime.timedelta(days=1)
 | 
			
		||||
	return testtime.day
 | 
			
		||||
 | 
			
		||||
# Increment to the next iteration of command schedule
 | 
			
		||||
def incrementCommandScheduleTime(commandschedule, testtime, addmode):
 | 
			
		||||
	testminute = commandschedule.get("minute", -1)
 | 
			
		||||
	testhour = commandschedule.get("hour", -1)
 | 
			
		||||
	testdate = commandschedule.get("date", -1)
 | 
			
		||||
	testmonth = commandschedule.get("month", -1)
 | 
			
		||||
	testweekday = commandschedule.get("weekday", -1)
 | 
			
		||||
 | 
			
		||||
	if addmode == "minute":
 | 
			
		||||
		testfield = commandschedule.get(addmode, -1)
 | 
			
		||||
		if testfield < 0:
 | 
			
		||||
			if testtime.minute < 59:
 | 
			
		||||
				return testtime + datetime.timedelta(minutes=1)
 | 
			
		||||
			else:
 | 
			
		||||
				return incrementCommandScheduleTime(commandschedule, testtime.replace(minute=0), "hour")
 | 
			
		||||
		else:
 | 
			
		||||
			return incrementCommandScheduleTime(commandschedule, testtime, "hour")
 | 
			
		||||
	elif addmode == "hour":
 | 
			
		||||
		testfield = commandschedule.get(addmode, -1)
 | 
			
		||||
		if testfield < 0:
 | 
			
		||||
			if testtime.hour < 23:
 | 
			
		||||
				return testtime + datetime.timedelta(hours=1)
 | 
			
		||||
			else:
 | 
			
		||||
				return incrementCommandScheduleTime(commandschedule, testtime.replace(hour=0), "date")
 | 
			
		||||
		else:
 | 
			
		||||
			return incrementCommandScheduleTime(commandschedule, testtime, "date")
 | 
			
		||||
	elif addmode == "date":
 | 
			
		||||
		testfield = commandschedule.get(addmode, -1)
 | 
			
		||||
		if testfield < 0:
 | 
			
		||||
			maxmonthdate = getLastMonthDate(testtime.year, testtime.month)
 | 
			
		||||
			if testtime.day < maxmonthdate:
 | 
			
		||||
				return testtime + datetime.timedelta(days=1)
 | 
			
		||||
			else:
 | 
			
		||||
				return incrementCommandScheduleTime(commandschedule, testtime.replace(day=1), "month")
 | 
			
		||||
		else:
 | 
			
		||||
			return incrementCommandScheduleTime(commandschedule, testtime, "month")
 | 
			
		||||
	elif addmode == "month":
 | 
			
		||||
		testfield = commandschedule.get(addmode, -1)
 | 
			
		||||
		if testfield < 0:
 | 
			
		||||
			nextmonth = testtime.month
 | 
			
		||||
			nextyear = testtime.year
 | 
			
		||||
			while True:
 | 
			
		||||
				if nextmonth < 12:
 | 
			
		||||
					nextmonth = nextmonth + 1
 | 
			
		||||
				else:
 | 
			
		||||
					nextmonth = 1
 | 
			
		||||
					nextyear = nextyear + 1
 | 
			
		||||
				maxmonthdate = getLastMonthDate(nextyear, nextmonth)
 | 
			
		||||
				if testtime.day <= maxmonthdate:
 | 
			
		||||
					return testtime.replace(month=nextmonth, year=nextyear)
 | 
			
		||||
		else:
 | 
			
		||||
			return incrementCommandScheduleTime(commandschedule, testtime, "year")
 | 
			
		||||
	else:
 | 
			
		||||
		# Year
 | 
			
		||||
		if testtime.month == 2 and testtime.day == 29:
 | 
			
		||||
			# Leap day handling
 | 
			
		||||
			nextyear = testtime.year
 | 
			
		||||
			while True:
 | 
			
		||||
				nextyear = nextyear + 1
 | 
			
		||||
				maxmonthdate = getLastMonthDate(nextyear, testtime.month)
 | 
			
		||||
				if testtime.day <= maxmonthdate:
 | 
			
		||||
					return testtime.replace(year=nextyear)
 | 
			
		||||
		else:
 | 
			
		||||
			return testtime.replace(year=(testtime.year+1))
 | 
			
		||||
 | 
			
		||||
# Set Next Alarm on RTC
 | 
			
		||||
def getNextAlarm(commandschedulelist, prevdatetime):
 | 
			
		||||
	curtime = datetime.datetime.now()
 | 
			
		||||
	if prevdatetime > curtime:
 | 
			
		||||
		return [prevdatetime, -1, -1, -1, -1]
 | 
			
		||||
 | 
			
		||||
	# Divisible by 4 for leap day
 | 
			
		||||
	checklimityears = 12
 | 
			
		||||
	foundnextcmd = False
 | 
			
		||||
	nextcommandschedule = {}
 | 
			
		||||
	# To be sure it's later than any schedule
 | 
			
		||||
	nextcommandtime = curtime.replace(year=(curtime.year+checklimityears))
 | 
			
		||||
 | 
			
		||||
	ctr = 0
 | 
			
		||||
	while ctr < len(commandschedulelist):
 | 
			
		||||
		testcmd = commandschedulelist[ctr].get("cmd", "").lower()
 | 
			
		||||
		if testcmd == "on":
 | 
			
		||||
			invaliddata = False
 | 
			
		||||
			testminute = commandschedulelist[ctr].get("minute", -1)
 | 
			
		||||
			testhour = commandschedulelist[ctr].get("hour", -1)
 | 
			
		||||
			testdate = commandschedulelist[ctr].get("date", -1)
 | 
			
		||||
			testmonth = commandschedulelist[ctr].get("month", -1)
 | 
			
		||||
			testweekday = commandschedulelist[ctr].get("weekday", -1)
 | 
			
		||||
 | 
			
		||||
			tmpminute = testminute
 | 
			
		||||
			tmphour = testhour
 | 
			
		||||
			tmpdate = testdate
 | 
			
		||||
			tmpmonth = testmonth
 | 
			
		||||
			tmpyear = curtime.year
 | 
			
		||||
 | 
			
		||||
			if tmpminute < 0:
 | 
			
		||||
				tmpminute = curtime.minute
 | 
			
		||||
 | 
			
		||||
			if tmphour < 0:
 | 
			
		||||
				tmphour = curtime.hour
 | 
			
		||||
 | 
			
		||||
			if tmpdate < 0:
 | 
			
		||||
				tmpdate = curtime.day
 | 
			
		||||
 | 
			
		||||
			if tmpmonth < 0:
 | 
			
		||||
				tmpmonth = curtime.month
 | 
			
		||||
 | 
			
		||||
			maxmonthdate = getLastMonthDate(tmpyear, tmpmonth)
 | 
			
		||||
			if tmpdate > maxmonthdate:
 | 
			
		||||
				# Invalid month date
 | 
			
		||||
				if testdate < 0:
 | 
			
		||||
					tmpdate = maxmonthdate
 | 
			
		||||
				else:
 | 
			
		||||
					# Date is fixed
 | 
			
		||||
					if testminute < 0:
 | 
			
		||||
						tmpminute = 0
 | 
			
		||||
					if testhour < 0:
 | 
			
		||||
						tmphour = 0
 | 
			
		||||
					if testmonth < 0 and testdate <= 31:
 | 
			
		||||
						# Look for next valid month
 | 
			
		||||
						while tmpdate > maxmonthdate:
 | 
			
		||||
							if tmpmonth < 12:
 | 
			
		||||
								tmpmonth = tmpmonth + 1
 | 
			
		||||
							else:
 | 
			
		||||
								tmpmonth = 1
 | 
			
		||||
								tmpyear = tmpyear + 1
 | 
			
		||||
							maxmonthdate = getLastMonthDate(tmpyear, tmpmonth)
 | 
			
		||||
					elif tmpdate == 29 and tmpmonth == 2:
 | 
			
		||||
						# Fixed to leap day
 | 
			
		||||
						while tmpdate > maxmonthdate:
 | 
			
		||||
							tmpyear = tmpyear + 1
 | 
			
		||||
							maxmonthdate = getLastMonthDate(tmpyear, tmpmonth)
 | 
			
		||||
					else:
 | 
			
		||||
						invaliddata = True
 | 
			
		||||
			if invaliddata == False:
 | 
			
		||||
				try:
 | 
			
		||||
					testtime = datetime.datetime(tmpyear, tmpmonth, tmpdate, tmphour, tmpminute)
 | 
			
		||||
				except:
 | 
			
		||||
					# Force time diff
 | 
			
		||||
					testtime = curtime - datetime.timedelta(hours=1)
 | 
			
		||||
				tmptimediff = (curtime - testtime).total_seconds()
 | 
			
		||||
			else:
 | 
			
		||||
				tmptimediff = 0
 | 
			
		||||
 | 
			
		||||
			if testweekday >= 0:
 | 
			
		||||
				# Day of Week check
 | 
			
		||||
				# python Sunday = 6, RTC Sunday = 0
 | 
			
		||||
				weekDay = testtime.weekday()
 | 
			
		||||
				if weekDay == 6:
 | 
			
		||||
					weekDay = 0
 | 
			
		||||
				else:
 | 
			
		||||
					weekDay = weekDay + 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
				if weekDay != testweekday or tmptimediff > 0:
 | 
			
		||||
					# Resulting 0-ed time will be <= the testtime
 | 
			
		||||
					if testminute < 0:
 | 
			
		||||
						testtime = testtime.replace(minute=0)
 | 
			
		||||
					if testhour < 0:
 | 
			
		||||
						testtime = testtime.replace(hour=0)
 | 
			
		||||
 | 
			
		||||
					dayoffset = testweekday-weekDay
 | 
			
		||||
					if dayoffset < 0:
 | 
			
		||||
						dayoffset = dayoffset + 7
 | 
			
		||||
					elif dayoffset == 0:
 | 
			
		||||
						dayoffset = 7
 | 
			
		||||
 | 
			
		||||
					testtime = testtime + datetime.timedelta(days=dayoffset)
 | 
			
		||||
 | 
			
		||||
				# Just look for the next valid weekday; Can be optimized
 | 
			
		||||
				while checkDateForCommandSchedule(commandschedulelist[ctr], testtime) == False and (testtime.year - curtime.year) < checklimityears:
 | 
			
		||||
					testtime = testtime + datetime.timedelta(days=7)
 | 
			
		||||
 | 
			
		||||
				if (testtime.year - curtime.year) >= checklimityears:
 | 
			
		||||
					# Too many iterations, abort/ignore
 | 
			
		||||
					tmptimediff = 0
 | 
			
		||||
				else:
 | 
			
		||||
					tmptimediff = (curtime - testtime).total_seconds()
 | 
			
		||||
			if tmptimediff > 0:
 | 
			
		||||
				# Find next iteration that's greater than the current time (Day of Week check already handled)
 | 
			
		||||
				while tmptimediff >= 0:
 | 
			
		||||
					testtime = incrementCommandScheduleTime(commandschedulelist[ctr], testtime, "minute")
 | 
			
		||||
					tmptimediff = (curtime - testtime).total_seconds()
 | 
			
		||||
 | 
			
		||||
			if nextcommandtime > testtime and tmptimediff < 0:
 | 
			
		||||
				nextcommandschedule = commandschedulelist[ctr]
 | 
			
		||||
				nextcommandtime = testtime
 | 
			
		||||
				foundnextcmd = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		ctr = ctr + 1
 | 
			
		||||
	if foundnextcmd == True:
 | 
			
		||||
		# Schedule Alarm
 | 
			
		||||
		# Assume no date,weekday involved just shift the hour and minute accordingly
 | 
			
		||||
		paramminute = nextcommandschedule.get("minute", -1)
 | 
			
		||||
		paramhour = nextcommandschedule.get("hour", -1)
 | 
			
		||||
		if nextcommandschedule.get("weekday", -1) >=0 or nextcommandschedule.get("date", -1) > 0:
 | 
			
		||||
			# Set alarm based on hour/minute of next occurrence to factor in timezone changes if any
 | 
			
		||||
			paramminute = nextcommandtime.minute
 | 
			
		||||
			paramhour = nextcommandtime.hour
 | 
			
		||||
		weekday, caldate, hour, minute = getRTCAlarm(nextcommandschedule.get("weekday", -1), nextcommandschedule.get("date", -1), paramhour, paramminute)
 | 
			
		||||
		return [nextcommandtime, weekday, caldate, hour, minute]
 | 
			
		||||
 | 
			
		||||
	# This will ensure that this will be replaced next iteration
 | 
			
		||||
	return [curtime, -1, -1, -1, -1]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										172
									
								
								source/scripts/argonstatus.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								source/scripts/argonstatus.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
sys.path.append("/etc/argon/")
 | 
			
		||||
from argonsysinfo import *
 | 
			
		||||
from argonregister import *
 | 
			
		||||
from argononed import *
 | 
			
		||||
 | 
			
		||||
def getFahrenheit(celsiustemp):
 | 
			
		||||
	try:
 | 
			
		||||
		return (32+9*(celsiustemp)/5)
 | 
			
		||||
	except:
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
temperature="C"
 | 
			
		||||
tmpconfig=load_unitconfig(UNIT_CONFIGFILE)
 | 
			
		||||
if "temperature" in tmpconfig:
 | 
			
		||||
	temperature = tmpconfig["temperature"]
 | 
			
		||||
 | 
			
		||||
baseleftoffset = ""
 | 
			
		||||
 | 
			
		||||
stdleftoffset = "   "
 | 
			
		||||
 | 
			
		||||
#if len(sys.argv) > 2:
 | 
			
		||||
#	baseleftoffset = stdleftoffset
 | 
			
		||||
baseleftoffset = stdleftoffset
 | 
			
		||||
 | 
			
		||||
argctr = 1
 | 
			
		||||
while argctr < len(sys.argv):
 | 
			
		||||
	cmd = sys.argv[argctr].lower()
 | 
			
		||||
	argctr = argctr + 1
 | 
			
		||||
	if baseleftoffset != "":
 | 
			
		||||
		print(cmd.upper(),"INFORMATION:")
 | 
			
		||||
	if cmd == "cpu usage":
 | 
			
		||||
		# CPU Usage
 | 
			
		||||
		curlist = argonsysinfo_listcpuusage()
 | 
			
		||||
 | 
			
		||||
		while len(curlist) > 0:
 | 
			
		||||
			curline = ""
 | 
			
		||||
			tmpitem = curlist.pop(0)
 | 
			
		||||
			curline = tmpitem["title"]+": "+str(tmpitem["value"])+"%"
 | 
			
		||||
			print(baseleftoffset+curline)
 | 
			
		||||
	elif cmd == "storage":
 | 
			
		||||
		# Storage Info
 | 
			
		||||
		curlist = []
 | 
			
		||||
		try:
 | 
			
		||||
			tmpobj = argonsysinfo_listhddusage()
 | 
			
		||||
			for curdev in tmpobj:
 | 
			
		||||
				curlist.append({"title": curdev, "value": argonsysinfo_kbstr(tmpobj[curdev]['total']), "usage": int(100*tmpobj[curdev]['used']/tmpobj[curdev]['total']) })
 | 
			
		||||
			#curlist = argonsysinfo_liststoragetotal()
 | 
			
		||||
		except Exception:
 | 
			
		||||
			curlist = []
 | 
			
		||||
 | 
			
		||||
		while len(curlist) > 0:
 | 
			
		||||
			tmpitem = curlist.pop(0)
 | 
			
		||||
			# Right column first, safer to overwrite white space
 | 
			
		||||
			print(baseleftoffset+tmpitem["title"], str(tmpitem["usage"])+"%","used of", tmpitem["value"])
 | 
			
		||||
 | 
			
		||||
	elif cmd == "raid":
 | 
			
		||||
		# Raid Info
 | 
			
		||||
		curlist = []
 | 
			
		||||
		try:
 | 
			
		||||
			tmpobj = argonsysinfo_listraid()
 | 
			
		||||
			curlist = tmpobj['raidlist']
 | 
			
		||||
		except Exception:
 | 
			
		||||
			curlist = []
 | 
			
		||||
 | 
			
		||||
		if len(curlist) > 0:
 | 
			
		||||
			tmpitem = curlist.pop(0)
 | 
			
		||||
			print(baseleftoffset+tmpitem["title"], tmpitem["value"], argonsysinfo_kbstr(tmpitem["info"]["size"]))
 | 
			
		||||
 | 
			
		||||
			if len(tmpitem['info']['state']) > 0:
 | 
			
		||||
				print(baseleftoffset+stdleftoffset,tmpitem['info']['state'])
 | 
			
		||||
 | 
			
		||||
			if len(tmpitem['info']['rebuildstat']) > 0:
 | 
			
		||||
				print(baseleftoffset+stdleftoffset,"Rebuild:" + tmpitem['info']['rebuildstat'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			print(baseleftoffset+stdleftoffset,"Active:"+str(int(tmpitem["info"]["active"]))+"/"+str(int(tmpitem["info"]["devices"])))
 | 
			
		||||
			print(baseleftoffset+stdleftoffset,"Working:"+str(int(tmpitem["info"]["working"]))+"/"+str(int(tmpitem["info"]["devices"])))
 | 
			
		||||
			print(baseleftoffset+stdleftoffset,"Failed:"+str(int(tmpitem["info"]["failed"]))+"/"+str(int(tmpitem["info"]["devices"])))
 | 
			
		||||
		else:
 | 
			
		||||
			print(baseleftoffset+stdleftoffset,"N/A")
 | 
			
		||||
 | 
			
		||||
	elif cmd == "ram":
 | 
			
		||||
		# RAM
 | 
			
		||||
		try:
 | 
			
		||||
			tmpraminfo = argonsysinfo_getram()
 | 
			
		||||
			print(baseleftoffset+tmpraminfo[0],"of", tmpraminfo[1])
 | 
			
		||||
		except Exception:
 | 
			
		||||
			pass
 | 
			
		||||
 | 
			
		||||
	elif cmd == "temperature":
 | 
			
		||||
		# Temp
 | 
			
		||||
		try:
 | 
			
		||||
			hddtempctr = 0
 | 
			
		||||
			maxcval = 0
 | 
			
		||||
			mincval = 200
 | 
			
		||||
 | 
			
		||||
			alltempobj = {"cpu": argonsysinfo_getcputemp()}
 | 
			
		||||
			# Get min/max of hdd temp
 | 
			
		||||
			hddtempobj = argonsysinfo_gethddtemp()
 | 
			
		||||
			for curdev in hddtempobj:
 | 
			
		||||
				alltempobj[curdev] = hddtempobj[curdev]
 | 
			
		||||
				if hddtempobj[curdev] < mincval:
 | 
			
		||||
					mincval = hddtempobj[curdev]
 | 
			
		||||
				if hddtempobj[curdev] > maxcval:
 | 
			
		||||
					maxcval = hddtempobj[curdev]
 | 
			
		||||
				hddtempctr = hddtempctr + 1
 | 
			
		||||
 | 
			
		||||
			if hddtempctr > 0:
 | 
			
		||||
				alltempobj["hdd min"]=mincval
 | 
			
		||||
				alltempobj["hdd max"]=maxcval
 | 
			
		||||
 | 
			
		||||
			for curdev in alltempobj:
 | 
			
		||||
				if temperature == "C":
 | 
			
		||||
					# Celsius
 | 
			
		||||
					tmpstr = str(alltempobj[curdev])
 | 
			
		||||
					if len(tmpstr) > 4:
 | 
			
		||||
						tmpstr = tmpstr[0:4]
 | 
			
		||||
				else:
 | 
			
		||||
					# Fahrenheit
 | 
			
		||||
					tmpstr = str(getFahrenheit(alltempobj[curdev]))
 | 
			
		||||
					if len(tmpstr) > 5:
 | 
			
		||||
						tmpstr = tmpstr[0:5]
 | 
			
		||||
				print(baseleftoffset+curdev.upper()+": "+ tmpstr+ chr(176) +temperature)
 | 
			
		||||
 | 
			
		||||
		except Exception:
 | 
			
		||||
			pass
 | 
			
		||||
	elif cmd == "ip":
 | 
			
		||||
		# IP Address
 | 
			
		||||
		try:
 | 
			
		||||
			print(baseleftoffset+argonsysinfo_getip())
 | 
			
		||||
		except Exception:
 | 
			
		||||
			pass
 | 
			
		||||
	elif cmd == "fan speed":
 | 
			
		||||
		# Fan Speed
 | 
			
		||||
		try:
 | 
			
		||||
			newspeed = argonregister_getfanspeed(argonregister_initializebusobj())
 | 
			
		||||
			if newspeed <= 0:
 | 
			
		||||
				fanconfig = load_fancpuconfig()
 | 
			
		||||
				fanhddconfig = load_fanhddconfig()
 | 
			
		||||
 | 
			
		||||
				# Speed based on CPU Temp
 | 
			
		||||
				val = argonsysinfo_getcputemp()
 | 
			
		||||
				newspeed = get_fanspeed(val, fanconfig)
 | 
			
		||||
 | 
			
		||||
				val = argonsysinfo_getmaxhddtemp()
 | 
			
		||||
				tmpspeed = get_fanspeed(val, fanhddconfig)
 | 
			
		||||
				if tmpspeed > newspeed:
 | 
			
		||||
					newspeed = tmpspeed
 | 
			
		||||
			print(baseleftoffset+"Fan Speed",str(newspeed))
 | 
			
		||||
		except Exception:
 | 
			
		||||
			pass
 | 
			
		||||
	elif cmd == "fan configuration":
 | 
			
		||||
		fanconfig = load_fancpuconfig()
 | 
			
		||||
		fanhddconfig = load_fanhddconfig()
 | 
			
		||||
 | 
			
		||||
		if len(fanhddconfig) > 0:
 | 
			
		||||
			print(baseleftoffset+"Fan Temp-Speed cut-offs")
 | 
			
		||||
		for curconfig in fanconfig:
 | 
			
		||||
			print(baseleftoffset+stdleftoffset,curconfig)
 | 
			
		||||
 | 
			
		||||
		if len(fanhddconfig) > 0:
 | 
			
		||||
			print(baseleftoffset+"HDD Temp-Speed cut-offs")
 | 
			
		||||
			for curconfig in fanhddconfig:
 | 
			
		||||
				print(baseleftoffset+stdleftoffset,curconfig)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										394
									
								
								source/scripts/argonsysinfo.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										394
									
								
								source/scripts/argonsysinfo.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,394 @@
 | 
			
		||||
#!/usr/bin/python3
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Misc methods to retrieve system information.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import time
 | 
			
		||||
import socket
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_listcpuusage(sleepsec = 1):
 | 
			
		||||
	outputlist = []
 | 
			
		||||
	curusage_a = argonsysinfo_getcpuusagesnapshot()
 | 
			
		||||
	time.sleep(sleepsec)
 | 
			
		||||
	curusage_b = argonsysinfo_getcpuusagesnapshot()
 | 
			
		||||
 | 
			
		||||
	for cpuname in curusage_a:
 | 
			
		||||
		if cpuname == "cpu":
 | 
			
		||||
			continue
 | 
			
		||||
		if curusage_a[cpuname]["total"] == curusage_b[cpuname]["total"]:
 | 
			
		||||
			outputlist.append({"title": cpuname, "value": "0%"})
 | 
			
		||||
		else:
 | 
			
		||||
			total = curusage_b[cpuname]["total"]-curusage_a[cpuname]["total"]
 | 
			
		||||
			idle = curusage_b[cpuname]["idle"]-curusage_a[cpuname]["idle"]
 | 
			
		||||
			outputlist.append({"title": cpuname, "value": int(100*(total-idle)/(total))})
 | 
			
		||||
	return outputlist
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getcpuusagesnapshot():
 | 
			
		||||
	cpupercent = {}
 | 
			
		||||
	errorflag = False
 | 
			
		||||
	try:
 | 
			
		||||
		cpuctr = 0
 | 
			
		||||
		# user, nice, system, idle, iowait, irc, softirq, steal, guest, guest nice
 | 
			
		||||
		tempfp = open("/proc/stat", "r")
 | 
			
		||||
		alllines = tempfp.readlines()
 | 
			
		||||
		for temp in alllines:
 | 
			
		||||
			temp = temp.replace('\t', ' ')
 | 
			
		||||
			temp = temp.strip()
 | 
			
		||||
			while temp.find("  ") >= 0:
 | 
			
		||||
				temp = temp.replace("  ", " ")
 | 
			
		||||
			if len(temp) < 3:
 | 
			
		||||
				cpuctr = cpuctr +1
 | 
			
		||||
				continue
 | 
			
		||||
 | 
			
		||||
			checkname = temp[0:3]
 | 
			
		||||
			if checkname == "cpu":
 | 
			
		||||
				infolist = temp.split(" ")
 | 
			
		||||
				idle = 0
 | 
			
		||||
				total = 0
 | 
			
		||||
				colctr = 1
 | 
			
		||||
				while colctr < len(infolist):
 | 
			
		||||
					curval = int(infolist[colctr])
 | 
			
		||||
					if colctr == 4 or colctr == 5:
 | 
			
		||||
						idle = idle + curval
 | 
			
		||||
					total = total + curval
 | 
			
		||||
					colctr = colctr + 1
 | 
			
		||||
				if total > 0:
 | 
			
		||||
					cpupercent[infolist[0]] = {"total": total, "idle": idle}
 | 
			
		||||
			cpuctr = cpuctr +1
 | 
			
		||||
 | 
			
		||||
		tempfp.close()
 | 
			
		||||
	except IOError:
 | 
			
		||||
		errorflag = True
 | 
			
		||||
	return cpupercent
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_liststoragetotal():
 | 
			
		||||
	outputlist = []
 | 
			
		||||
	ramtotal = 0
 | 
			
		||||
	errorflag = False
 | 
			
		||||
 | 
			
		||||
	try:
 | 
			
		||||
		hddctr = 0
 | 
			
		||||
		tempfp = open("/proc/partitions", "r")
 | 
			
		||||
		alllines = tempfp.readlines()
 | 
			
		||||
 | 
			
		||||
		for temp in alllines:
 | 
			
		||||
			temp = temp.replace('\t', ' ')
 | 
			
		||||
			temp = temp.strip()
 | 
			
		||||
			while temp.find("  ") >= 0:
 | 
			
		||||
				temp = temp.replace("  ", " ")
 | 
			
		||||
			infolist = temp.split(" ")
 | 
			
		||||
			if len(infolist) >= 4:
 | 
			
		||||
				# Check if header
 | 
			
		||||
				if infolist[3] != "name":
 | 
			
		||||
					parttype = infolist[3][0:3]
 | 
			
		||||
					if parttype == "ram":
 | 
			
		||||
						ramtotal = ramtotal + int(infolist[2])
 | 
			
		||||
					elif parttype[0:2] == "sd" or parttype[0:2] == "hd":
 | 
			
		||||
						lastchar = infolist[3][-1]
 | 
			
		||||
						if lastchar.isdigit() == False:
 | 
			
		||||
							outputlist.append({"title": infolist[3], "value": argonsysinfo_kbstr(int(infolist[2]))})
 | 
			
		||||
					else:
 | 
			
		||||
						# SD Cards
 | 
			
		||||
						lastchar = infolist[3][-2]
 | 
			
		||||
						if lastchar[0] != "p":
 | 
			
		||||
							outputlist.append({"title": infolist[3], "value": argonsysinfo_kbstr(int(infolist[2]))})
 | 
			
		||||
 | 
			
		||||
		tempfp.close()
 | 
			
		||||
		#outputlist.append({"title": "ram", "value": argonsysinfo_kbstr(ramtotal)})
 | 
			
		||||
	except IOError:
 | 
			
		||||
		errorflag = True
 | 
			
		||||
	return outputlist
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getram():
 | 
			
		||||
	totalram = 0
 | 
			
		||||
	totalfree = 0
 | 
			
		||||
	tempfp = open("/proc/meminfo", "r")
 | 
			
		||||
	alllines = tempfp.readlines()
 | 
			
		||||
 | 
			
		||||
	for temp in alllines:
 | 
			
		||||
		temp = temp.replace('\t', ' ')
 | 
			
		||||
		temp = temp.strip()
 | 
			
		||||
		while temp.find("  ") >= 0:
 | 
			
		||||
			temp = temp.replace("  ", " ")
 | 
			
		||||
		infolist = temp.split(" ")
 | 
			
		||||
		if len(infolist) >= 2:
 | 
			
		||||
			if infolist[0] == "MemTotal:":
 | 
			
		||||
				totalram = int(infolist[1])
 | 
			
		||||
			elif infolist[0] == "MemFree:":
 | 
			
		||||
				totalfree = totalfree + int(infolist[1])
 | 
			
		||||
			elif infolist[0] == "Buffers:":
 | 
			
		||||
				totalfree = totalfree + int(infolist[1])
 | 
			
		||||
			elif infolist[0] == "Cached:":
 | 
			
		||||
				totalfree = totalfree + int(infolist[1])
 | 
			
		||||
	if totalram == 0:
 | 
			
		||||
		return "0%"
 | 
			
		||||
	return [str(int(100*totalfree/totalram))+"%", str((totalram+512*1024)>>20)+"GB"]
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getcputemp():
 | 
			
		||||
	try:
 | 
			
		||||
		tempfp = open("/sys/class/thermal/thermal_zone0/temp", "r")
 | 
			
		||||
		temp = tempfp.readline()
 | 
			
		||||
		tempfp.close()
 | 
			
		||||
		#cval = temp/1000
 | 
			
		||||
		#fval = 32+9*temp/5000
 | 
			
		||||
		return float(int(temp)/1000)
 | 
			
		||||
	except IOError:
 | 
			
		||||
		return 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getmaxhddtemp():
 | 
			
		||||
	maxtempval = 0
 | 
			
		||||
	try:
 | 
			
		||||
		hddtempobj = argonsysinfo_gethddtemp()
 | 
			
		||||
		for curdev in hddtempobj:
 | 
			
		||||
			if hddtempobj[curdev] > maxtempval:
 | 
			
		||||
				maxtempval = hddtempobj[curdev]
 | 
			
		||||
		return maxtempval
 | 
			
		||||
	except:
 | 
			
		||||
		return maxtempval
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_gethddtemp():
 | 
			
		||||
	# May 2022: Used smartctl, hddtemp is not available on some platforms
 | 
			
		||||
	hddtempcmd = "/usr/sbin/smartctl"
 | 
			
		||||
	if os.path.exists(hddtempcmd) == False:
 | 
			
		||||
		# Fallback for now
 | 
			
		||||
		hddtempcmd = "/usr/sbin/hddtemp"
 | 
			
		||||
 | 
			
		||||
	outputobj = {}
 | 
			
		||||
	if os.path.exists(hddtempcmd):
 | 
			
		||||
		try:
 | 
			
		||||
			tmp = os.popen("lsblk | grep -e '0 disk' | awk '{print $1}'").read()
 | 
			
		||||
			alllines = tmp.split("\n")
 | 
			
		||||
			for curdev in alllines:
 | 
			
		||||
				if curdev[0:2] == "sd" or curdev[0:2] == "hd":
 | 
			
		||||
					tempval = argonsysinfo_getdevhddtemp(hddtempcmd,curdev)
 | 
			
		||||
					if tempval > 0:
 | 
			
		||||
						outputobj[curdev] = tempval
 | 
			
		||||
			return outputobj
 | 
			
		||||
		except:
 | 
			
		||||
			return outputobj
 | 
			
		||||
	return outputobj
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getdevhddtemp(hddtempcmd, curdev):
 | 
			
		||||
	cmdstr = ""
 | 
			
		||||
	if hddtempcmd == "/usr/sbin/hddtemp":
 | 
			
		||||
		cmdstr = "/usr/sbin/hddtemp -n sata:/dev/"+curdev
 | 
			
		||||
	elif hddtempcmd == "/usr/sbin/smartctl":
 | 
			
		||||
		cmdstr = "/usr/sbin/smartctl -d sat -A /dev/"+curdev+" | grep Temperature_Celsius | awk '{print $10}'"
 | 
			
		||||
 | 
			
		||||
	tempval = 0
 | 
			
		||||
	if len(cmdstr) > 0:
 | 
			
		||||
		try:
 | 
			
		||||
			temperaturestr = os.popen(cmdstr+" 2>&1").read()
 | 
			
		||||
			tempval = float(temperaturestr)
 | 
			
		||||
		except:
 | 
			
		||||
			tempval = -1
 | 
			
		||||
 | 
			
		||||
	return tempval
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getip():
 | 
			
		||||
	ipaddr = ""
 | 
			
		||||
	st = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 | 
			
		||||
	try: 
 | 
			
		||||
		# Connect to nonexistent device
 | 
			
		||||
		st.connect(('254.255.255.255', 1))
 | 
			
		||||
		ipaddr = st.getsockname()[0]
 | 
			
		||||
	except Exception:
 | 
			
		||||
		ipaddr = 'N/A'
 | 
			
		||||
	finally:
 | 
			
		||||
		st.close()
 | 
			
		||||
	return ipaddr
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getrootdev():
 | 
			
		||||
	tmp = os.popen('mount').read()
 | 
			
		||||
	alllines = tmp.split("\n")
 | 
			
		||||
 | 
			
		||||
	for temp in alllines:
 | 
			
		||||
		temp = temp.replace('\t', ' ')
 | 
			
		||||
		temp = temp.strip()
 | 
			
		||||
		while temp.find("  ") >= 0:
 | 
			
		||||
			temp = temp.replace("  ", " ")
 | 
			
		||||
		infolist = temp.split(" ")
 | 
			
		||||
		if len(infolist) >= 3:
 | 
			
		||||
 | 
			
		||||
			if infolist[2] == "/":
 | 
			
		||||
				return infolist[0]
 | 
			
		||||
	return ""
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_listhddusage():
 | 
			
		||||
	outputobj = {}
 | 
			
		||||
	raidlist = argonsysinfo_listraid()
 | 
			
		||||
	raiddevlist = []
 | 
			
		||||
	raidctr = 0
 | 
			
		||||
	while raidctr < len(raidlist['raidlist']):
 | 
			
		||||
		raiddevlist.append(raidlist['raidlist'][raidctr]['title'])
 | 
			
		||||
		# TODO: May need to use different method for each raid type (i.e. check raidlist['raidlist'][raidctr]['value'])
 | 
			
		||||
		#outputobj[raidlist['raidlist'][raidctr]['title']] = {"used":int(raidlist['raidlist'][raidctr]['info']['used']), "total":int(raidlist['raidlist'][raidctr]['info']['size'])}
 | 
			
		||||
		raidctr = raidctr + 1
 | 
			
		||||
 | 
			
		||||
	rootdev = argonsysinfo_getrootdev()
 | 
			
		||||
 | 
			
		||||
	tmp = os.popen('df').read()
 | 
			
		||||
	alllines = tmp.split("\n")
 | 
			
		||||
 | 
			
		||||
	for temp in alllines:
 | 
			
		||||
		temp = temp.replace('\t', ' ')
 | 
			
		||||
		temp = temp.strip()
 | 
			
		||||
		while temp.find("  ") >= 0:
 | 
			
		||||
			temp = temp.replace("  ", " ")
 | 
			
		||||
		infolist = temp.split(" ")
 | 
			
		||||
		if len(infolist) >= 6:
 | 
			
		||||
			if infolist[1] == "Size":
 | 
			
		||||
				continue
 | 
			
		||||
			if len(infolist[0]) < 5:
 | 
			
		||||
				continue
 | 
			
		||||
			elif infolist[0][0:5] != "/dev/":
 | 
			
		||||
				continue
 | 
			
		||||
			curdev = infolist[0]
 | 
			
		||||
			if curdev == "/dev/root" and rootdev != "":
 | 
			
		||||
				curdev = rootdev
 | 
			
		||||
			tmpidx = curdev.rfind("/")
 | 
			
		||||
			if tmpidx >= 0:
 | 
			
		||||
				curdev = curdev[tmpidx+1:]
 | 
			
		||||
 | 
			
		||||
			if curdev in raidlist['hddlist']:
 | 
			
		||||
				# Skip devices that are part of a RAID setup
 | 
			
		||||
				continue
 | 
			
		||||
			elif curdev in raiddevlist:
 | 
			
		||||
				# Skip RAID ID that already have size data
 | 
			
		||||
				# (use df information otherwise)
 | 
			
		||||
				if curdev in outputobj:
 | 
			
		||||
					continue
 | 
			
		||||
			elif curdev[0:2] == "sd" or curdev[0:2] == "hd":
 | 
			
		||||
				curdev = curdev[0:-1]
 | 
			
		||||
			else:
 | 
			
		||||
				curdev = curdev[0:-2]
 | 
			
		||||
 | 
			
		||||
			# Aggregate values (i.e. sda1, sda2 to sda)
 | 
			
		||||
			if curdev in outputobj:
 | 
			
		||||
				outputobj[curdev] = {"used":outputobj[curdev]['used']+int(infolist[2]), "total":outputobj[curdev]['total']+int(infolist[1])}
 | 
			
		||||
			else:
 | 
			
		||||
				outputobj[curdev] = {"used":int(infolist[2]), "total":int(infolist[1])}
 | 
			
		||||
 | 
			
		||||
	return outputobj
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_kbstr(kbval, wholenumbers = True):
 | 
			
		||||
	remainder = 0
 | 
			
		||||
	suffixidx = 0
 | 
			
		||||
	suffixlist = ["KB", "MB", "GB", "TB"]
 | 
			
		||||
	while kbval > 1023 and suffixidx < len(suffixlist):
 | 
			
		||||
		remainder = kbval & 1023
 | 
			
		||||
		kbval  = kbval >> 10
 | 
			
		||||
		suffixidx = suffixidx + 1
 | 
			
		||||
 | 
			
		||||
	#return str(kbval)+"."+str(remainder) + suffixlist[suffixidx]
 | 
			
		||||
	remainderstr = ""
 | 
			
		||||
	if kbval < 100 and wholenumbers == False:
 | 
			
		||||
		remainder = int((remainder+50)/100)
 | 
			
		||||
		if remainder > 0:
 | 
			
		||||
			remainderstr = "."+str(remainder)
 | 
			
		||||
	elif remainder >= 500:
 | 
			
		||||
		kbval = kbval + 1
 | 
			
		||||
	return str(kbval)+remainderstr + suffixlist[suffixidx]
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_listraid():
 | 
			
		||||
	hddlist = []
 | 
			
		||||
	outputlist = []
 | 
			
		||||
	# cat /proc/mdstat
 | 
			
		||||
	# multiple mdxx from mdstat
 | 
			
		||||
	# mdadm -D /dev/md1
 | 
			
		||||
 | 
			
		||||
	ramtotal = 0
 | 
			
		||||
	errorflag = False
 | 
			
		||||
	try:
 | 
			
		||||
		hddctr = 0
 | 
			
		||||
		tempfp = open("/proc/mdstat", "r")
 | 
			
		||||
		alllines = tempfp.readlines()
 | 
			
		||||
		for temp in alllines:
 | 
			
		||||
			temp = temp.replace('\t', ' ')
 | 
			
		||||
			temp = temp.strip()
 | 
			
		||||
			while temp.find("  ") >= 0:
 | 
			
		||||
				temp = temp.replace("  ", " ")
 | 
			
		||||
			infolist = temp.split(" ")
 | 
			
		||||
			if len(infolist) >= 4:
 | 
			
		||||
 | 
			
		||||
				# Check if raid info
 | 
			
		||||
				if infolist[0] != "Personalities" and infolist[1] == ":":
 | 
			
		||||
					devname = infolist[0]
 | 
			
		||||
					raidtype = infolist[3]
 | 
			
		||||
					#raidstatus = infolist[2]
 | 
			
		||||
					hddctr = 4
 | 
			
		||||
					while hddctr < len(infolist):
 | 
			
		||||
						tmpdevname = infolist[hddctr]
 | 
			
		||||
						tmpidx = tmpdevname.find("[")
 | 
			
		||||
						if tmpidx >= 0:
 | 
			
		||||
							tmpdevname = tmpdevname[0:tmpidx]
 | 
			
		||||
						hddlist.append(tmpdevname)
 | 
			
		||||
						hddctr = hddctr + 1
 | 
			
		||||
					devdetail = argonsysinfo_getraiddetail(devname)
 | 
			
		||||
					outputlist.append({"title": devname, "value": raidtype, "info": devdetail})
 | 
			
		||||
 | 
			
		||||
		tempfp.close()
 | 
			
		||||
	except IOError:
 | 
			
		||||
		# No raid
 | 
			
		||||
		errorflag = True
 | 
			
		||||
 | 
			
		||||
	return {"raidlist": outputlist, "hddlist": hddlist}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def argonsysinfo_getraiddetail(devname):
 | 
			
		||||
	state = ""
 | 
			
		||||
	raidtype = ""
 | 
			
		||||
	size = 0
 | 
			
		||||
	used = 0
 | 
			
		||||
	total = 0
 | 
			
		||||
	working = 0
 | 
			
		||||
	active = 0
 | 
			
		||||
	failed = 0
 | 
			
		||||
	spare = 0
 | 
			
		||||
	rebuildstat = ""
 | 
			
		||||
	tmp = os.popen('mdadm -D /dev/'+devname).read()
 | 
			
		||||
	alllines = tmp.split("\n")
 | 
			
		||||
 | 
			
		||||
	for temp in alllines:
 | 
			
		||||
		temp = temp.replace('\t', ' ')
 | 
			
		||||
		temp = temp.strip()
 | 
			
		||||
		while temp.find("  ") >= 0:
 | 
			
		||||
			temp = temp.replace("  ", " ")
 | 
			
		||||
		infolist = temp.split(" : ")
 | 
			
		||||
		if len(infolist) == 2:
 | 
			
		||||
			if infolist[0].lower() == "raid level":
 | 
			
		||||
				raidtype = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "array size":
 | 
			
		||||
				tmpidx = infolist[1].find(" ")
 | 
			
		||||
				if tmpidx > 0:
 | 
			
		||||
					size = (infolist[1][0:tmpidx])
 | 
			
		||||
			elif infolist[0].lower() == "used dev size":
 | 
			
		||||
				tmpidx = infolist[1].find(" ")
 | 
			
		||||
				if tmpidx > 0:
 | 
			
		||||
					used = (infolist[1][0:tmpidx])
 | 
			
		||||
			elif infolist[0].lower() == "state":
 | 
			
		||||
				tmpidx = infolist[1].rfind(" ") 
 | 
			
		||||
				if tmpidx > 0:
 | 
			
		||||
					state = (infolist[1][tmpidx+1:])
 | 
			
		||||
				else:
 | 
			
		||||
					state = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "total devices":
 | 
			
		||||
				total = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "active devices":
 | 
			
		||||
				active = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "working devices":
 | 
			
		||||
				working = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "failed devices":
 | 
			
		||||
				failed = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "spare devices":
 | 
			
		||||
				spare = infolist[1]
 | 
			
		||||
			elif infolist[0].lower() == "rebuild status":
 | 
			
		||||
				tmpidx = infolist[1].find("%") 
 | 
			
		||||
				if tmpidx > 0:
 | 
			
		||||
					rebuildstat = (infolist[1][0:tmpidx])+"%"
 | 
			
		||||
	return {"state": state, "raidtype": raidtype, "size": int(size), "used": int(used), "devices": int(total), "active": int(active), "working": int(working), "failed": int(failed), "spare": int(spare), "rebuildstat": rebuildstat}
 | 
			
		||||
							
								
								
									
										42
									
								
								source/tools/setntpserver.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								source/tools/setntpserver.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
NTPSERVER="time.google.com"
 | 
			
		||||
TMPCONFIG=/dev/shm/tmpconfig.conf
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# timesyncd
 | 
			
		||||
CONFIG=/etc/systemd/timesyncd.conf
 | 
			
		||||
if [ -f "$CONFIG" ]
 | 
			
		||||
then
 | 
			
		||||
	cat "$CONFIG" | grep -v -e 'NTP=' > "$TMPCONFIG"
 | 
			
		||||
	echo "NTP=$NTPSERVER" >> "$TMPCONFIG"
 | 
			
		||||
 | 
			
		||||
	sudo chown root:root "$TMPCONFIG"
 | 
			
		||||
	sudo chmod 644 "$TMPCONFIG"
 | 
			
		||||
	sudo mv "$TMPCONFIG" "$CONFIG"
 | 
			
		||||
 | 
			
		||||
	# /usr/sbin/ntpd
 | 
			
		||||
 | 
			
		||||
	sudo service systemd-timesyncd restart > /dev/null 2>&1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
for CURSERVICECONFIG in ntp chrony
 | 
			
		||||
do
 | 
			
		||||
	CONFIG=/etc/${CURSERVICECONFIG}.conf
 | 
			
		||||
	if [ -f "$CONFIG" ]
 | 
			
		||||
	then
 | 
			
		||||
		cat "$CONFIG" | grep -v -e 'pool ' > "$TMPCONFIG"
 | 
			
		||||
		#echo "server $NTPSERVER" >> "$TMPCONFIG"
 | 
			
		||||
		echo "pool time1.google.com iburst" >> "$TMPCONFIG"
 | 
			
		||||
		echo "pool time2.google.com iburst" >> "$TMPCONFIG"
 | 
			
		||||
		echo "pool time3.google.com iburst" >> "$TMPCONFIG"
 | 
			
		||||
		echo "pool time4.google.com iburst" >> "$TMPCONFIG"
 | 
			
		||||
 | 
			
		||||
		sudo chown root:root "$TMPCONFIG"
 | 
			
		||||
		sudo chmod 644 "$TMPCONFIG"
 | 
			
		||||
		sudo mv "$TMPCONFIG" "$CONFIG"
 | 
			
		||||
 | 
			
		||||
		sudo service ${CURSERVICECONFIG} restart > /dev/null 2>&1
 | 
			
		||||
	fi
 | 
			
		||||
done
 | 
			
		||||
		Reference in New Issue
	
	Block a user