[Fixes and New Features] Fixed disk usage display, disk temperatures, disk and network activity, fan speed percentage display on OLED display, improved uptime format

Can you show your /etc/rockpi-sata.conf file?
And also a df -h command output.

conf

[fan]

When the temperature is above lv0 (35’C), the fan at 25% power,

and lv1 at 50% power, lv2 at 75% power, lv3 at 100% power.

When the temperature is below lv0, the fan is turned off.

You can change these values if necessary.

lv0 = 35
lv1 = 40
lv2 = 45
lv3 = 50

[key]

You can customize the function of the key, currently available functions are

slider: oled display next page

switch: fan turn on/off switch

reboot, poweroff

If you have any good suggestions for key functions,

please add an issue on https://setq.me/rockpi-sata

click = slider
twice = switch
press = reboot

[time]

twice: maximum time between double clicking (seconds)

press: long press time (seconds)

twice = 0.7
press = 1.8

[slider]

Whether the oled auto display next page and the time interval (seconds)

auto = true
time = 10

[oled]

Whether rotate the text of oled 180 degrees, whether use Fahrenheit

rotate = true
f-temp = false

[disk]

Mount points for disks to show space usage (separated with |)

space_usage_mnt_points = /media/a211b519-e330-483a-843d-6014622d662|/media/934efb34-6950-4b5d-ba2d-900c3e5444a

Mount points for disks to show I/O usage (separated with |)

Leave it blank (after the =) if you don’t want to use it

io_usage_mnt_points =

[network]

Name of the interfaces which should be measured (separated with |)

Leave it blank (after the =) if you don’t want to use it

Option ‘auto’ means select them automatically by their link status (every interface which link status is UP)

interfaces = eth0

df-h

Filesystem Size Used Avail Use% Mounted on
/dev/root 29G 3.8G 25G 14% /
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 28K 1.9G 1% /dev/shm
tmpfs 1.9G 9.6M 1.9G 1% /run
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mmcblk0p1 253M 49M 204M 20% /boot
/dev/sda 458G 73M 435G 1% /media/a211b519-e330-483a-843d-6014622d662
/dev/sdb 458G 81G 354G 19% /media/934efb34-6950-4b5d-ba2d-900c3e5444a
tmpfs 380M 0 380M 0% /run/user/1000

Thanks! They are looking good.
And please show me a rockpi-sata.conf file, when you add the mount points to the io_usage_mnt_points.

[fan]

When the temperature is above lv0 (35’C), the fan at 25% power,

and lv1 at 50% power, lv2 at 75% power, lv3 at 100% power.

When the temperature is below lv0, the fan is turned off.

You can change these values if necessary.

lv0 = 35
lv1 = 40
lv2 = 45
lv3 = 50

[key]

You can customize the function of the key, currently available functions are

slider: oled display next page

switch: fan turn on/off switch

reboot, poweroff

If you have any good suggestions for key functions,

please add an issue on https://setq.me/rockpi-sata

click = slider
twice = switch
press = poweroff

[time]

twice: maximum time between double clicking (seconds)

press: long press time (seconds)

twice = 0.7
press = 1.8

[slider]

Whether the oled auto display next page and the time interval (seconds)

auto = true
time = 10

[oled]

Whether rotate the text of oled 180 degrees, whether use Fahrenheit

rotate = true
f-temp = false

[disk]

Mount points for disks to show space usage (separated with |)

space_usage_mnt_points = /media/a211b519-e330-483a-843d-6014622d662|/media/934efb34-6950-4b5d-ba2d-900c3e5444a

Mount points for disks to show I/O usage (separated with |)

Leave it blank (after the =) if you don’t want to use it

io_usage_mnt_points = /media/a211b519-e330-483a-843d-6014622d662|/media/934efb34-6950-4b5d-ba2d-900c3e5444a

[network]

Name of the interfaces which should be measured (separated with |)

Leave it blank (after the =) if you don’t want to use it

Option ‘auto’ means select them automatically by their link status (every interface which link status is UP)

interfaces = eth0

