<reponame>WillVan/fanshim-python
#!/usr/bin/env python3
from fanshim import FanShim
from threading import Lock
import colorsys
import psutil
import argparse
import time
import signal
import sys


parser = argparse.ArgumentParser()
parser.add_argument('--off-threshold', type=float, default=55.0, help='Temperature threshold in degrees C to enable fan')
parser.add_argument('--on-threshold', type=float, default=65.0, help='Temperature threshold in degrees C to disable fan')
parser.add_argument('--low-temp', type=float, default=None, help='Temperature at which the LED is greeen')
parser.add_argument('--high-temp', type=float, default=None, help='Temperature for which LED is red')
parser.add_argument('--delay', type=float, default=2.0, help='Delay, in seconds, between temperature readings')
parser.add_argument('--preempt', action='store_true', default=False, help='Monitor CPU frequency and activate cooling premptively')
parser.add_argument('--verbose', action='store_true', default=False, help='Output temp and fan status messages')
parser.add_argument('--nobutton', action='store_true', default=False, help='Disable button input')
parser.add_argument('--noled', action='store_true', default=False, help='Disable LED control')
parser.add_argument('--brightness', type=float, default=255.0, help='LED brightness, from 0 to 255')
parser.add_argument('--extended-colours', action='store_true', default=False, help='Extend LED colours for outside of normal low to high range')

args = parser.parse_args()


def clean_exit(signum, frame):
    set_fan(False)
    if not args.noled:
        fanshim.set_light(0, 0, 0)
    sys.exit(0)


def update_led_temperature(temp):
    led_busy.acquire()
    temp = float(temp)
    if temp < args.low_temp and args.extended_colours:
        # Between minimum temp and low temp, set LED to blue through to green
        temp -= min_temp
        temp /= float(args.low_temp - min_temp)
        temp  = max(0, temp)
        hue   = (120.0 / 360.0) + ((1.0 - temp) * 120.0 / 360.0)
    elif temp > args.high_temp and args.extended_colours:
        # Between high temp and maximum temp, set LED to red through to magenta
        temp -= args.high_temp
        temp /= float(max_temp - args.high_temp)
        temp  = min(1, temp)
        hue   = 1.0 - (temp * 60.0 / 360.0)
    else:
        # In the normal low temp to high temp range, set LED to green through to red
        temp -= args.low_temp
        temp /= float(args.high_temp - args.low_temp)
        temp = max(0, min(1, temp))
        hue   = (1.0 - temp) * 120.0 / 360.0

    r, g, b = [int(c * 255.0) for c in colorsys.hsv_to_rgb(hue, 1.0, args.brightness / 255.0)]
    fanshim.set_light(r, g, b)
    led_busy.release()


def get_cpu_temp():
    with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f : 
        x = int(f.read()) / 1000
    return x

def get_cpu_freq():
    freq = psutil.cpu_freq()
    return freq


def set_fan(status):
    global enabled
    changed = False
    if status != enabled:
        changed = True
        fanshim.set_fan(status)
    enabled = status
    return changed


def set_automatic(status):
    global armed, last_change
    armed = status
    last_change = 0


fanshim = FanShim(disable_button=args.nobutton, disable_led=args.noled)
fanshim.set_hold_time(1.0)
fanshim.set_fan(False)
armed = True
enabled = False
led_busy = Lock()
enable = False
is_fast = False
last_change = 0
min_temp = 30
max_temp = 85
signal.signal(signal.SIGTERM, clean_exit)

if args.noled:
    led_busy.acquire()
    fanshim.set_light(0, 0, 0)
    led_busy.release()

if args.low_temp is None:
    args.low_temp = args.off_threshold

if args.high_temp is None:
    args.high_temp = args.on_threshold

if not args.nobutton:
    @fanshim.on_release()
    def release_handler(was_held):
        global armed
        if was_held:
            set_automatic(not armed)
        elif not armed:
            set_fan(not enabled)

    @fanshim.on_hold()
    def held_handler():
        global led_busy
        if args.noled:
            return
        led_busy.acquire()
        for _ in range(3):
            fanshim.set_light(0, 0, 255)
            time.sleep(0.04)
            fanshim.set_light(0, 0, 0)
            time.sleep(0.04)
        led_busy.release()


try:
    while True:
        t = get_cpu_temp()
        f = get_cpu_freq()
        was_fast = is_fast
        is_fast = (int(f.current) == int(f.max))
        if args.verbose:
            print("Current: {:05.02f} Target: {:05.02f} Freq {: 5.02f} Automatic: {} On: {}".format(t, args.off_threshold, f.current / 1000.0, armed, enabled))

        if args.preempt and is_fast and was_fast:
            enable = True
        elif armed:
            if t >= args.on_threshold:
                enable = True
            elif t <= args.off_threshold:
                enable = False

            if set_fan(enable):
                last_change = t

        if not args.noled:
            update_led_temperature(t)

        time.sleep(args.delay)
except KeyboardInterrupt:
    pass

#!/usr/bin/env python3
from fanshim import FanShim
from threading import Lock
import colorsys
import psutil
import argparse
import time
import signal
import sys


