Skip to content

Instantly share code, notes, and snippets.

@daniel-j
Last active January 4, 2016 02:59
Show Gist options
  • Save daniel-j/8559113 to your computer and use it in GitHub Desktop.
Save daniel-j/8559113 to your computer and use it in GitHub Desktop.
A system monitor for PiGlow, uses the PyGlow library, shows CPU usage, memory usage and current CPU temperature. When a value change it transition to it smoothly. There's also a version written in C using the wiringPi library! It should use less CPU, and it's multithreaded, yay!
//
// PiGlow system monitor by djazz!
// Makefile is embedded below
//
// Configuration
float temperature_range[] = {35.0, 65.0};
float led_update_interval = 1000/20.0;
float value_update_interval = 1000.0;
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <wiringPi.h>
#include <piGlow.h>
#ifndef true
# define true (1==1)
# define false (!true)
#endif
const int CHANGE_VALUE = 0;
float values[] = {0.0, 0.0, 0.0};
float values_current[] = {0.0, 0.0, 0.0};
// takes a value from 0.0 to 1.0, leg can be 0-2, brightness is max brightness and can be 0-255
void leg_level(float val, int leg, int brightness) {
float ratio = 0.0;
int i = 0;
for (i = 0; i < 6; i++) {
ratio = 6*val - i;
if (ratio > 1.0) ratio = 1.0;
else if (ratio < 0.0) ratio = 0.0;
if (i == 0) {
ratio /= 3.0;
}
if (i < 3) {
ratio /= 2.0;
}
piGlow1(leg, 5-i, (int)brightness*ratio);
}
}
PI_THREAD (updateValuesThread) {
FILE* fp;
FILE* stat;
FILE* pfree;
int raw = 0.0;
float temperature = 0.0;
float temp = 0.0;
unsigned totalMem, used, free, shared, buffered, cached;
float memory = 0.0;
unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
float cpu_percent = 0.0;
stat = fopen("/proc/stat", "r");
fscanf(stat, "cpu %Ld %Ld %Ld %Ld", &lastTotalUser, &lastTotalUserLow, &lastTotalSys, &lastTotalIdle);
fclose(stat);
while (true) {
fp = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
fscanf(fp, "%d", &raw);
fclose(fp);
temperature = raw/1000.0;
temp = (temperature-temperature_range[0])/(temperature_range[1]-temperature_range[0]);
pfree = popen("free | sed -n 2p |awk '{print $2 \" \" $3 \" \" $4 \" \" $5 \" \" $6 \" \" $7}'","r");
fscanf(pfree,"%u %u %u %u %u %u\n", &totalMem, &used, &free, &shared, &buffered, &cached);
pclose(pfree);
memory = (used - buffered - cached)/(float)totalMem;
stat = fopen("/proc/stat", "r");
fscanf(stat, "cpu %Ld %Ld %Ld %Ld", &totalUser, &totalUserLow, &totalSys, &totalIdle);
fclose(stat);
if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow || totalSys < lastTotalSys || totalIdle < lastTotalIdle){
//Overflow detection. Just skip this value.
//cpu_percent = -1.0;
} else {
total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + (totalSys - lastTotalSys);
cpu_percent = total;
total += (totalIdle - lastTotalIdle);
cpu_percent /= total;
}
lastTotalUser = totalUser;
lastTotalUserLow = totalUserLow;
lastTotalSys = totalSys;
lastTotalIdle = totalIdle;
piLock(CHANGE_VALUE);
values[0] = cpu_percent;
values[1] = temp;
values[2] = memory;
piUnlock(CHANGE_VALUE);
delay(value_update_interval);
}
return 0;
}
int main(void) {
wiringPiSetupSys();
piGlowSetup(true);
piThreadCreate(updateValuesThread);
while (true) {
int i;
float diff;
for (i = 0; i < 3; i++) {
diff = fabs(values_current[i]-values[i]);
if (diff > 0.025) diff = 0.025;
if (values[i] < values_current[i]) {
values_current[i] -= diff;
} else if (values[i] > values_current[i]) {
values_current[i] += diff;
}
leg_level(values_current[i], i, 30);
}
delay(led_update_interval);
}
return 0;
}
/* Makefile
#DEBUG = -g -O0
DEBUG = -O3
CC = gcc
INCLUDE = -I/usr/local/include
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe
LDFLAGS = -L/usr/local/lib
LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm
# Should not alter anything below this line
###############################################################################
SRC = cpu.c
OBJ = $(SRC:.c=.o)
BINS = $(SRC:.c=)
all: $(BINS)
cpu: cpu.o
@echo [link]
@$(CC) -o $@ cpu.o $(LDFLAGS) $(LDLIBS)
.c.o:
@echo [CC] $<
@$(CC) -c $(CFLAGS) $< -o $@
clean:
@echo "[Clean]"
@rm -f $(OBJ) *~ core tags $(BINS)
tags: $(SRC)
@echo [ctags]
@ctags $(SRC)
depend:
makedepend -Y $(SRC)
*/
#
# PiGlow system monitor by djazz!
#
temperature_range = [35.0, 65.0]
cpu_delay = 1.0 # the time it should take to calculate CPU usage
other_delay = 5.0 # wait this long between memory and temperature update
from pyglow import PyGlow
from subprocess import PIPE, Popen
from threading import Timer
from sys import exit
from time import sleep
import psutil
pyglow = PyGlow()
values = [0.0, 0.0, 0.0]
values_current = [0.0, 0.0, 0.0]
# found this online somewhere..
def get_cpu_temperature():
process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE)
output, _error = process.communicate()
return float(output[output.index('=') + 1:output.rindex("'")])
# takes a value from 0.0 to 1.0, leg can be 0-2, brightness is max brightness and can be 0-255
def leg_level(val = 0.0, leg = 0, brightness = 100):
#print "--" + str(val)
for i in range(0,6):
ratio = max(0.0, min(1.0, 6*val - i))
#print str(i)+" - "+str(ratio)
if i == 0:
ratio /= 3.0
if i < 3:
ratio /= 2.0
pyglow.set_leds([int(leg*6+(6-i))], int(brightness*ratio))
def update_cpu():
cpu = psutil.cpu_percent(cpu_delay)/100.0
values[0] = cpu
timer = Timer(0.0, update_cpu)
timer.daemon = True
timer.start()
def update_other():
memory = psutil.phymem_usage().percent/100.0
values[2] = memory
degrees = get_cpu_temperature()
temp = (degrees-temperature_range[0])/(temperature_range[1]-temperature_range[0])
values[1] = temp
timer = Timer(other_delay, update_other)
timer.daemon = True
timer.start()
pyglow.all(0)
update_other()
update_cpu()
try:
while True:
for i in range(0,3):
diff = min(0.025, abs(values_current[i]-values[i]))
if values[i] < values_current[i]:
values_current[i]-=diff
elif values[i] > values_current[i]:
values_current[i]+=diff
leg_level(values_current[i], i, 255)
pyglow.update_leds()
sleep(0.05)
except KeyboardInterrupt:
pyglow.all(0)
exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment