Add ROCK 5C service and monitoring setup
This commit is contained in:
8
.env.example
Normal file
8
.env.example
Normal file
@@ -0,0 +1,8 @@
|
||||
# ROCK 5C + Radxa Penta SATA HAT Top Board
|
||||
SDA=I2C8_SDA_M2
|
||||
SCL=I2C8_SCL_M2
|
||||
OLED_RESET=GPIO1_A5
|
||||
PWMCHIP=1
|
||||
BUTTON_CHIP=4
|
||||
BUTTON_LINE=11
|
||||
HARDWARE_PWM=1
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.env
|
||||
.venv/
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
77
README.md
77
README.md
@@ -0,0 +1,77 @@
|
||||
# Radxa Penta SATA HAT controller on ROCK 5C
|
||||
|
||||
Local ROCK 5C setup for the Radxa Penta SATA HAT Top Board.
|
||||
|
||||
It runs the existing Python OLED/fan controller as a systemd service and can
|
||||
export fan/temperature state through node_exporter's textfile collector.
|
||||
|
||||
## ROCK 5C hardware setup
|
||||
|
||||
The current host uses these device-tree overlays:
|
||||
|
||||
- `rk3588-i2c8-m2`
|
||||
- `rk3588-pwm14-m1`
|
||||
|
||||
The OLED is an SSD1306 on `/dev/i2c-8` at address `0x3c`. The HAT fan
|
||||
uses hardware PWM exposed as `/sys/class/pwm/pwmchip1/pwm0`.
|
||||
|
||||
Copy the board environment before starting the service:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
The service intentionally runs as root because the controller needs I2C,
|
||||
GPIO and PWM access.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Ubuntu packages:
|
||||
|
||||
```bash
|
||||
sudo apt install python3-virtualenv python3-libgpiod gpiod
|
||||
```
|
||||
|
||||
Create the virtualenv with system packages available and install Python
|
||||
dependencies:
|
||||
|
||||
```bash
|
||||
virtualenv --system-site-packages .venv
|
||||
.venv/bin/pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## systemd
|
||||
|
||||
The unit currently assumes this repository is located at
|
||||
`/home/ubuntu/radxa-hat`.
|
||||
|
||||
```bash
|
||||
sudo cp radxa-hat.service /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now radxa-hat.service
|
||||
systemctl status radxa-hat.service
|
||||
```
|
||||
|
||||
## Prometheus / node_exporter
|
||||
|
||||
`export-prometheus.sh` writes
|
||||
`/var/lib/node_exporter/textfile_collector/radxa_hat.prom`.
|
||||
|
||||
The exported values include:
|
||||
|
||||
- `radxa_hat_service_up`
|
||||
- `radxa_hat_oled_i2c_present`
|
||||
- `radxa_hat_cpu_temperature_celsius`
|
||||
- `radxa_hat_pwm_duty_ratio` — raw kernel PWM duty
|
||||
- `radxa_hat_fan_command_ratio` — effective fan command, corrected for the
|
||||
inverted HAT PWM mapping
|
||||
|
||||
Install the timer with:
|
||||
|
||||
```bash
|
||||
sudo cp radxa-hat-metrics.service radxa-hat-metrics.timer /etc/systemd/system/
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now radxa-hat-metrics.timer
|
||||
```
|
||||
|
||||
The timer refreshes metrics every 15 seconds.
|
||||
|
||||
68
export-prometheus.sh
Executable file
68
export-prometheus.sh
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
OUTDIR=/var/lib/node_exporter/textfile_collector
|
||||
OUT="$OUTDIR/radxa_hat.prom"
|
||||
TMP="$OUT.tmp.$$"
|
||||
PWM=/sys/class/pwm/pwmchip1/pwm0
|
||||
|
||||
mkdir -p "$OUTDIR"
|
||||
|
||||
service_up=0
|
||||
systemctl is-active --quiet radxa-hat.service && service_up=1
|
||||
i2c_present=0
|
||||
[ -e /dev/i2c-8 ] && i2c_present=1
|
||||
|
||||
temp_c="NaN"
|
||||
if [ -r /sys/class/thermal/thermal_zone0/temp ]; then
|
||||
raw=$(cat /sys/class/thermal/thermal_zone0/temp)
|
||||
temp_c=$(awk -v v="$raw" 'BEGIN { printf "%.3f", v/1000 }')
|
||||
fi
|
||||
period=0
|
||||
duty=0
|
||||
enabled=0
|
||||
polarity="unknown"
|
||||
[ -r "$PWM/period" ] && period=$(cat "$PWM/period")
|
||||
[ -r "$PWM/duty_cycle" ] && duty=$(cat "$PWM/duty_cycle")
|
||||
[ -r "$PWM/enable" ] && enabled=$(cat "$PWM/enable")
|
||||
[ -r "$PWM/polarity" ] && polarity=$(cat "$PWM/polarity")
|
||||
|
||||
duty_ratio="NaN"
|
||||
fan_command_ratio="NaN"
|
||||
if [ "$period" -gt 0 ] 2>/dev/null; then
|
||||
duty_ratio=$(awk -v d="$duty" -v p="$period" 'BEGIN { printf "%.6f", d/p }')
|
||||
fan_command_ratio=$(awk -v d="$duty" -v p="$period" 'BEGIN { printf "%.6f", 1-(d/p) }')
|
||||
fi
|
||||
|
||||
cat >"$TMP" <<EOF
|
||||
# HELP radxa_hat_service_up Whether radxa-hat.service is active.
|
||||
# TYPE radxa_hat_service_up gauge
|
||||
radxa_hat_service_up $service_up
|
||||
# HELP radxa_hat_oled_i2c_present Whether the HAT I2C bus device exists.
|
||||
# TYPE radxa_hat_oled_i2c_present gauge
|
||||
radxa_hat_oled_i2c_present $i2c_present
|
||||
# HELP radxa_hat_cpu_temperature_celsius CPU temperature used by the fan controller.
|
||||
# TYPE radxa_hat_cpu_temperature_celsius gauge
|
||||
radxa_hat_cpu_temperature_celsius $temp_c
|
||||
# HELP radxa_hat_pwm_enabled Kernel PWM channel enable state.
|
||||
# TYPE radxa_hat_pwm_enabled gauge
|
||||
radxa_hat_pwm_enabled $enabled
|
||||
# HELP radxa_hat_pwm_period_nanoseconds Raw PWM period from sysfs.
|
||||
# TYPE radxa_hat_pwm_period_nanoseconds gauge
|
||||
radxa_hat_pwm_period_nanoseconds $period
|
||||
# HELP radxa_hat_pwm_duty_cycle_nanoseconds Raw PWM duty cycle from sysfs.
|
||||
# TYPE radxa_hat_pwm_duty_cycle_nanoseconds gauge
|
||||
radxa_hat_pwm_duty_cycle_nanoseconds $duty
|
||||
# HELP radxa_hat_pwm_duty_ratio Raw sysfs duty divided by period.
|
||||
# TYPE radxa_hat_pwm_duty_ratio gauge
|
||||
radxa_hat_pwm_duty_ratio $duty_ratio
|
||||
# HELP radxa_hat_fan_command_ratio Effective fan command ratio for the inverted HAT PWM, 0=minimum/off and 1=full.
|
||||
# TYPE radxa_hat_fan_command_ratio gauge
|
||||
radxa_hat_fan_command_ratio $fan_command_ratio
|
||||
# HELP radxa_hat_pwm_polarity_info PWM polarity information.
|
||||
# TYPE radxa_hat_pwm_polarity_info gauge
|
||||
radxa_hat_pwm_polarity_info{polarity="$polarity"} 1
|
||||
EOF
|
||||
|
||||
chmod 0644 "$TMP"
|
||||
mv -f "$TMP" "$OUT"
|
||||
3
misc.py
3
misc.py
@@ -53,7 +53,8 @@ def read_conf():
|
||||
|
||||
try:
|
||||
cfg = ConfigParser()
|
||||
cfg.read('/etc/rockpi-penta.conf')
|
||||
#cfg.read('/etc/rockpi-penta.conf')
|
||||
cfg.read('./rockpi-penta.conf')
|
||||
# fan
|
||||
conf['fan']['lv0'] = cfg.getfloat('fan', 'lv0')
|
||||
conf['fan']['lv1'] = cfg.getfloat('fan', 'lv1')
|
||||
|
||||
8
radxa-hat-metrics.service
Normal file
8
radxa-hat-metrics.service
Normal file
@@ -0,0 +1,8 @@
|
||||
[Unit]
|
||||
Description=Export Radxa HAT metrics for node_exporter
|
||||
After=radxa-hat.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
ExecStart=/home/ubuntu/radxa-hat/export-prometheus.sh
|
||||
11
radxa-hat-metrics.timer
Normal file
11
radxa-hat-metrics.timer
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Refresh Radxa HAT Prometheus metrics
|
||||
|
||||
[Timer]
|
||||
OnBootSec=20s
|
||||
OnUnitActiveSec=15s
|
||||
AccuracySec=1s
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
21
radxa-hat.service
Normal file
21
radxa-hat.service
Normal file
@@ -0,0 +1,21 @@
|
||||
[Unit]
|
||||
Description=Radxa Penta SATA HAT OLED/Fan Controller
|
||||
After=local-fs.target systemd-udev-settle.service
|
||||
Wants=systemd-udev-settle.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/home/ubuntu/radxa-hat
|
||||
EnvironmentFile=/home/ubuntu/radxa-hat/.env
|
||||
Environment=PYTHONUNBUFFERED=1
|
||||
ExecStartPre=/usr/bin/test -e /dev/i2c-8
|
||||
ExecStartPre=/usr/bin/test -d /sys/class/pwm/pwmchip1
|
||||
ExecStart=/home/ubuntu/radxa-hat/.venv/bin/python -u /home/ubuntu/radxa-hat/main.py
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
KillSignal=SIGINT
|
||||
TimeoutStopSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
adafruit-circuitpython-ssd1306
|
||||
pillow
|
||||
36
rockpi-penta.conf
Normal file
36
rockpi-penta.conf
Normal file
@@ -0,0 +1,36 @@
|
||||
[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://github.com/radxa/rockpi-penta/issues
|
||||
click = slider
|
||||
twice = switch
|
||||
press = none
|
||||
|
||||
[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 = false
|
||||
f-temp = false
|
||||
Reference in New Issue
Block a user