Initial commit
This commit is contained in:
commit
d41e06e02b
4 changed files with 554 additions and 0 deletions
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
*.sh
|
||||
*.pyc
|
||||
*.swp
|
||||
server/bin/
|
||||
server/lib/
|
||||
server/include/
|
||||
server/local/
|
304
client/tempino/tempino.ino
Normal file
304
client/tempino/tempino.ino
Normal file
|
@ -0,0 +1,304 @@
|
|||
#include <registers.h>
|
||||
#include <pin_magic.h>
|
||||
#include <Adafruit_TFTLCD.h>
|
||||
|
||||
// Paint example specifically for the TFTLCD breakout board.
|
||||
// If using the Arduino shield, use the tftpaint_shield.pde sketch instead!
|
||||
// DOES NOT CURRENTLY WORK ON ARDUINO LEONARDO
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library
|
||||
#include <Adafruit_TFTLCD.h> // Hardware-specific library
|
||||
#include <TouchScreen.h>
|
||||
|
||||
#if defined(__SAM3X8E__)
|
||||
#undef __FlashStringHelper::F(string_literal)
|
||||
#define F(string_literal) string_literal
|
||||
#endif
|
||||
|
||||
// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
|
||||
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
|
||||
// D0 connects to digital pin 8 (Notice these are
|
||||
// D1 connects to digital pin 9 NOT in order!)
|
||||
// D2 connects to digital pin 2
|
||||
// D3 connects to digital pin 3
|
||||
// D4 connects to digital pin 4
|
||||
// D5 connects to digital pin 5
|
||||
// D6 connects to digital pin 6
|
||||
// D7 connects to digital pin 7
|
||||
|
||||
// For the Arduino Mega, use digital pins 22 through 29
|
||||
// (on the 2-row header at the end of the board).
|
||||
// D0 connects to digital pin 22
|
||||
// D1 connects to digital pin 23
|
||||
// D2 connects to digital pin 24
|
||||
// D3 connects to digital pin 25
|
||||
// D4 connects to digital pin 26
|
||||
// D5 connects to digital pin 27
|
||||
// D6 connects to digital pin 28
|
||||
// D7 connects to digital pin 29
|
||||
|
||||
// For the Arduino Due, use digital pins 33 through 40
|
||||
// (on the 2-row header at the end of the board).
|
||||
// D0 connects to digital pin 33
|
||||
// D1 connects to digital pin 34
|
||||
// D2 connects to digital pin 35
|
||||
// D3 connects to digital pin 36
|
||||
// D4 connects to digital pin 37
|
||||
// D5 connects to digital pin 38
|
||||
// D6 connects to digital pin 39
|
||||
// D7 connects to digital pin 40
|
||||
|
||||
// #define YP A1 // must be an analog pin, use "An" notation!
|
||||
// #define XM A2 // must be an analog pin, use "An" notation!
|
||||
// #define YM 7 // can be a digital pin
|
||||
///#define XP 6 // can be a digital pin
|
||||
#define XM A1
|
||||
#define YP A2
|
||||
#define YM 6
|
||||
#define XP 7
|
||||
|
||||
#define TS_MINX 150
|
||||
#define TS_MINY 120
|
||||
#define TS_MAXX 880
|
||||
#define TS_MAXY 940
|
||||
|
||||
//#define TS_MINX 131
|
||||
//#define TS_MINY 159
|
||||
//#define TS_MAXX 942
|
||||
//#define TS_MAXY 878
|
||||
|
||||
|
||||
// For better pressure precision, we need to know the resistance
|
||||
// between X+ and X- Use any multimeter to read it
|
||||
// For the one we're using, its 300 ohms across the X plate
|
||||
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
|
||||
|
||||
|
||||
#define LCD_CS A3
|
||||
#define LCD_CD A2
|
||||
#define LCD_WR A1
|
||||
#define LCD_RD A0
|
||||
// optional
|
||||
#define LCD_RESET A4
|
||||
|
||||
// Assign human-readable names to some common 16-bit color values:
|
||||
#define BLACK 0x0000
|
||||
#define BLUE 0x001F
|
||||
#define RED 0xF800
|
||||
#define GREEN 0x07E0
|
||||
#define CYAN 0x07FF
|
||||
#define MAGENTA 0xF81F
|
||||
#define YELLOW 0xFFE0
|
||||
#define WHITE 0xFFFF
|
||||
|
||||
|
||||
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
|
||||
|
||||
// Make the icons bigger or smaller
|
||||
#define ICONSIZE 20
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
tft.reset();
|
||||
|
||||
// There are various drivers, we check them. This code has been brought
|
||||
// by https://github.com/adafruit/TFTLCD-Library
|
||||
if(identifier == 0x9325) {
|
||||
Serial.println(F("Found ILI9325 LCD driver"));
|
||||
} else if(identifier == 0x9327) {
|
||||
Serial.println(F("Found ILI9327 LCD driver"));
|
||||
} else if(identifier == 0x9328) {
|
||||
Serial.println(F("Found ILI9328 LCD driver"));
|
||||
} else if(identifier == 0x7575) {
|
||||
Serial.println(F("Found HX8347G LCD driver"));
|
||||
} else if(identifier == 0x9341) {
|
||||
Serial.println(F("Found ILI9341 LCD driver"));
|
||||
} else if(identifier == 0x8357) {
|
||||
Serial.println(F("Found HX8357D LCD driver"));
|
||||
} else if(identifier == 0x0154) {
|
||||
Serial.println(F("Found S6D0154 LCD driver"));
|
||||
} else if(identifier == 0x9488) {
|
||||
Serial.println(F("Found ILI9488 LCD driver"));
|
||||
} else {
|
||||
Serial.print(F("Unknown LCD driver chip: "));
|
||||
Serial.println(identifier, HEX);
|
||||
Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
|
||||
Serial.println(F(" #define USE_ADAFRUIT_SHIELD_PINOUT"));
|
||||
Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
|
||||
Serial.println(F("If using the breakout board, it should NOT be #defined!"));
|
||||
Serial.println(F("Also if using the breakout, double-check that all wiring"));
|
||||
Serial.println(F("matches the tutorial."));
|
||||
return;
|
||||
}
|
||||
|
||||
tft.begin(identifier);
|
||||
|
||||
// I happen to like this position, feel free to
|
||||
// experiment and change it
|
||||
tft.setRotation(2);
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
drawHeader(false);
|
||||
|
||||
pinMode(13, OUTPUT);
|
||||
}
|
||||
|
||||
void drawHeader(bool loading) {
|
||||
tft.fillRect(10, 5, 240, 30, BLACK);
|
||||
if (!loading) {
|
||||
tft.setCursor(10, 5);
|
||||
tft.setTextSize(4);
|
||||
tft.setTextColor(WHITE);
|
||||
tft.println("Sensors");
|
||||
} else {
|
||||
tft.setCursor(10, 5);
|
||||
tft.setTextSize(4);
|
||||
tft.setTextColor(WHITE);
|
||||
tft.println("Loading");
|
||||
}
|
||||
}
|
||||
|
||||
void drawCPU(int x, int y) {
|
||||
int bound = ICONSIZE / 10;
|
||||
int factor = ICONSIZE / 4;
|
||||
int dieSize = ICONSIZE - bound * 2;
|
||||
int added = 0;
|
||||
tft.fillRect(x, y, x + ICONSIZE, y + ICONSIZE, BLACK);
|
||||
for (int c=1;c < 4; c++) {
|
||||
added = factor * c;
|
||||
tft.drawLine(x + added, y, x + added, y + ICONSIZE, YELLOW);
|
||||
tft.drawLine(x + added, y, x + added, y + ICONSIZE, YELLOW);
|
||||
tft.drawLine(x, y + added, x + ICONSIZE, y + added, YELLOW);
|
||||
tft.drawLine(x, y + added, x + ICONSIZE, y + added, YELLOW);
|
||||
}
|
||||
tft.fillRect(x + bound, y + bound, dieSize, dieSize, WHITE);
|
||||
}
|
||||
|
||||
void drawFan(int x, int y) {
|
||||
int radius = ICONSIZE / 2;
|
||||
int centerX = x + radius;
|
||||
int centerY = y + radius;
|
||||
tft.fillRect(x, y, x + ICONSIZE, y + ICONSIZE, BLACK);
|
||||
|
||||
for(int r = 1; r < 6; r++) {
|
||||
tft.drawCircle(centerX, centerY, radius / r, BLUE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void drawSystem(int x, int y) {
|
||||
int width = ICONSIZE / 3;
|
||||
tft.fillRect(x, y, x + ICONSIZE, y + ICONSIZE, BLACK);
|
||||
tft.fillRect(x + width, y, width, ICONSIZE, GREEN);
|
||||
tft.drawRect(x + width + 1, y + 1, width - 2 , ICONSIZE - 2, BLACK);
|
||||
}
|
||||
|
||||
void drawTemp(int x, int y, String value) {
|
||||
int horizontal = x + ICONSIZE + (ICONSIZE / 8);
|
||||
int vertical = y + (ICONSIZE / 3);
|
||||
char text[50];
|
||||
tft.fillRect(horizontal, vertical, 240, ICONSIZE, BLACK);
|
||||
tft.setCursor(horizontal, vertical);
|
||||
tft.setTextSize(2);
|
||||
tft.setTextColor(WHITE);
|
||||
|
||||
sprintf(text, "%s C", value.c_str());
|
||||
|
||||
tft.println(text);
|
||||
}
|
||||
|
||||
void drawRPM(int x, int y, String value) {
|
||||
int horizontal = x + ICONSIZE + (ICONSIZE / 8);
|
||||
int vertical = y + (ICONSIZE / 3);
|
||||
char text[50];
|
||||
tft.fillRect(horizontal, vertical, 240, ICONSIZE, BLACK);
|
||||
tft.setCursor(horizontal, vertical);
|
||||
tft.setTextSize(2);
|
||||
tft.setTextColor(WHITE);
|
||||
|
||||
sprintf(text, "%s RPM", value.c_str());
|
||||
|
||||
tft.println(text);
|
||||
}
|
||||
|
||||
|
||||
// Slice and dice the string so we
|
||||
// get the commands to display
|
||||
String getCommand(String str) {
|
||||
int pos = str.lastIndexOf(';');
|
||||
if (pos > -1) {
|
||||
return str.substring(pos + 1, str.length());
|
||||
} else {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the rest of the string so it shrinks
|
||||
String advanceString(String input) {
|
||||
int pos = input.lastIndexOf(';');
|
||||
if (pos > -1) {
|
||||
return input.substring(0, pos);
|
||||
} else {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
String input;
|
||||
String temp;
|
||||
String command;
|
||||
String sensorType;
|
||||
String value;
|
||||
int len;
|
||||
int cursorPos = 20;
|
||||
int increments = 30;
|
||||
while(Serial.available() > 0) {
|
||||
cursorPos = 40;
|
||||
// Get the serial string
|
||||
input = Serial.readStringUntil('\n');
|
||||
|
||||
while (input.length() > 0)
|
||||
{
|
||||
command = getCommand(input);
|
||||
|
||||
len = 0;
|
||||
while((len < command.length() && (command.charAt(len) != '='))) {
|
||||
len++;
|
||||
}
|
||||
|
||||
// Get the command part and the data part in
|
||||
// different variables
|
||||
sensorType = command.substring(0, len);
|
||||
value = command.substring(len + 1, command.length());
|
||||
|
||||
if(sensorType.equals("CPU")) {
|
||||
drawCPU(10, cursorPos);
|
||||
drawTemp(10, cursorPos, value);
|
||||
}
|
||||
|
||||
if(sensorType.equals("FAN")) {
|
||||
drawFan(10, cursorPos);
|
||||
drawRPM(10, cursorPos, value);
|
||||
}
|
||||
|
||||
if(sensorType.equals("SYS")) {
|
||||
drawSystem(10, cursorPos);
|
||||
drawTemp(10, cursorPos, value);
|
||||
}
|
||||
|
||||
// Make sure the next icon appears below
|
||||
cursorPos = cursorPos + increments;
|
||||
|
||||
if (input.lastIndexOf(';') != -1) {
|
||||
// Keep shrinking
|
||||
temp = advanceString(input);
|
||||
input = temp;
|
||||
} else {
|
||||
// Finish the while loop
|
||||
input = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
server/requirements.txt
Normal file
3
server/requirements.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
PySensors==0.0.3
|
||||
argparse==1.2.1
|
||||
pyserial==2.7
|
240
server/server.py
Normal file
240
server/server.py
Normal file
|
@ -0,0 +1,240 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import serial
|
||||
import sensors
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
import signal
|
||||
|
||||
running = True
|
||||
|
||||
# Be careful if you use Python 3, it'll send Unicode and
|
||||
# the Arduino won't know what to do with it. Add a b before
|
||||
# the strings or use the conversion functions before sending
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
global running
|
||||
print("Exiting...")
|
||||
running = False
|
||||
|
||||
|
||||
def available_cpu_count():
|
||||
""" Number of available virtual or physical CPUs on this system, i.e.
|
||||
user/real as output by time(1) when called with an optimally scaling
|
||||
userspace-only program"""
|
||||
|
||||
# cpuset
|
||||
# cpuset may restrict the number of *available* processors
|
||||
try:
|
||||
m = re.search(r'(?m)^Cpus_allowed:\s*(.*)$',
|
||||
open('/proc/self/status').read())
|
||||
if m:
|
||||
res = bin(int(m.group(1).replace(',', ''), 16)).count('1')
|
||||
if res > 0:
|
||||
return res
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
# Python 2.6+
|
||||
try:
|
||||
import multiprocessing
|
||||
return multiprocessing.cpu_count()
|
||||
except (ImportError, NotImplementedError):
|
||||
pass
|
||||
|
||||
# http://code.google.com/p/psutil/
|
||||
try:
|
||||
import psutil
|
||||
return psutil.cpu_count() # psutil.NUM_CPUS on old versions
|
||||
except (ImportError, AttributeError):
|
||||
pass
|
||||
|
||||
# POSIX
|
||||
try:
|
||||
res = int(os.sysconf('SC_NPROCESSORS_ONLN'))
|
||||
|
||||
if res > 0:
|
||||
return res
|
||||
except (AttributeError, ValueError):
|
||||
pass
|
||||
|
||||
# Windows
|
||||
try:
|
||||
res = int(os.environ['NUMBER_OF_PROCESSORS'])
|
||||
|
||||
if res > 0:
|
||||
return res
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
|
||||
# jython
|
||||
try:
|
||||
from java.lang import Runtime
|
||||
runtime = Runtime.getRuntime()
|
||||
res = runtime.availableProcessors()
|
||||
if res > 0:
|
||||
return res
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# BSD
|
||||
try:
|
||||
sysctl = subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
|
||||
stdout=subprocess.PIPE)
|
||||
scStdout = sysctl.communicate()[0]
|
||||
res = int(scStdout)
|
||||
|
||||
if res > 0:
|
||||
return res
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
||||
# Linux
|
||||
try:
|
||||
res = open('/proc/cpuinfo').read().count('processor\t:')
|
||||
|
||||
if res > 0:
|
||||
return res
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
# Solaris
|
||||
try:
|
||||
pseudoDevices = os.listdir('/devices/pseudo/')
|
||||
res = 0
|
||||
for pd in pseudoDevices:
|
||||
if re.match(r'^cpuid@[0-9]+$', pd):
|
||||
res += 1
|
||||
|
||||
if res > 0:
|
||||
return res
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
# Other UNIXes (heuristic)
|
||||
try:
|
||||
try:
|
||||
dmesg = open('/var/run/dmesg.boot').read()
|
||||
except IOError:
|
||||
dmesgProcess = subprocess.Popen(['dmesg'], stdout=subprocess.PIPE)
|
||||
dmesg = dmesgProcess.communicate()[0]
|
||||
|
||||
res = 0
|
||||
while '\ncpu' + str(res) + ':' in dmesg:
|
||||
res += 1
|
||||
|
||||
if res > 0:
|
||||
return res
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
raise Exception('Can not determine number of CPUs on this system')
|
||||
|
||||
|
||||
class Data(object):
|
||||
"""
|
||||
Data encapsulation
|
||||
"""
|
||||
def __init__(self, label, value):
|
||||
self.label = label
|
||||
if (label is not None):
|
||||
self.value = int(value)
|
||||
|
||||
else:
|
||||
self.value = value
|
||||
|
||||
def __str__(self):
|
||||
return self.label + " {}".format(self.value)
|
||||
|
||||
|
||||
class Sensors(object):
|
||||
"""
|
||||
Parses the output of the sensors command
|
||||
"""
|
||||
def __init__(self):
|
||||
print("Getting sensors ready")
|
||||
sensors.init()
|
||||
self.data = {}
|
||||
self.cpus = available_cpu_count()
|
||||
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
print("Reading sensors")
|
||||
cpu_counter = 0
|
||||
fan_count = 0
|
||||
|
||||
for chip in sensors.iter_detected_chips():
|
||||
for feature in chip:
|
||||
if feature.get_value() > 0 and feature.label != 'CPUTIN':
|
||||
if 'cpu' in feature.label.lower() or 'core' in feature.label.lower() and cpu_counter < self.cpus:
|
||||
self.data['CPU{}'.format(cpu_counter)] = Data(feature.label, feature.get_value())
|
||||
cpu_counter += 1
|
||||
|
||||
elif 'fan' in feature.label.lower():
|
||||
self.data['FAN{}'.format(fan_count)] = Data(feature.label, feature.get_value())
|
||||
fan_count += 1
|
||||
|
||||
elif 'sys' in feature.label.lower():
|
||||
self.data['SYSTEM'] = Data(feature.label, feature.get_value())
|
||||
|
||||
|
||||
class Arduino(object):
|
||||
"""
|
||||
With this class we communicate with the Arduino
|
||||
"""
|
||||
def __init__(self):
|
||||
# TODO: Should be configurable or read from command line
|
||||
print("Connecting to Arduino")
|
||||
self.serial = serial.Serial('/dev/ttyACM0', 9600)
|
||||
time.sleep(2)
|
||||
|
||||
def close(self):
|
||||
self.serial.close()
|
||||
|
||||
def send(self, sensors_data):
|
||||
print("Sending data")
|
||||
sensors_data.update()
|
||||
data = sensors_data.data
|
||||
|
||||
stream = []
|
||||
|
||||
keys = data.keys()
|
||||
keys.sort()
|
||||
|
||||
for key in keys:
|
||||
if 'CPU' in key:
|
||||
stream.append("CPU={}".format(data[key]))
|
||||
|
||||
if 'FAN' in key:
|
||||
stream.append("FAN={}".format(data[key]))
|
||||
|
||||
if 'SYS' in key:
|
||||
stream.append("SYS={}".format(data[key]))
|
||||
|
||||
print("Sending {} datagrams".format(len(stream)))
|
||||
|
||||
res = ";".join(stream)
|
||||
|
||||
print(res)
|
||||
|
||||
self.serial.write(res + "\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
arduino = Arduino()
|
||||
sensor_data = Sensors()
|
||||
|
||||
while running:
|
||||
arduino.send(sensor_data)
|
||||
# This should be configurable too
|
||||
time.sleep(3)
|
||||
|
||||
arduino.close()
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in a new issue