I am working on a simple neopixel strip (8 pixels) that acts as a temperature gauge for the CPU, lighting up more of the pixels as the temp increases. I got a python script working, but one requirement of the circuitpython-neopixel library i am using requires that the script is run as root.
So I have 2 questions:
- Is there a way to see any error messages that may be triggered by the automatic.py script when it runs (as directed by the service)?
- Is there a way to force the automatic.py script to run as root with the -E switch? (ie run it like sudo -E filename.py)? I need the -E switch so the environment variables for the pi user carry over to running it as root.
Or is there something different that I could do to make this work?
Here is my modified code :
`
#!/usr/bin/env python3
from fanshim import FanShim
from threading import Lock
import colorsys
import psutil
import argparse
import time
import signal
import sys
import board
import neopixel
min_val = 55
max_val = 65
parser = argparse.ArgumentParser()
parser.add_argument('--threshold', type=float, default=-1, help='Temperature threshold in degrees C to enable fan')
parser.add_argument('--hysteresis', type=float, default=-1, help='Distance from threshold before fan is disabled')
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('--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')
args = parser.parse_args()
Choose an open pin connected to the Data In of the NeoPixel strip, i.e. board.D18
NeoPixels must be connected to D10, D12, D18 or D21 to work.
pixel_pin = board.D21
The number of NeoPixels
num_pixels = 8
The order of the pixel colors - RGB or GRB. Some NeoPixels have red and green reversed!
For RGBW NeoPixels, simply change the ORDER to RGBW or GRBW.
ORDER = neopixel.GRBW
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.25, auto_write=False,
pixel_order=ORDER)
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)
temp -= args.off_threshold
temp /= float(args.on_threshold - args.off_threshold)
temp = max(0, min(1, temp))
temp = 1.0 - temp
temp *= 120.0
temp /= 360.0
r, g, b = [int(c * 255.0) for c in colorsys.hsv_to_rgb(temp, 1.0, args.brightness / 255.0)]
fanshim.set_light(r, g, b)
led_busy.release()
def update_neo_temp(temp2):
pixels.fill((0,0,0,0))
pixels.show
temp2 = float(temp2)
print(temp2)
temp2 -= min_val
print(temp2)
temp2 /= float(max_val-min_val)
print(temp2)
temp2 = max(0, min(1,temp2))
print(temp2)
#temp2 = 1.0 - temp2
print(temp2)
color = [((0, 0, 255, 0)),
((0, 128, 255, 0)),
((0, 255, 255, 0)),
((0, 255, 128, 0)),
((128, 255, 0, 0)),
((128, 128, 0, 0)),
((255, 128, 0, 0)),
((255, 0, 0, 0))]
t_test = temp2*8
print(t_test)
t_test = int(t_test)
print(t_test)
for i in range(t_test):
pixels[i] = color[i]
pixels.show()
def get_cpu_temp():
t = psutil.sensors_temperatures()
for x in ['cpu-thermal', 'cpu_thermal']:
if x in t:
return t[x][0].current
print("Warning: Unable to get CPU temperature!")
return 0
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
if args.threshold > -1 or args.hysteresis > -1:
print("""
The --threshold and --hysteresis parameters have been deprecated.
Use --on-threshold and --off-threshold instead!
""")
sys.exit(1)
fanshim = FanShim()
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
signal.signal(signal.SIGTERM, clean_exit)
if args.noled:
led_busy.acquire()
fanshim.set_light(0, 0, 0)
led_busy.release()
t = get_cpu_temp()
if t >= args.threshold:
last_change = get_cpu_temp()
set_fan(True)
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)
update_neo_temp(t)
time.sleep(args.delay)
except KeyboardInterrupt:
pass
`