I also think there should be nothing wrong with my settings, but every time I add io_usage_mnt_points, the button will be disabled

Yeah, you are right. It’s not really works. :frowning:
I will try to debug this when I will have more free time.

Thank you, I look forward to your next reply

I still couldn’t figure out why the button not work properly, but there is another new feature:
Display temperature of disks image:

1.0. You have to install smartctl, but not from the APT (sudo apt install smartctl), because of it’s too old.
1.1. Read this to install the newest version:
> Cannot Retrieve SMART Data - Quad SATA Hat

2.0. Update the configuration file:
2.1. There is a new option: disks_temp = true
2.2. Updated /etc/rockpi-sata.conf:

[fan]
# When the temperature is above lv0 (35'C), the fan at 25% power,
# and lv1 at 50% power, lv2 at 75% power, lv3 at 100% power.
# When the temperature is below lv0, the fan is turned off.
# You can change these values if necessary.
lv0 = 35
lv1 = 40
lv2 = 45
lv3 = 50

[key]
# You can customize the function of the key, currently available functions are
# slider: oled display next page
# switch: fan turn on/off switch
# reboot, poweroff
# If you have any good suggestions for key functions,
# please add an issue on https://setq.me/rockpi-sata
click = slider
twice = switch
press = poweroff

[time]
# twice: maximum time between double clicking (seconds)
# press: long press time (seconds)
twice = 0.7
press = 1.8

[slider]
# Whether the oled auto display next page and the time interval (seconds)
auto = true
time = 10

[oled]
# Whether rotate the text of oled 180 degrees, whether use Fahrenheit
rotate = true
f-temp = false

[disk]
# Mount points for disks to show space usage (separated with |)
space_usage_mnt_points = /mnt/raid1|/mnt/torrent|/mnt/torrent2

# Mount points for disks to show I/O usage (separated with |)
# Leave it blank (after the =) if you don't want to use it
io_usage_mnt_points =

# Detect automatically the disks and show their temperatures
disks_temp = true

[network]
# Name of the interfaces which should be measured (separated with |)
# Leave it blank (after the =) if you don't want to use it
# Option 'auto' means select them automatically by their link status (every interface which link status is UP)
interfaces =

3.0. Updated /usr/bin/rockpi-sata/misc.py:

#!/usr/bin/env python3
import re
import os
import sys
import time
import json
import subprocess
import RPi.GPIO as GPIO
import multiprocessing as mp
from collections import defaultdict
from configparser import ConfigParser

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(17, GPIO.OUT)
GPIO.output(17, GPIO.HIGH)

cmds = {
    'blk': "lsblk | awk '{print $1}'",
    #'up': "echo Uptime: `uptime | sed 's/.*up \\([^,]*\\), .*/\\1/'`",
    'up': "echo Up: $(uptime -p | sed 's/ years,/y/g;s/ year,/y/g;s/ months,/m/g;s/ month,/m/g;s/ weeks,/w/g;s/ week,/w/g;s/ days,/d/g;s/ day,/d/g;s/ hours,/h/g;s/ hour,/h/g;s/ minutes/m/g;s/ minute/m/g' | cut -d ' ' -f2-)",
    'temp': "cat /sys/class/thermal/thermal_zone0/temp",
    'ip': "hostname -I | awk '{printf \"IP %s\", $1}'",
    'cpu': "uptime | tr , . | awk '{printf \"CPU Load: %.2f%%\", $(NF-2)}'",
    'men': "free -m | awk 'NR==2{printf \"Mem: %s/%s MB\", $3,$2}'",
    'disk': "df -h | awk '$NF==\"/\"{printf \"Disk: %d/%d GB %s\", $3,$2,$5}'"
}

lv2dc = {'lv3': 100, 'lv2': 75, 'lv1': 50, 'lv0': 25}


# pin37(bcm26) sata0, pin22(bcm25) sata1
def set_mode(pin, mode):
    try:
        GPIO.setup(pin, GPIO.OUT)
        GPIO.output(pin, mode)
    except Exception as ex:
        print(ex)


