commit 5fd76b071a7b5b359abd62ab18ab9d42fad0d1a4 Author: Blaster4385 Date: Sat May 20 12:45:38 2023 +0530 Initial System Monitor Code diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1194b5 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# ESP8266 Based System Monitor + +## Disclaimer! + +### This project is based on work from [execuc/esp-hw-monitoring](https://github.com/execuc/esp-hw-monitoring) with several modifications to fit my needs. I take no credit for the original work. + +### Modifications include but are not limited to: + +- Major code cleanup +- Data format modification +- More efficient data reading + +--- + +## What is this? + +This is a simple ESP8266 based system monitor that can be used to monitor system information and resources. It also shows the current time as well as the ambient temperature and humidity. + +## Components used + +- ESP8266 +- 240*320 2.8 inch ILI9341 LCD +- DHT22 temperature module (with resistor) + +## Connecting the components + +- Connect the LCD to the ESP8266 as follows: + - LCD VCC to ESP8266 3.3V + - LCD GND to ESP8266 GND + - LCD CS to ESP8266 D2 + - LCD RESET to ESP8266 D3 + - LCD DC to ESP8266 D4 + +- Connect the DHT22 to the ESP8266 as follows: + - DHT22 VCC to ESP8266 3.3V + - DHT22 GND to ESP8266 GND + - DHT22 DATA to ESP8266 D8 + +## How to use + +- Install the Arduino IDE +- Install the ESP8266 board +- Install the following libraries: + - Adafruit GFX Library + - Adafruit ILI9341 + - Adafruit Unified Sensor + - DHT sensor library + +- Open the `sysmon.ino` file in the Arduino IDE + +- Upload the code to the ESP8266 + +- Run the sysmon.py script on your computer + +- Enjoy! \ No newline at end of file diff --git a/cpu.cpp b/cpu.cpp new file mode 100644 index 0000000..2c1b437 --- /dev/null +++ b/cpu.cpp @@ -0,0 +1,69 @@ +#include "cpu.h" + +int16_t cpuUsageGlobal = defaultValue; +int16_t cpuUsage[8] = {defaultValue, defaultValue, defaultValue,defaultValue, defaultValue, defaultValue, defaultValue, defaultValue}; +int16_t cpuTempGlobal = defaultValue; +int16_t cpuTemp[8] = {defaultValue, defaultValue, defaultValue,defaultValue, defaultValue, defaultValue, defaultValue, defaultValue}; +uint32_t ramFree = defaultValue; +uint32_t ramMax = defaultValue; + +static int8_t extractArray(String &command, int16_t *array) +{ + int8_t startIndex = 1, lastIndex; + int8_t index = 0; + bool needStop = false; + while(index < 8) + { + lastIndex = command.indexOf(",", startIndex); + if(lastIndex == -1) + { + lastIndex = command.length() - 1; + needStop = true; + } + + array[index++] = command.substring(startIndex, lastIndex).toInt(); + if(needStop) + break; + startIndex = lastIndex +1; + } + return index; +} + +int8_t setCpuTemp(String command) +{ + if(command.substring(0, 1) == "[") + { + extractArray(command, cpuTemp); + } + else + { + cpuTempGlobal = command.toInt(); + } + return 0; +} + +int8_t setCpuUsage(String command) +{ + if(command.substring(0, 1) == "[") + { + extractArray(command, cpuUsage); + } + else + { + cpuUsageGlobal = command.toInt(); + } + return 0; +} + +int8_t setRamMax(String command) +{ + ramMax = command.toInt(); + return 0; +} + +int8_t setRamFree(String command) +{ + ramFree = command.toInt(); + return 0; +} + diff --git a/cpu.h b/cpu.h new file mode 100644 index 0000000..cffd298 --- /dev/null +++ b/cpu.h @@ -0,0 +1,21 @@ +#ifndef __CPU_H__ +#define __CPU_H__ + +#include + +#define defaultValue 0 + +extern void initCpuParameters(); +extern int8_t setCpuTemp(String command); +extern int8_t setCpuUsage(String command); +extern int8_t setRamMax(String command); +extern int8_t setRamFree(String command); + +extern int16_t cpuUsageGlobal; +extern int16_t cpuUsage[8]; +extern int16_t cpuTempGlobal; +extern int16_t cpuTemp[8]; +extern uint32_t ramMax; +extern uint32_t ramFree; + +#endif // __CPU_H__ diff --git a/datetimeHandler.cpp b/datetimeHandler.cpp new file mode 100644 index 0000000..6e5abd5 --- /dev/null +++ b/datetimeHandler.cpp @@ -0,0 +1,19 @@ +#include "datetimeHandler.h" + +uint8_t localTemp = 255; +uint8_t localHum = 255; +uint8_t hour = 0; +uint8_t minute = 0; +uint8_t time_tab[6] = {'-', '-', ':', '-', '-', 0}; + +void setTime(String time) +{ + if(time.length() == 8) + { + hour = time.substring(0,2).toInt(); + time.substring(0,5).getBytes(time_tab, 5+1); + minute = time.substring(3,5).toInt(); + } +} + + diff --git a/datetimeHandler.h b/datetimeHandler.h new file mode 100644 index 0000000..d51a8d6 --- /dev/null +++ b/datetimeHandler.h @@ -0,0 +1,13 @@ +#ifndef __DATETIMEHANDLER_H__ +#define __DATETIMEHANDLER_H__ + +#include + +extern uint8_t localTemp; +extern uint8_t localHum; +extern uint8_t hour; +extern uint8_t minute; +extern uint8_t time_tab[6]; +extern void setTime(String time); + +#endif // __DATETIMEHANDLER_H__ diff --git a/gfx_1.cpp b/gfx_1.cpp new file mode 100644 index 0000000..755ab04 --- /dev/null +++ b/gfx_1.cpp @@ -0,0 +1,210 @@ +#include "gfx_1.h" +#include "datetimeHandler.h" +#include "cpu.h" +#include "Adafruit_GFX.h" +#include + +bool gfx1_refresh = true; +static uint8_t s_time_tab[6] = {'0', '0', ':', '0', '0', 0}; +static uint8_t s_localHum = 0, s_localTemp = 0, s_cpuTemp = 255; +static int16_t s_cpu_usage = 255; +static uint32_t s_ram_free = 255, s_ram_max = 255; + + +// 5px size +static void gfx_update_toolbar(); +static void gfx_update_cpu(); +static void gfx_update_mem(); + +static void writeArray(const char *buf) +{ + uint8_t c= 0; + while(buf[c] != 0) + tft.write(buf[c++]); +} + + +void gfx1_udpate() +{ + // if(!gfx1_refresh) + // return ; + + gfx1_refresh = false; + gfx_update_toolbar(); + gfx_update_cpu(); + gfx_update_mem(); +} + +#define LINE_Y_REL 29 +#define TEXT_Y_REL 9 +#define FIRST_TEXT_Y_REL 40 +#define TEXT_ESPACE_Y 35 +#define TEXT_ESPACE_SHORT_Y 25 + +char buf[20]; + +void gfx1_layout() +{ + uint8_t c= 0; + + tft.fillScreen(ILI9341_BLACK); + tft.drawLine(10, 18, 310, 18, ILI9341_YELLOW); + tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); + tft.setCursor(35, 0); + tft.setTextSize(1); + tft.write('o'); + tft.setTextSize(2); + tft.setCursor(35+8, 2); + tft.write('C'); + //Humidity + tft.setCursor(300, 2); + tft.write('%'); + + // CPU rect + tft.setTextSize(2); + tft.drawRoundRect(5, 45, 150, 90, 10, ILI9341_DARKCYAN); + tft.drawLine(5, 45+LINE_Y_REL, 154, 45+LINE_Y_REL, ILI9341_DARKCYAN); + tft.setTextColor(ILI9341_DARKCYAN, ILI9341_BLACK); + tft.setCursor(60, 45+TEXT_Y_REL); + sprintf(buf, "CPU"); + writeArray(buf); + tft.setCursor(15, 45+FIRST_TEXT_Y_REL); + sprintf(buf, "Usage:"); + writeArray(buf); + tft.setCursor(15, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); + sprintf(buf, "Temp:"); + writeArray(buf); + tft.setCursor(15, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y *2); + + // memory + tft.drawRoundRect(165, 45, 150, 90, 10, ILI9341_GREEN); + tft.drawLine(165, 45+LINE_Y_REL, 314, 45+LINE_Y_REL, ILI9341_GREEN); + tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK); + tft.setCursor(205, 45+TEXT_Y_REL); + sprintf(buf, "MEMORY"); + writeArray(buf); + tft.setCursor(175, 45+FIRST_TEXT_Y_REL); + sprintf(buf, "Max:"); + writeArray(buf); + tft.setCursor(175, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); + sprintf(buf, "Free:"); + writeArray(buf); + + gfx1_refresh = true; + gfx1_udpate(); +} + +void get_formated_space(int32_t valueMb) +{ + int8_t unity = 0; + if(valueMb > 999) + { + valueMb = valueMb / 1024; + unity = 1; // GB + } + + if(valueMb > 9999) + { + valueMb = valueMb / 1024; + unity = 2; // TB + } + + if(unity == 0) + sprintf(buf, "%4d MB", valueMb); + else if(unity == 1) + sprintf(buf, "%4d GB", valueMb); + else + sprintf(buf, "%4d TB", valueMb); +} + +static void gfx_update_mem() +{ + tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK); + if(s_ram_max != ramMax) + { + tft.setCursor(175 + 50, 45+FIRST_TEXT_Y_REL); + get_formated_space(ramMax); + writeArray(buf); + s_ram_free = ramMax; + } + + if(s_ram_free != ramFree) + { + tft.setCursor(175 + 50, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); + get_formated_space(ramFree); + writeArray(buf); + s_ram_free = ramFree; + } +} + +//s_cpu_usage = 0; +static void gfx_update_cpu() +{ + tft.setTextColor(ILI9341_DARKCYAN, ILI9341_BLACK); + if(cpuUsageGlobal != s_cpu_usage) + { + tft.setCursor(15+75, 45+FIRST_TEXT_Y_REL); + sprintf(buf, "%3d %%", cpuUsageGlobal); + writeArray(buf); + s_cpu_usage = cpuUsageGlobal; + } + if(s_cpuTemp != cpuTempGlobal) + { + tft.setCursor(15 + 75, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); + sprintf(buf, "%3d ", cpuTempGlobal); + writeArray(buf); + tft.setCursor(15 + 115, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y - 2); + tft.setTextSize(1); + tft.write('o'); + tft.setTextSize(2); + tft.setCursor(15 + 115 +8, 45+FIRST_TEXT_Y_REL + TEXT_ESPACE_SHORT_Y); + tft.write('C'); + s_cpuTemp = cpuTempGlobal; + } +} + +static void gfx_update_toolbar() +{ + uint8_t c= 0; + char buf[5]; + tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK); + //time + if(s_time_tab[4] != time_tab[4] || s_time_tab[3] != time_tab[3] + || s_time_tab[1] != time_tab[1] || s_time_tab[0] != time_tab[0]) + { + tft.setTextSize(2); + tft.setCursor(135, 2); + + while(c < 5) + { + uint8_t car = time_tab[c]; + s_time_tab[c] = car; + tft.write(car); + c++; + } + } + + //temp + if(s_localTemp != localTemp) + { + tft.setCursor(10, 2); + if(localTemp != 255) + sprintf(buf, "%2d", localTemp); + else + sprintf(buf, "--"); + writeArray(buf); + s_localTemp = localTemp; + } + + // humidity + if(s_localHum != localHum) + { + tft.setCursor(275, 2); + if(localHum != 255) + sprintf(buf, "%2d", localHum); + else + sprintf(buf, "--"); + writeArray(buf); + s_localHum = localHum; + } +} diff --git a/gfx_1.h b/gfx_1.h new file mode 100644 index 0000000..601401e --- /dev/null +++ b/gfx_1.h @@ -0,0 +1,14 @@ +#ifndef __GFX_1_H__ +#define __GFX_1_H__ + +#include "Adafruit_ILI9341.h" + +extern Adafruit_ILI9341 tft; + +extern void gfx1_udpate(); +extern void gfx1_layout(); + +extern bool gfx1_refresh; + + +#endif diff --git a/sysmon.ino b/sysmon.ino new file mode 100644 index 0000000..b854bfd --- /dev/null +++ b/sysmon.ino @@ -0,0 +1,108 @@ +#include "Adafruit_GFX.h" +#include "Adafruit_ILI9341.h" +#include +#include "DHT.h" +#include "cpu.h" +#include "datetimeHandler.h" +#include "gfx_1.h" + +#define TFT_DC D4 +#define TFT_CS D2 +#define TFT_RESET D3 +#define DHTPIN D8 +#define DHTTYPE DHT22 + +Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); +DHT dht(DHTPIN, DHTTYPE); + +static uint32_t tempTime = 0; +static uint32_t rtcTime = 0; +static uint32_t displayTime = 0; + +void setup() { + Serial.begin(9600); + initHardware(); + gfx1_layout(); +} + +void update(String command) { + int delimiterIndex = command.indexOf('='); + // Serial.println(command); + if (delimiterIndex != -1) { + String key = command.substring(0, delimiterIndex); + String value = command.substring(delimiterIndex + 1); + Serial.print(key); + + // Check the key and assign the corresponding value + if (key.equals("CpuTemp")) { + setCpuTemp(value); + Serial.print("Received CPU temperature: "); + Serial.println(value); + // gfx1_udpate(); + } else if (key.equals("CpuUsage")) { + setCpuUsage(value); + Serial.print("Received CPU usage: "); + Serial.println(value); + // gfx1_udpate(); + } else if (key.equals("RamFree")) { + setRamFree(value); + Serial.print("Received Ram free: "); + Serial.println(value); + // gfx1_udpate(); + } else if (key.equals("RamMax")) { + setRamMax(value); + Serial.print("Received Ram max: "); + Serial.println(value); + // gfx1_udpate(); + } else if (key.equals("Time")) { + setTime(value); + Serial.print("Received Time: "); + Serial.println(value); + // gfx1_udpate(); + } + } + gfx1_refresh = true; + gfx1_udpate(); +} + +void loop() { + Serial.println("Enter data:"); + // while (Serial.available() == 0) {} + String command = Serial.readString(); + command.trim(); + Serial.println(command); + + if(!isnan(dht.readTemperature())) + { + localHum = dht.readHumidity(); + localTemp = dht.readTemperature() - 4; + Serial.println(localTemp); + gfx1_refresh = true; + gfx1_udpate(); + } + // else + // { + // localHum = 255; + // localTemp = 255; + // } + + update(command); + // delay(1000); + + // if ( currentTime > displayTime ) { + // displayTime = currentTime + 100000; + // } +} + +void initHardware() +{ + pinMode(TFT_RESET, OUTPUT); + digitalWrite(TFT_RESET, LOW); + delay(1000); + digitalWrite(TFT_RESET, HIGH); + delay(1000); + tft.begin(); + tft.setRotation(3); + dht.begin(); + // delay(3000); +} \ No newline at end of file diff --git a/sysmon.py b/sysmon.py new file mode 100644 index 0000000..9fd0530 --- /dev/null +++ b/sysmon.py @@ -0,0 +1,99 @@ +#!/usr/bin/python + +import sys +from datetime import datetime +from datetime import timedelta +import psutil +import serial +from gettext import c2py +from time import sleep +import sensors +import subprocess +import math +import pyowm +import os + +CPU_TEMP_PATH = '/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon2/temp1_input' + +file_descriptor = '/dev/ttyUSB0' +baud_rate = 9600 + +arduino = serial.Serial(port=file_descriptor, baudrate=baud_rate) +sleep(6) + +def send_command(command): + print("sent: " + command) + arduino.write(command.encode()) + sleep(0.1) + +def set_time(date_time): + request = '\nTime=%s\r\n' % date_time.strftime('%H:%M:%S') + send_command(request) + + +def set_max(): + ram_max = int(psutil.virtual_memory().total / (1024.*1024.)) + request = 'RamMax=%d\r\n' % ram_max + send_command(request) + +def set_free(): + ram_free = int(psutil.virtual_memory().free / (1024.*1024.)) + request = 'RamFree=%d\r\n' % ram_free + send_command(request) + +def set_system_info(): + with open('/etc/os-release', 'r') as f: + for line in f: + if line.startswith('NAME='): + OSName = line.split('"')[1] + break + request = 'OS=%s\r\n' % OSName + send_command(request) + sleep(1) + + with open('/proc/version', 'r') as f: + for line in f: + Kernel = line.split(' ')[2].split('-')[0] + break + request = 'Kernel=%s\r\n' % Kernel + send_command(request) + sleep(1) + +def set_uptime(): + uptime_seconds = psutil.boot_time() + uptime = datetime.now() - datetime.fromtimestamp(uptime_seconds) + uptime_hours = int(uptime.total_seconds() // 3600) + uptime_minutes = int((uptime.total_seconds() % 3600) // 60) + uptime = f"{uptime_hours:02d}:{uptime_minutes:02d}" + request = 'Uptime=%s\r\n' % uptime + send_command(request) + +def start(tty_serial): + + set_system_info() + while 1: + set_uptime() + sleep(1) + cpu_temp = int(subprocess.check_output(['cat', CPU_TEMP_PATH]))/1000 + requests = "\nCpuTemp="+str(math.trunc(cpu_temp)) + send_command(requests) + sleep(1) + cpu_pct = psutil.cpu_percent(interval=None, percpu=False) + cpu_global = int(cpu_pct) + request = "\nCpuUsage=" + str(math.trunc(cpu_global)) + send_command(request) + sleep(1) + set_time(datetime.now()) + sleep(1) + set_max() + sleep(1) + set_free() + sleep(1) + + +def main(): + start('/dev/ttyUSB0') + + +if __name__ == "__main__": + main()