parser = argparse.ArgumentParser()
parser.add_argument('--off-threshold', type=float, default=55.0, help='Temperature threshold in degrees C to enable fan')
parser.add_argument('--on-threshold', type=float, default=65.0, help='Temperature threshold in degrees C to disable fan')
parser.add_argument('--low-temp', type=float, default=None, help='Temperature at which the LED is greeen')
parser.add_argument('--high-temp', type=float, default=None, help='Temperature for which LED is red')
parser.add_argument('--delay', type=float, default=2.0, help='Delay, in seconds, between temperature readings')
parser.add_argument('--preempt', action='store_true', default=False, help='Monitor CPU frequency and activate cooling premptively')
parser.add_argument('--verbose', action='store_true', default=False, help='Output temp and fan status messages')
parser.add_argument('--nobutton', action='store_true', default=False, help='Disable button input')
parser.add_argument('--noled', action='store_true', default=False, help='Disable LED control')
parser.add_argument('--brightness', type=float, default=255.0, help='LED brightness, from 0 to 255')
parser.add_argument('--extended-colours', action='store_true', default=False, help='Extend LED colours for outside of normal low to high range')

args = parser.parse_args()


def clean_exit(signum, frame):
    set_fan(False)
    if not args.noled:
        fanshim.set_light(0, 0, 0)
    sys.exit(0)


def update_led_temperature(temp):
    led_busy.acquire()
    temp = float(temp)
    if temp < args.low_temp and args.extended_colours:
        # Between minimum temp and low temp, set LED to blue through to green
        temp -= min_temp
        temp /= float(args.low_temp - min_temp)
        temp  = max(0, temp)
        hue   = (120.0 / 360.0) + ((1.0 - temp) * 120.0 / 360.0)
    elif temp > args.high_temp and args.extended_colours:
        # Between high temp and maximum temp, set LED to red through to magenta
        temp -= args.high_temp
        temp /= float(max_temp - args.high_temp)
        temp  = min(1, temp)
        hue   = 1.0 - (temp * 60.0 / 360.0)
    else:
        # In the normal low temp to high temp range, set LED to green through to red
        temp -= args.low_temp
        temp /= float(args.high_temp - args.low_temp)
        temp = max(0, min(1, temp))
        hue   = (1.0 - temp) * 120.0 / 360.0

    r, g, b = [int(c * 255.0) for c in colorsys.hsv_to_rgb(hue, 1.0, args.brightness / 255.0)]
    fanshim.set_light(r, g, b)
    led_busy.release()


def get_cpu_temp():
    with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f : 
        x = int(f.read()) / 1000
    return x

def get_cpu_freq():
    freq = psutil.cpu_freq()
    return freq


def set_fan(status):
    global enabled
    changed = False
    if status != enabled:
        changed = True
        fanshim.set_fan(status)
    enabled = status
    return changed


def set_automatic(status):
    global armed, last_change
    armed = status
    last_change = 0


fanshim = FanShim(disable_button=args.nobutton, disable_led=args.noled)
fanshim.set_hold_time(1.0)
fanshim.set_fan(False)
armed = True
enabled = False
led_busy = Lock()
enable = False
is_fast = False
last_change = 0
min_temp = 30
max_temp = 85
signal.signal(signal.SIGTERM, clean_exit)

if args.noled:
    led_busy.acquire()
    fanshim.set_light(0, 0, 0)
    led_busy.release()

if args.low_temp is None:
    args.low_temp = args.off_threshold

if args.high_temp is None:
    args.high_temp = args.on_threshold

if not args.nobutton:
    @fanshim.on_release()
    def release_handler(was_held):
        global armed
        if was_held:
            set_automatic(not armed)
        elif not armed:
            set_fan(not enabled)

    @fanshim.on_hold()
    def held_handler():
        global led_busy
        if args.noled:
            return
        led_busy.acquire()
        for _ in range(3):
            fanshim.set_light(0, 0, 255)
            time.sleep(0.04)
            fanshim.set_light(0, 0, 0)
            time.sleep(0.04)
        led_busy.release()


try:
    while True:
        t = get_cpu_temp()
        f = get_cpu_freq()
        was_fast = is_fast
        is_fast = (int(f.current) == int(f.max))
        if args.verbose:
            print("Current: {:05.02f} Target: {:05.02f} Freq {: 5.02f} Automatic: {} On: {}".format(t, args.off_threshold, f.current / 1000.0, armed, enabled))

        if args.preempt and is_fast and was_fast:
            enable = True
        elif armed:
            if t >= args.on_threshold:
                enable = True
            elif t <= args.off_threshold:
                enable = False

            if set_fan(enable):
                last_change = t

        if not args.noled:
            update_led_temperature(t)

        time.sleep(args.delay)
except KeyboardInterrupt:
    pass
#!/usr/bin/env python3 # Between minimum temp and low temp, set LED to blue through to green # Between high temp and maximum temp, set LED to red through to magenta # In the normal low temp to high temp range, set LED to green through to red