def disk_turn_on():
    #blk1 = get_blk()
    set_mode(26, GPIO.HIGH)
    time.sleep(0.5)
    set_mode(25, GPIO.HIGH)
    wait_blk(10)
    #blk2 = get_blk()
    #conf['disk'] = sorted(list(set(blk2) - set(blk1)))


def disk_turn_off():
    set_mode(26, GPIO.LOW)
    time.sleep(0.5)
    set_mode(25, GPIO.LOW)


def check_output(cmd):
    return subprocess.check_output(cmd, shell=True).decode().strip()


def check_call(cmd):
    return subprocess.check_call(cmd, shell=True)


def wait_blk(t1=10):
    t = 0
    while t <= t1:
        try:
            check_call('lsblk /dev/sda > /dev/null 2>&1')
            check_call('lsblk /dev/sdb > /dev/null 2>&1')
            check_call('lsblk /dev/sdc > /dev/null 2>&1')
            check_call('lsblk /dev/sdd > /dev/null 2>&1')
        except Exception:
            time.sleep(0.1)
            t += 0.1
            continue
        else:
            time.sleep(0.5)
            break


def get_blk():
    return check_output(cmds['blk']).strip().split('\n')


def get_info(s):
    return check_output(cmds[s])


def get_cpu_temp():
    t = float(get_info('temp')) / 1000
    if conf['oled']['f-temp']:
        temp = "CPU Temp: {:.0f}°F".format(t * 1.8 + 32)
    else:
        temp = "CPU Temp: {:.1f}°C".format(t)
    return temp


def read_conf():
    conf = defaultdict(dict)

    try:
        cfg = ConfigParser()
        cfg.read('/etc/rockpi-sata.conf')
        # fan
        conf['fan']['lv0'] = cfg.getfloat('fan', 'lv0')
        conf['fan']['lv1'] = cfg.getfloat('fan', 'lv1')
        conf['fan']['lv2'] = cfg.getfloat('fan', 'lv2')
        conf['fan']['lv3'] = cfg.getfloat('fan', 'lv3')
        # key
        conf['key']['click'] = cfg.get('key', 'click')
        conf['key']['twice'] = cfg.get('key', 'twice')
        conf['key']['press'] = cfg.get('key', 'press')
        # time
        conf['time']['twice'] = cfg.getfloat('time', 'twice')
        conf['time']['press'] = cfg.getfloat('time', 'press')
        # other
        conf['slider']['auto'] = cfg.getboolean('slider', 'auto')
        conf['slider']['time'] = cfg.getfloat('slider', 'time')
        conf['oled']['rotate'] = cfg.getboolean('oled', 'rotate')
        conf['oled']['f-temp'] = cfg.getboolean('oled', 'f-temp')
        # disk
        conf['disk']['space_usage_mnt_points'] = cfg.get('disk', 'space_usage_mnt_points').split('|')
        conf['disk']['io_usage_mnt_points'] = cfg.get('disk', 'io_usage_mnt_points').split('|')
        conf['disk']['disks_temp'] = cfg.getboolean('disk', 'disks_temp')
        #conf['disk']['disks'] = get_disk_list()
        # network
        conf['network']['interfaces'] = cfg.get('network', 'interfaces').split('|')
    except Exception:
        # fan
        conf['fan']['lv0'] = 35
        conf['fan']['lv1'] = 40
        conf['fan']['lv2'] = 45
        conf['fan']['lv3'] = 50
        # key
        conf['key']['click'] = 'slider'
        conf['key']['twice'] = 'switch'
        conf['key']['press'] = 'none'
        # time
        conf['time']['twice'] = 0.7  # second
        conf['time']['press'] = 1.8
        # other
        conf['slider']['auto'] = True
        conf['slider']['time'] = 10  # second
        conf['oled']['rotate'] = False
        conf['oled']['f-temp'] = False
        # disk
        conf['disk']['space_usage_mnt_points'] = []
        conf['disk']['io_usage_mnt_points'] = []
        conf['disk']['disks_temp'] = False
        #conf['disk']['disks'] = []
        # network
        conf['network']['interfaces'] = []

    return conf


