Skip to content

Instantly share code, notes, and snippets.

@stefaang
Last active September 1, 2024 16:07
Show Gist options
  • Save stefaang/0a23a25460f65086cbec0db526e87b03 to your computer and use it in GitHub Desktop.
Save stefaang/0a23a25460f65086cbec0db526e87b03 to your computer and use it in GitHub Desktop.
Hardware control script for PR2100/PR4100
#!/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
@superdupe
Copy link

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.

@superdupe
Copy link

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