mirror of
https://github.com/okunze/Argon40-ArgonOne-Script.git
synced 2026-05-04 22:21:13 +02: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 |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||||
|
|
||||||
@@ -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()
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -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."
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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)
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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()
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
if [ -e /boot/firmware/config.txt ] ; then
|
if [ -e /boot/firmware/config.txt ] ; then
|
||||||
FIRMWARE=/firmware
|
FIRMWARE=/firmware
|
||||||
else
|
else
|
||||||
@@ -24,9 +25,10 @@ then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "--------------------------------"
|
|
||||||
echo "Argon One IR Configuration Tool"
|
echo "-----------------------------"
|
||||||
echo "--------------------------------"
|
echo " Argon IR Configuration Tool"
|
||||||
|
echo "------------------------------"
|
||||||
echo "WARNING: This only supports NEC"
|
echo "WARNING: This only supports NEC"
|
||||||
echo " protocol only."
|
echo " protocol only."
|
||||||
echo -n "Press Y to continue:"
|
echo -n "Press Y to continue:"
|
||||||
@@ -70,8 +72,8 @@ get_number () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irexecrcfile=/etc/lirc/irexec.lircrc
|
irexecrcfile=/etc/lirc/irexec.lircrc
|
||||||
irexecshfile=/usr/bin/argonirexec
|
irexecshfile=/etc/argon/argonirexec
|
||||||
irdecodefile=/usr/bin/argonirdecoder
|
irdecodefile=/etc/argon/argonirdecoder
|
||||||
kodiuserdatafolder="$HOME/.kodi/userdata"
|
kodiuserdatafolder="$HOME/.kodi/userdata"
|
||||||
kodilircmapfile="$kodiuserdatafolder/Lircmap.xml"
|
kodilircmapfile="$kodiuserdatafolder/Lircmap.xml"
|
||||||
remotemode=""
|
remotemode=""
|
||||||
@@ -176,9 +178,9 @@ then
|
|||||||
fi
|
fi
|
||||||
elif [ $newmode -eq 2 ]
|
elif [ $newmode -eq 2 ]
|
||||||
then
|
then
|
||||||
echo "--------------------------------"
|
echo "-----------------------------"
|
||||||
echo "Argon One IR Configuration Tool"
|
echo " Argon IR Configuration Tool"
|
||||||
echo "--------------------------------"
|
echo "-----------------------------"
|
||||||
echo "WARNING: This will install LIRC"
|
echo "WARNING: This will install LIRC"
|
||||||
echo " and related libraries."
|
echo " and related libraries."
|
||||||
echo -n "Press Y to agree:"
|
echo -n "Press Y to agree:"
|
||||||
@@ -320,7 +322,10 @@ then
|
|||||||
echo ' <down>KEY_DOWN</down>' | tee -a $kodilircmapfile 1> /dev/null
|
echo ' <down>KEY_DOWN</down>' | tee -a $kodilircmapfile 1> /dev/null
|
||||||
echo ' <select>KEY_OK</select>' | 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 ' <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 ' <volumeplus>KEY_VOLUMEUP</volumeplus>' | tee -a $kodilircmapfile 1> /dev/null
|
||||||
echo ' <volumeminus>KEY_VOLUMEDOWN</volumeminus>' | 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
|
echo ' </remote>' | tee -a $kodilircmapfile 1> /dev/null
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -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)
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -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")
|
||||||
@@ -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()
|
||||||
@@ -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)
|
||||||
@@ -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)
|
||||||
@@ -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]
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
@@ -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}
|
||||||
@@ -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