def read_key(pattern, size):
    s = ''
    while True:
        s = s[-size:] + str(GPIO.input(17))
        for t, p in pattern.items():
            if p.match(s):
                return t
        time.sleep(0.1)


def watch_key(q=None):
    size = int(conf['time']['press'] * 10)
    wait = int(conf['time']['twice'] * 10)
    pattern = {
        'click': re.compile(r'1+0+1{%d,}' % wait),
        'twice': re.compile(r'1+0+1+0+1{3,}'),
        'press': re.compile(r'1+0{%d,}' % size),
    }

    while True:
        q.put(read_key(pattern, size))


def get_interface_list():
    if len(conf['network']['interfaces']) == 1 and conf['network']['interfaces'][0] == '':
        return []

    if len(conf['network']['interfaces']) == 1 and conf['network']['interfaces'][0] == 'auto':
        interfaces = []
        cmd = "ip -o link show | awk '{print $2,$9}'"
        list = check_output(cmd).split('\n')
        for x in list:
            name_status = x.split(': ')
            if "UP" in name_status[1]:
                interfaces.append(name_status[0])

        interfaces.sort()

    else:
        interfaces = conf['network']['interfaces']

    return interfaces


def get_interface_rx_info(interface):
    cmd = "R1=$(cat /sys/class/net/" + interface + "/statistics/rx_bytes); sleep 1; R2=$(cat /sys/class/net/" + interface + "/statistics/rx_bytes); echo | awk -v r1=$R1 -v r2=$R2 '{printf \"rx: %.5f MB/s\", (r2 - r1) / 1024 / 1024}';"
    output = check_output(cmd)
    return output


def get_interface_tx_info(interface):
    cmd = "T1=$(cat /sys/class/net/" + interface + "/statistics/tx_bytes); sleep 1; T2=$(cat /sys/class/net/" + interface + "/statistics/tx_bytes); echo | awk -v t1=$T1 -v t2=$T2 '{printf \"tx: %.5f MB/s\", (t2 - t1) / 1024 / 1024}';"
    output = check_output(cmd)
    return output


def delete_disk_partition_number(disk):
    if "sd" in disk and disk[-1].isdigit():
        disk = disk[:-1]
    return disk


def get_disk_list(type):
    if len(conf['disk'][type]) == 1 and conf['disk'][type][0] == '':
        return []

    disks = []
    for x in conf['disk'][type]:
        cmd = "df -Bg | awk '$6==\"{}\" {{printf \"%s\", $1}}'".format(x)
        output = check_output(cmd).split('/')[-1]
        if output != '':
            disks.append(output)

    disks.sort()
    return disks


def get_disk_temp_info():
    if not conf['disk']['disks_temp']:
        return [(), ()]
    disks = list(check_output("ls /dev/sd* | grep -E \"[0-9]$\" | cut -f3 -d'/' | tr -d '0123456789'").split("\n"))
    disks_temp = {}
    for disk in disks:
        output = check_output(f"sudo smartctl -A /dev/{disk} -j")
        object = json.loads(output)
        disk_temp = object["temperature"]["current"]
        if conf['oled']['f-temp']:
            disk_temp = "{:.0f}°F".format(disk_temp * 1.8 + 32)
        else:
            disk_temp = "{}°C".format(disk_temp)
        disks_temp[disk] = disk_temp
    return list(zip(*disks_temp.items()))


def get_disk_io_read_info(disk):
    cmd = "R1=$(cat /sys/block/" + disk + "/stat | awk '{print $3}'); sleep 1; R2=$(cat /sys/block/" + disk + "/stat | awk '{print $3}'); echo | awk -v r1=$R1 -v r2=$R2 '{printf \"R: %.5f MB/s\", (r2 - r1) / 2 / 1024}';"
    output = check_output(cmd)
    return output


