Last active
September 1, 2024 16:07
-
-
Save stefaang/0a23a25460f65086cbec0db526e87b03 to your computer and use it in GitHub Desktop.
Hardware control script for PR2100/PR4100
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Post-init script for FreeNAS on Western Digital PR2100/PR4100 | |
# wdhws v1.0 by TFL | |
# | |
# BSD 3 LICENSE | |
# | |
# thanks unix stackexchange question 231975 | |
setup_tty() { | |
tty=/dev/cuau3 | |
exec 4<$tty 5>$tty | |
} | |
setup_i2c() { | |
# load kernel modules required for the temperature sensor on the RAM modules | |
kldload -n iicbus smbus smb ichsmb | |
} | |
send() { | |
setup_tty | |
# send a command to the PMC module and echo the answer | |
echo -ne "$1\r" >&5 | |
read ans <&4 | |
if [ "$ans" = "ALERT" ]; then | |
echo -ne ALERT >&2 | |
exit 2 | |
else | |
# keep this for debugging failing commands | |
if [ "$ans" = "ERR" ] || [ -z "$ans" ]; then | |
echo "CMD $1 gives ERR at $2" >&2 | |
send_empty | |
ans=$(send "$1" $(($2 + 1))) | |
#exit 1 | |
fi | |
fi | |
# only echo the result for retries ($2 not empty) | |
if [ ! -z $2 ]; then | |
echo "CMD $1 gives '$ans' at $2" >&2 | |
fi | |
echo $ans | |
send_empty | |
# deconstruct tty file pointers, otherwise this script breaks on sleep | |
exec 4<&- 5>&- | |
} | |
send_empty() { | |
# send a empty command to clear the output | |
echo -ne "\r" >&5 | |
read ignore <&4 | |
} | |
get_ncpu() { | |
# get the number of CPUs | |
sysctl -n hw.ncpu | |
} | |
get_coretemp() { | |
# get the CPU temperature and strip of the Celsius | |
sysctl -n dev.cpu.$1.temperature | cut -d'.' -f1 | |
} | |
get_disktemp() { | |
# get the disk $i temperature only if it is spinning | |
smartctl -n standby -A /dev/ada$1 | grep Temperature_Celsius | awk '{print $NF}' | |
} | |
get_ramtemp() { | |
# get the memory temperature from the I2C sensor | |
smbmsg -s 0x98 -c 0x0$1 -i 1 -F %d | |
} | |
get_pmc() { | |
# get a value from the PMC | |
# e.g. TMP returns TMP=25 --> 25 | |
send $1 | cut -d'=' -f2 | |
} | |
init() { | |
setup_tty | |
setup_i2c | |
echo "get system status and firmware" | |
send VER | |
send CFG | |
send STA | |
show_welcome | |
stop_powerled | |
} | |
show_welcome() { | |
# set welcome message | |
# maximum "xxx xxx xxx xxx " | |
send "LN1= FreeNAS " | |
send "LN2= go go go go go " | |
} | |
stop_powerled() { | |
# stop blinking power LED | |
send PLS=00 | |
send LED=00 # set to 01 to enable it | |
send BLK=00 | |
} | |
show_ip() { | |
send "LN1=Interface re$1" | |
ip=$(ifconfig re$1 | grep inet | awk '{printf $2}') | |
send "LN2=$ip" | |
} | |
monitor() { | |
lvl="COOL" | |
# check RPM (fan may get stuck) and convert hex to dec | |
fan=$(get_pmc FAN) | |
rpm=$((0x$(get_pmc RPM))) | |
echo "Got rpm $rpm" | |
if [ "$rpm" != ERR ]; then | |
if [ "$rpm" -lt 400 ]; then | |
echo "WARNING: low RPM - $rpm - clean dust!" | |
fi | |
fi | |
# check pmc | |
tmp=$((0x$(get_pmc TMP))) | |
if [ "$tmp" -gt 64 ]; then | |
lvl="HOT" | |
fi | |
# check disks [adjust this for PR2100!!] | |
for i in 0 1 2 3 ; do | |
tmp=$(get_disktemp $i) | |
echo "disk $i is $tmp" | |
if [ ! -z $tmp ] && [ "$tmp" -gt 40 ]; then | |
echo "Disk $i temperature is $tmp" | |
lvl="HOT" | |
fi | |
done | |
# check cpu | |
for i in $(seq $(get_ncpu)); do | |
tmp=$(get_coretemp $((i-1))) | |
echo "cpu $i is $tmp" | |
if [ "$tmp" -gt 50 ]; then | |
echo "CPU $i temperature is $tmp" | |
lvl="HOT" | |
fi | |
done | |
# check ram | |
for i in 0 1; do | |
tmp=$(get_ramtemp $i) | |
echo "ram temp is $tmp for $i" | |
if [ "$tmp" -gt 40 ]; then | |
echo "RAM $i temperature is $tmp" | |
lvl="HOT" | |
fi | |
done | |
echo "Temperature LVL is $lvl" | |
if [ "$lvl" == HOT ] ; then | |
if [ "$fan" != 40 ]; then | |
send FAN=40 | |
fi | |
else | |
if [ "$fan" != 20 ]; then | |
send FAN=20 | |
fi | |
fi | |
} | |
check_btn_pressed() { | |
btn=$(get_pmc ISR) | |
#echo "Btn is .$btn." | |
case $btn in | |
20*) | |
echo "Button up pressed!" | |
menu=$(( ($menu + 1) % 3 )) | |
;; | |
40*) | |
echo "Button down pressed!" | |
menu=$(( ($menu + 2) % 3 )) | |
;; | |
*) | |
return | |
esac | |
case "$menu" in | |
0) | |
show_welcome | |
;; | |
1) | |
show_ip 0 | |
;; | |
2) | |
show_ip 1 | |
;; | |
# if you add menu items here, update mod 3 uses above | |
esac | |
} | |
# initial setup | |
init | |
while true; do | |
# adjust fan speed every 30 seconds | |
monitor | |
# check for button presses | |
for i in $(seq 30); do | |
sleep 1 | |
check_btn_pressed | |
done | |
done |
Hey Everyone, have any of you moved to Scale from Core? If so, how did you handle hardware as this script appears to no longer work.
FYI for anyone looking for the Scale answer, Scale is now Debian Linux instead of FreeBSD. TrueNAS Core is FreeBSD. In any event, I had to change the tty from tty=/dev/cuau3 to tty=/dev/ttyS2. That appears to the correct setting for Linux on the PR4100.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey stefan! Thank you for your post on the forum and this script!
Running TrueNAS-13.0-U4, I had to change line 65 to
smartctl -n standby -A /dev/ada$1 | grep Temperature_Celsius | awk '{print $NF-1}'
In order to get the correct value for disk temperature