made alpine-fan-control work
changes made after installing packages
/usr/lib/lua/model/cbi/alpine-fan-control.lua
-- Copyright 2008 Steven Barth <steven@midlink.org>
-- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
-- Licensed to the public under the Apache License 2.0.
local fs = require "nixio.fs"
local sys = require "luci.sys"
local m, s, p, ok
local cur_temp, cur_speed
local msg = translate("Service status:") .. " "
local service_running = (luci.sys.call("pgrep -f \"/alpine-fan-controller\" > /dev/null"))==0
if service_running then
msg = msg .. "<span style=\"color:green;font-weight:bold\">" .. translate("Active") .. "</span>"
else
msg = msg .. "<span style=\"color:red;font-weight:bold\">" .. translate("Inactive") .. "</span>"
end
msg = msg .. "<br /><br />" .. translate("Current temperature:") .. " "
function get_cur_temp()
local FILE_TEMP
local uci = (require "luci.model.uci").cursor()
local tmp_sens = uci:get("alpine-fan-control", "@alpine-fan-control[0]", "tmp_sens") or ""
if tmp_sens ~= "" then
FILE_TEMP = luci.sys.exec("grep -l -F " .. tmp_sens .. " /sys/class/thermal/thermal_zone*/type 2>/dev/null") or ""
if FILE_TEMP ~= "" then
FILE_TEMP = luci.sys.exec("dirname '" .. FILE_TEMP .. "' 2>/dev/null | xargs echo -n") or ""
FILE_TEMP = FILE_TEMP .. "/temp"
local cur_temp = luci.sys.exec("cat " .. FILE_TEMP .. " 2>/dev/null") or ""
if cur_temp ~= "" then
cur_temp = tonumber(cur_temp)
cur_temp = cur_temp / 1000.0
return tostring(cur_temp)
end
end
end
return ""
end
ok, cur_temp = pcall(get_cur_temp)
if ok and cur_temp ~= nil and cur_temp ~= "" then
msg = msg .. cur_temp .. " °C"
end
msg = msg .. "<br /><br />" .. translate("Current fan speed:") .. " "
function get_cur_speed()
local FILE_SPEED
local uci = (require "luci.model.uci").cursor()
local drv_speed_max = uci:get("alpine-fan-control", "@alpine-fan-control[0]", "drv_speed_max") or "255"
local fan_cont = uci:get("alpine-fan-control", "@alpine-fan-control[0]", "fan_cont") or ""
if fan_cont ~= "" then
FILE_SPEED = luci.sys.exec("grep -l -F " .. fan_cont .. " /sys/class/hwmon/hwmon*/name 2>/dev/null") or ""
if FILE_SPEED ~= "" then
FILE_SPEED = luci.sys.exec("dirname '" .. FILE_SPEED .. "' 2>/dev/null | xargs echo -n") or ""
FILE_SPEED = FILE_SPEED .. "/pwm1"
local cur_speed = luci.sys.exec("cat " .. FILE_SPEED .. " 2>/dev/null") or ""
if cur_speed ~= "" then
cur_speed = tonumber(cur_speed)
drv_speed_max = tonumber(drv_speed_max)
return tostring(math.floor(cur_speed * 100.0 / drv_speed_max))
end
end
end
return ""
end
ok, cur_speed = pcall(get_cur_speed)
if ok and cur_speed ~= nil and cur_speed ~= "" then
msg = msg .. cur_speed .. "%"
end
m = Map("alpine-fan-control", translate("Fan Control"), msg)
s = m:section(TypedSection, "alpine-fan-control", translate("Settings"))
s.addremove = false
s.anonymous = true
e = s:option(Flag, "enable", translate("Enabled"), translate("Enables or disables the fan control daemon."))
e.rmempty = false
function e.write(self, section, value)
if value == "1" then
luci.sys.call("/etc/init.d/alpine-fan-control start >/dev/null")
else
luci.sys.call("/etc/init.d/alpine-fan-control stop >/dev/null")
end
return Flag.write(self, section, value)
end
dbg = s:option(Flag, "debug", translate("Debug"), translate("Enables or disables debugging output."))
dbg.datatype = "uinteger"
dbg.default = "0"
dbg.rmempty = false
dbg.optional = false
min_temp = s:option(Value, "min_temp", translate("min_temp"), translate("Temperature for minimum fan state (Celsius)"))
min_temp.datatype = "uinteger"
min_temp.default = "40"
min_temp.rmempty = false
min_temp.optional = false
min_speed = s:option(Value, "min_speed", translate("min_speed"), translate("Fan speed at minimum fan state (Percents)"))
min_speed.datatype = "uinteger"
min_speed.default = "60"
min_speed.rmempty = false
min_speed.optional = false
med_temp = s:option(Value, "med_temp", translate("med_temp"), translate("Temperature for medium fan state (Celsius)"))
med_temp.datatype = "uinteger"
med_temp.default = "45"
med_temp.rmempty = false
med_temp.optional = false
med_speed = s:option(Value, "med_speed", translate("med_speed"), translate("Fan speed at medium fan state (Percents)"))
med_speed.datatype = "uinteger"
med_speed.default = "80"
med_speed.rmempty = false
med_speed.optional = false
max_temp = s:option(Value, "max_temp", translate("max_temp"), translate("Temperature for maximum fan state (Celsius)"))
max_temp.datatype = "uinteger"
max_temp.default = "50"
max_temp.rmempty = false
max_temp.optional = false
max_speed = s:option(Value, "max_speed", translate("max_speed"), translate("Fan speed at maximum fan state (default: 100%)"))
max_speed.datatype = "uinteger"
max_speed.default = "100"
max_speed.rmempty = false
max_speed.optional = false
interval = s:option(Value, "interval", translate("interval"), translate("Interval for hysteresis adjustment (seconds)"))
interval.datatype = "uinteger"
interval.default = "5"
interval.rmempty = false
interval.optional = false
temp_hyst = s:option(Value, "temp_hyst", translate("temp_hyst"), translate("Hysteresis value (Celsius)"))
temp_hyst.datatype = "integer"
temp_hyst.default = "0"
temp_hyst.rmempty = false
temp_hyst.optional = false
tmp_sens = s:option(Value, "tmp_sens", translate("tmp_sens"), translate("Temperature sensor name (default: tmp75)"))
tmp_sens.datatype = "string"
tmp_sens.default = "tmp75"
tmp_sens.rmempty = false
tmp_sens.optional = false
fan_cont = s:option(Value, "fan_cont", translate("fan_cont"), translate("Fan controller name (default: emc230)"))
fan_cont.datatype = "string"
fan_cont.default = "emc230"
fan_cont.rmempty = false
fan_cont.optional = false
return m
/usr/bin/alpine-fan-controller
#!/bin/sh
. /lib/functions.sh
CFGNAME=alpine-fan-control
function get_opt() {
local opt_name=$1
local def_value=$2
local config="@$CFGNAME[0]"
echo "$( uci_get $CFGNAME "$config" $opt_name $def_value )"
}
# set temps (in degrees C) and corresponding fan speeds
# in ascending order and with the same amount of values
TEMP_MIN=$( get_opt min_temp 40 )
SPEED_MIN=$( get_opt min_speed 60 )
TEMP_MED=$( get_opt med_temp 45 )
SPEED_MED=$( get_opt med_speed 80 )
TEMP_MAX=$( get_opt max_temp 50 )
SPEED_MAX=$( get_opt max_speed 100 )
TEMP_SENSOR=$( get_opt tmp_sens tmp75 )
FAN_CONT=$( get_opt fan_cont emc230 )
HYSTERESIS=$( get_opt temp_hyst 0 )
SLEEP_INTERVAL=$( get_opt interval 5 )
DEBUG=$( get_opt debug 0 )
DRV_SPEED_MIN=$( get_opt drv_speed_min 0 )
DRV_SPEED_MAX=$( get_opt drv_speed_max 180 )
CFG_SPEED_MAX=180
LOGPREFIX="alpine-fan-controller"
TEMP_AT_LAST_SPEED_CHANGE=0
function log_error {
logger "$LOGPREFIX: ERROR: $1"
}
function log_debug {
if [ "$DEBUG" = "1" ]; then
logger "$LOGPREFIX: $1"
fi
}
if [ -z "$TEMP_MED" ]; then
log_error "Cannot read option 'med_temp' form config!"
exit 1
fi
# checking for privileges
if [ $UID -ne 0 ]; then
log_error "Writing to sysfs requires privileges, relaunch as root!"
echo "Writing to sysfs requires privileges, relaunch as root"
exit 1
fi
OPTLIST=""
OPTLIST="$OPTLIST [$TEMP_MIN $SPEED_MIN]"
OPTLIST="$OPTLIST [$TEMP_MED $SPEED_MED]"
OPTLIST="$OPTLIST [$TEMP_MAX $SPEED_MAX]"
OPTLIST="$OPTLIST $HYSTERESIS $SLEEP_INTERVAL $DEBUG"
OPTLIST="$OPTLIST $TEMP_SENSOR $FAN_CONT"
# Perform conversion to millidegrees Celsius
TEMP_MIN=$(( $TEMP_MIN * 1000 ))
TEMP_MED=$(( $TEMP_MED * 1000 ))
TEMP_MAX=$(( $TEMP_MAX * 1000 ))
FILE_SPEED=$( grep -l -F $FAN_CONT /sys/class/hwmon/hwmon*/name 2>/dev/null )
[ -f "$FILE_SPEED" ] || { log_error "fan controller $FAN_CONT not found" ; exit 1; }
FILE_SPEED=$( dirname "$FILE_SPEED" 2>/dev/null )
FILE_SPEED=$FILE_SPEED/pwm1
[ -f "$FILE_SPEED" ] || { log_error "Fan controller $FAN_CONT not found" ; exit 1; }
FILE_TEMP=$( grep -l -F $TEMP_SENSOR /sys/class/thermal/thermal_zone*/type 2>/dev/null )
[ -f "$FILE_TEMP" ] || { log_error "thermal sensor $TEMP_SENSOR not found" ; exit 1; }
FILE_TEMP=$( dirname "$FILE_TEMP" 2>/dev/null )
FILE_TEMP=$FILE_TEMP/temp
[ -f "$FILE_TEMP" ] || { log_error "Thermal sensor $TEMP_SENSOR not found" ; exit 1; }
function get_speed {
local speed=$(cat $FILE_SPEED)
speed=$(( $CFG_SPEED_MAX * $speed / $DRV_SPEED_MAX ))
echo $speed
}
function internal_set_speed {
local speed=$1
local value=$(( $DRV_SPEED_MAX * $speed / $CFG_SPEED_MAX ))
[ $value -lt $DRV_SPEED_MIN ] && value=$DRV_SPEED_MIN
[ $value -gt $DRV_SPEED_MAX ] && value=$DRV_SPEED_MAX
echo $value > $FILE_SPEED
}
PREV_SET_SPEED=
function set_speed {
local NEW_SPEED=$1
local interpolated=$2
local CUR_SPEED
local TEMP tmp
[ "$NEW_SPEED" = "$PREV_SET_SPEED" ] && return
CUR_SPEED=$( get_speed )
log_debug "current speed: $CUR_SPEED, requested to set speed to $NEW_SPEED"
TEMP=$(cat $FILE_TEMP)
[ "$interpolated" = "1" ] && log_debug "interpolated speed value for temperature $TEMP is: $NEW_SPEED"
tmp=$TEMP_AT_LAST_SPEED_CHANGE
if [ -z "$tmp" ] || [ "$TEMP" -gt "$tmp" ] || [ $(( TEMP + HYSTERESIS )) -le "$tmp" ]; then
log_debug "current temp: $TEMP, temp at last change was $TEMP_AT_LAST_SPEED_CHANGE, changing speed to $NEW_SPEED"
internal_set_speed $NEW_SPEED
TEMP_AT_LAST_SPEED_CHANGE=$TEMP
else
log_debug "not changing speed, we just did at $TEMP_AT_LAST_SPEED_CHANGE, next change when below $((TEMP_AT_LAST_SPEED_CHANGE - HYSTERESIS))"
fi
PREV_SET_SPEED=$NEW_SPEED
}
function set_speed_adv {
# interpolate linearly
local LOWERTEMP=$1
local LOWERSPEED=$2
local HIGHERTEMP=$3
local HIGHERSPEED=$4
local TEMP=$5
[ -z "$TEMP" ] && TEMP=$(cat $FILE_TEMP)
local value=$(( ( $TEMP - $LOWERTEMP ) * ( $HIGHERSPEED - $LOWERSPEED ) ))
local SPEED=$(( $value / ( $HIGHERTEMP - $LOWERTEMP ) + $LOWERSPEED ))
set_speed "$SPEED" 1
}
TEMP_PREV=
function interpolate_speed {
local TEMP=$(cat $FILE_TEMP)
if [ "$TEMP" != "$TEMP_PREV" ]; then
log_debug "current temp: $TEMP"
TEMP_PREV=$TEMP
fi
if [ $TEMP -le $TEMP_MIN ]; then
# below first point in list, set to min speed
set_speed $SPEED_MIN
return
fi
if [ $TEMP -gt $TEMP_MAX ]; then
# above last point in list, set to max speed
set_speed $SPEED_MAX
return
fi
if [ $TEMP -le $TEMP_MAX ]; then
set_speed_adv $TEMP_MED $SPEED_MED $TEMP_MAX $SPEED_MAX $TEMP
return
fi
if [ $TEMP -le $TEMP_MED ]; then
set_speed_adv $TEMP_MIN $SPEED_MIN $TEMP_MED $SPEED_MED $TEMP
return
fi
}
function reset_on_exit {
echo "exiting, going to max fan speed for safety..."
internal_set_speed 100
exit 0
}
# always try to reset fans on exit
trap "reset_on_exit" SIGINT SIGTERM
function run_daemon {
while true; do
interpolate_speed
sleep $SLEEP_INTERVAL
done
}
logger "$LOGPREFIX: run daemon:" $OPTLIST
# finally start the loop
run_daemon
/etc/config/alpine-fan-control
config alpine-fan-control
option enable '1'
option debug '0'
option min_temp '40'
option min_speed '20'
option med_temp '45'
option med_speed '50'
option max_temp '50'
option max_speed '100'
option interval '5'
option temp_hyst '0'
option tmp_sens 'cpu0'
option fan_cont 'emc230'
option drv_speed_min '0'
option drv_speed_max '180'