def get_disk_io_write_info(disk):
    cmd = "W1=$(cat /sys/block/" + disk + "/stat | awk '{print $7}'); sleep 1; W2=$(cat /sys/block/" + disk + "/stat | awk '{print $7}'); echo | awk -v w1=$W1 -v w2=$W2 '{printf \"W: %.5f MB/s\", (w2 - w1) / 2 / 1024}';"
    output = check_output(cmd)
    return output


def get_disk_info(cache={}):
    if not cache.get('time') or time.time() - cache['time'] > 30:
        info = {}
        cmd = "df -h | awk '$NF==\"/\"{printf \"%s\", $5}'"
        info['root'] = check_output(cmd)
        conf['disk']['disks'] = get_disk_list('space_usage_mnt_points')
        for x in conf['disk']['disks']:
            delete_disk_partition_number(x)
            cmd = "df -Bg | awk '$1==\"/dev/{}\" {{printf \"%s\", $5}}'".format(x)
            info[x] = check_output(cmd)
        cache['info'] = list(zip(*info.items()))
        cache['time'] = time.time()

    return cache['info']


def slider_next(pages):
    conf['idx'].value += 1
    return pages[conf['idx'].value % len(pages)]


def slider_sleep():
    time.sleep(conf['slider']['time'])


def fan_temp2dc(t):
    for lv, dc in lv2dc.items():
        if t >= conf['fan'][lv]:
            return dc
    return 0


def fan_switch():
    conf['run'].value = not(conf['run'].value)


def get_func(key):
    return conf['key'].get(key, 'none')


def open_w1_i2c():
    with open('/boot/config.txt', 'r') as f:
        content = f.read()

    if 'dtoverlay=w1-gpio' not in content:
        with open('/boot/config.txt', 'w') as f:
            f.write(content.strip() + '\ndtoverlay=w1-gpio')

    if 'dtparam=i2c1=on' not in content:
        with open('/boot/config.txt', 'w') as f:
            f.write(content.strip() + '\ndtparam=i2c1=on')

    os.system('/sbin/modprobe w1-gpio')
    os.system('/sbin/modprobe w1-therm')
    os.system('/sbin/modprobe i2c-dev')


conf = {'disk': [], 'idx': mp.Value('d', -1), 'run': mp.Value('d', 1)}
conf.update(read_conf())


if __name__ == '__main__':
    if sys.argv[-1] == 'open_w1_i2c':
        open_w1_i2c()

4.0. Updated /usr/bin/rockpi-sata/oled.py:

#!/usr/bin/env python3

import time
import misc
import fan
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

font = {
    '10': ImageFont.truetype('fonts/DejaVuSansMono-Bold.ttf', 10),
    '11': ImageFont.truetype('fonts/DejaVuSansMono-Bold.ttf', 11),
    '12': ImageFont.truetype('fonts/DejaVuSansMono-Bold.ttf', 12),
    '14': ImageFont.truetype('fonts/DejaVuSansMono-Bold.ttf', 14),
}

misc.set_mode(23, 0)
time.sleep(0.2)
misc.set_mode(23, 1)


def disp_init():
    disp = Adafruit_SSD1306.SSD1306_128_32(rst=None)
    [getattr(disp, x)() for x in ('begin', 'clear', 'display')]
    return disp


try:
    disp = disp_init()
except Exception:
    misc.open_w1_i2c()
    time.sleep(0.2)
    disp = disp_init()

image = Image.new('1', (disp.width, disp.height))
draw = ImageDraw.Draw(image)


def disp_show():
    im = image.rotate(180) if misc.conf['oled']['rotate'] else image
    disp.image(im)
    disp.display()
    draw.rectangle((0, 0, disp.width, disp.height), outline=0, fill=0)


def welcome():
    draw.text((0, 0), 'ROCK Pi SATA HAT', font=font['14'], fill=255)
    draw.text((32, 16), 'Loading...', font=font['12'], fill=255)
    disp_show()


def goodbye():
    draw.text((30, 8), 'Power off...', font=font['14'], fill=255)
    disp_show()
    time.sleep(2)
    disp_show()  # clear


def put_disk_info():
    k, v = misc.get_disk_info()
    text1 = 'Disk: {} {}'.format(k[0], v[0])

    if len(k) == 5:
        text2 = '{} {}  {} {}'.format(k[1], v[1], k[2], v[2])
        text3 = '{} {}  {} {}'.format(k[3], v[3], k[4], v[4])
        page = [
            {'xy': (0, -2), 'text': text1, 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': text2, 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': text3, 'fill': 255, 'font': font['11']},
        ]
    elif len(k) == 4:
        text2 = '{} {}  {} {}'.format(k[1], v[1], k[2], v[2])
        text3 = '{} {}'.format(k[3], v[3])
        page = [
            {'xy': (0, -2), 'text': text1, 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': text2, 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': text3, 'fill': 255, 'font': font['11']},
        ]
    elif len(k) == 3:
        text2 = '{} {}  {} {}'.format(k[1], v[1], k[2], v[2])
        page = [
            {'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['12']},
            {'xy': (0, 18), 'text': text2, 'fill': 255, 'font': font['12']},
        ]
    elif len(k) == 2:
        text2 = '{} {}'.format(k[1], v[1])
        page = [
            {'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['12']},
            {'xy': (0, 18), 'text': text2, 'fill': 255, 'font': font['12']},
        ]
    else:
        page = [{'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['14']}]

    return page


def put_disk_temp_info(pages_len):
    page = {}
    k, v = misc.get_disk_temp_info()

    if len(k) == 0:
        return page

    text1 = 'Disks Temp:'

    if len(k) == 4:
        text2 = '{} {}  {} {}'.format(k[0], v[0], k[1], v[1])
        text3 = '{} {}  {} {}'.format(k[2], v[2], k[3], v[3])
        page[pages_len] = [
            {'xy': (0, -2), 'text': text1, 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': text2, 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': text3, 'fill': 255, 'font': font['11']},
        ]
    elif len(k) == 3:
        text2 = '{} {}  {} {}'.format(k[0], v[0], k[1], v[1])
        text3 = '{} {}'.format(k[2], v[2])
        page[pages_len] = [
            {'xy': (0, -2), 'text': text1, 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': text2, 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': text3, 'fill': 255, 'font': font['11']},
        ]
    elif len(k) == 2:
        text2 = '{} {}  {} {}'.format(k[0], v[0], k[1], v[1])
        page[pages_len] = [
            {'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['12']},
            {'xy': (0, 18), 'text': text2, 'fill': 255, 'font': font['12']},
        ]
    elif len(k) == 1:
        text2 = '{}'.format(k[0], v[0])
        page[pages_len] = [
            {'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['12']},
            {'xy': (0, 18), 'text': text2, 'fill': 255, 'font': font['12']},
        ]
    else:
        page[pages_len] = [{'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['14']}]

    return page


def put_disk_io_info(pages_len):
    pages = {}
    page_index = pages_len
    disks = misc.get_disk_list('io_usage_mnt_points')

    for x in disks:
        x = misc.delete_disk_partition_number(x)

        pages[page_index] = [
            {'xy': (0, -2), 'text': 'Disk (' + x + '):', 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': misc.get_disk_io_read_info(x), 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': misc.get_disk_io_write_info(x), 'fill': 255, 'font': font['11']}
        ]
        page_index = page_index + 1

    return pages


def put_interface_info(pages_len):
    pages = {}
    page_index = pages_len
    interfaces = misc.get_interface_list()

    for x in interfaces:
        pages[page_index] = [
            {'xy': (0, -2), 'text': 'Network (' + x + '):', 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': misc.get_interface_rx_info(x), 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': misc.get_interface_tx_info(x), 'fill': 255, 'font': font['11']}
        ]
        page_index = page_index + 1

    return pages


def gen_pages():
    pages = {
        0: [
            {'xy': (0, -2), 'text': misc.get_info('up'), 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': misc.get_cpu_temp(), 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': misc.get_info('ip'), 'fill': 255, 'font': font['11']}
        ],
        1: [
            #{'xy': (0, 2), 'text': misc.get_info('cpu'), 'fill': 255, 'font': font['12']},
            #{'xy': (0, 18), 'text': misc.get_info('men'), 'fill': 255, 'font': font['12']}
            {'xy': (0, -2), 'text': 'Fan speed: ' + str(fan.get_dc()) + '%', 'fill': 255, 'font': font['11']},
            {'xy': (0, 10), 'text': misc.get_info('cpu'), 'fill': 255, 'font': font['11']},
            {'xy': (0, 21), 'text': misc.get_info('men'), 'fill': 255, 'font': font['11']},
        ],
        2: put_disk_info()
    }

    pages.update(put_interface_info(len(pages)))
    pages.update(put_disk_temp_info(len(pages)))
    pages.update(put_disk_io_info(len(pages)))

    return pages


def slider(lock):
    with lock:
        for item in misc.slider_next(gen_pages()):
            draw.text(**item)
        disp_show()


def auto_slider(lock):
    while misc.conf['slider']['auto']:
        slider(lock)
        misc.slider_sleep()
    else:
        slider(lock)
1 Like

Hello, glad to see you again, I have installed smartmontools 7.1 and also have updated the firmware, together are very normal, but after installing your latest configuration file settings, the hard disk is lost, oled dead. After restoring the default 3 configuration files, everything is normal again. I want to ask the misc.py and oled.py files need me to make changes?

The only difference with your rockpi-sata file is that my drive is automatically mounted under /media, not /mnt

I see your last picture shows 4 hard drives, did you not do raid? I did raid 0 on my hard drive, according to this link (Setting up HARDWARE RAID with QUAD SATA-HAT (jms561 controller)), and I have succeeded raid and used it for a while.

This config file just an example to the new option/format.
You have to replace my mount points and settings with yours.

And also I found two indentation errors, I fixed them in the misc.py.
2021-04-28: And one is fixed in oled.py.
Please try it now.

I use software (mdadm) RAID, so my OS sees two physical disks.

This update is fantastic! Thank you! I love being able to see the disk temperatures and the formatting on the screen looks way better.

I’m still only able to get the “Disk: root 57%” reading. Have you been able to fully debug that yet?

Also, is it possible at some point to add an area to the config file that let’s you define what the OLED says on boot and shutdown? It would be fun to have it say “Hello Joe” or “See You Soon”. But not priority, haha, obviously just fun.

1 Like

Thank you for your reply!
I am happy I could share and develop a little bit on the code for the community!

You must add your mount points into /etc/rockpi-sata.conf file.

Yes, it’s possible, but I didn’t develop this feature. Because of the text positionating is not calculated automatically (maybe you can calculate it from the length of the string).

But there is an easier way:

  1. Open the oled.py file for editing.
    1. line: welcome() function. Over here you can change the text
    1. line goodbye() function. Over here you can change the text.
  2. You should calculate the new coordinates for the longer/shorter text for center alignment. So, play with the XY coordinates (0,0 means the left top corner if I rememer correctly).

Thanks for that. I had put my mount points in incorrectly, so it wasn’t populating it at all. Now it looks great!

And on the second part, it’s hilarious and awesome. My NAS now says all sorts of fun stuff to me on startup and shutdown.

You’re awesome!

I’m still working out getting my root % to stop increasing, but that’s not directly related to this, so I’ll keep it to the other thread.

1 Like

Is there an equivalent for the rockpi-penta hat? Do you have a github repo with these modifications?

Thanks !

There is a github repo and &setq merged my code into the main code:
https://github.com/akgnah/rockpi-sata

I think the code of rockpi-penta HAT is also coded in similar way (in Python), perhaps you can “merge” the codes into one.

The github repo I have found for the penta hat is:

I have done some playing with this and have done a merge of RayMondDrakon’s Quad SATA HAT code (with some modifications) with it. Still playing with it a bit, but basically (with the exception that I think the switch on my top_board is not functional) it seems to function.

1 Like

I have put the code up in the article: Penta SATA HAT enhanced display (oled, I/O, temp) and operation (button, fan)

1 Like