diff --git a/README.md b/README.md index 6f537fd..12bc939 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,9 @@ Well I'm not too sure about what is the point to install python-pip then remove * `sudo apt-get purge python-pip` * `sudo -H pip install --upgrade luma.oled` +### Install `ifstat` for displaying network statistic +* `sudo apt-get install ifstat` + ## Test That's it, the display is ready to use. @@ -74,6 +77,19 @@ That's it, the display is ready to use. * `sudo python demo.py` ## Next step -The original Python code in this repo is adopted from `demo.py` provided by the manufacturer, which is no good for 'production' use. Because your Pi will be too busy looking for button inputs instead of doing anything else useful. +The Python code in this repo (`monitor.py`) display system information of the Pi: +1. **Button 1** - Display information relating to the main purpose of the Pi: _Disk space_ and _WiFi_. +2. **Button 2** - Display _IP Address_, _CPU Idle %_, _Memory usage_ and _System temperature_. +3. **Button 3** - Display the system shutdown dialog, use the Joystick to select options, press **Button 3** to confirm your choice. +The screen will turn off after idling for around 20 seconds. -The latest version utilize GPIO input detection instead of busy wait, which is much more reasonable CPU-wise. \ No newline at end of file +### CPU usage +The original Python code in this repo (`monitor.py`) is adopted from `demo.py` provided by the manufacturer, which is no good for 'production' use. Because your Pi will be too busy looking for button inputs instead of doing anything else useful. + +The latest version utilize GPIO input detection instead of busy wait, which is much more reasonable CPU-wise. + +### Enable the display at startup +* `sudo vi /etc/rc.local` + * Add the following line at the end of the file, assuming `monitor.py` is in /home/pi/: + * `sudo python /home/pi/monitor.py &` + * _**IMPORTANT**_ Don't forget the `&` character at the end! \ No newline at end of file diff --git a/monitor.py b/monitor.py index 754be5a..f2dbc71 100644 --- a/monitor.py +++ b/monitor.py @@ -17,19 +17,21 @@ from PIL import ImageDraw from PIL import ImageFont #GPIO define -RST_PIN = 25 +RST_PIN = 25 #Reset CS_PIN = 8 DC_PIN = 24 -JS_U_PIN = 6 -JS_D_PIN = 19 -JS_L_PIN = 5 -JS_R_PIN = 26 -JS_P_PIN = 13 +JS_U_PIN = 6 #Joystick Up +JS_D_PIN = 19 #Joystick Down +JS_L_PIN = 5 #Joystick Left +JS_R_PIN = 26 #Joystick Right +JS_P_PIN = 13 #Joystick Pressed BTN1_PIN = 21 BTN2_PIN = 20 BTN3_PIN = 16 # Some constants +SCREEN_SAVER = 20.0 +CHAR_WIDTH = 19 font = ImageFont.load_default() width = 128 height = 64 @@ -55,13 +57,34 @@ device = sh1106(serial, rotate=2) #sh1106 draw = ImageDraw.Draw(Image.new('1', (width, height))) draw.rectangle((0,0,width,height), outline=0, fill=0) -SCREEN_SAVER = 20.0 -state = 0 -stamp = time.time() -start = time.time() +state = 0 #System state: 0 - scrren is off; equal to channel number (e.g. BTN2_PIN, JS_P_PIN) otherwise +stops = 0 #Shutdown choice: 0 - No; 1 - Yes +stamp = time.time() #Current timestamp +start = time.time() #Start screen saver count down -def end_process(channel): - os.system("sudo shutdown -h now") +def shutdown(channel): + global stops + if state == BTN3_PIN: + if stops == 1: + draw_process(RST_PIN) + os.system("sudo shutdown -h now") + else: + main_process(BTN1_PIN) + else: + stops = 0 + main_process(BTN3_PIN) + +def select(channel): + global stops + if state == BTN3_PIN: + if channel == JS_L_PIN: + stops = 1 + draw_process(state) + elif channel == JS_R_PIN: + stops = 0 + draw_process(state) + else: + pass def draw_process(channel): with canvas(device) as draw: @@ -70,31 +93,50 @@ def draw_process(channel): LINE2 = "" LINE3 = "" LINE4 = "" - LINE5 = "" - if channel == BTN1_PIN: + if channel == BTN2_PIN: LINE1 = subprocess.check_output("hostname -I | awk '{printf \"IP :%s\", $1}'", shell = True ) - LINE3 = subprocess.check_output("top -bn1 | awk 'NR==3{printf \"CPU:%.1f%% idle\", $8}'", shell = True ) - LINE4 = subprocess.check_output("free -mh | awk 'NR==2{printf \"Mem:%s/%s %.1f%%\", $3,$2,$3*100/$2 }'", shell = True ) - LINE5 = subprocess.check_output("cat /sys/class/thermal/thermal_zone0/temp | awk '{printf \"Tmp:%.1fC\", $1/1000}'", shell = True ) - elif channel == BTN2_PIN: - ssid = subprocess.check_output("iwgetid --raw | awk '{printf \"Net: %s\", $0}'", shell = True) + LINE2 = subprocess.check_output("top -bn1 | awk 'NR==3{printf \"CPU:%.1f%% idle\", $8}'", shell = True ) + LINE3 = subprocess.check_output("free -mh | awk 'NR==2{printf \"Mem:%s/%s %.1f%%\", $3,$2,$3*100/$2 }'", shell = True ) + LINE4 = subprocess.check_output("cat /sys/class/thermal/thermal_zone0/temp | awk '{printf \"Tmp:%.1fC\", $1/1000}'", shell = True ) + elif channel == BTN1_PIN: + ssid = subprocess.check_output("iwgetid --raw | awk '{printf \"WiFi:%s\", $0}'", shell = True) freq = subprocess.check_output("iwgetid --freq | awk '{gsub(/Frequency:/,\"\"); printf \" %.1f %s\", $2,$3}'", shell = True) - LINE2 = subprocess.check_output("df -h /mnt/usb | awk '$NF==\"/mnt/usb\"{printf \"USB:%s/%s %s\", $3,$2,$5}'", shell = True ) - LINE3 = ssid + freq - LINE4 = " in Kbps out Kbps" - LINE5 = subprocess.check_output("ifstat -bT 0.1 1 | awk 'NR==3{printf \"%9.2f %9.2f\",$3,$4}'", shell = True) + LINE1 = subprocess.check_output("df -h /mnt/usb | awk '$NF==\"/mnt/usb\"{printf \"Disk:%s/%s %s\", $3,$2,$5}'", shell = True ) + LINE2 = ssid + freq + LINE3 = " in Kbps out Kbps" + LINE4 = subprocess.check_output("ifstat -bT 0.1 1 | awk 'NR==3{printf \"%9.2f %9.2f\",$3,$4}'", shell = True) elif channel == BTN3_PIN: - LINE2 = " Shutdown?" - LINE4 = " Yes No" + LINE1 = " Shutdown ?" + LINE3 = " Yes No" + if stops == 0: + draw.rectangle((72,50,94,52), outline=255, fill=1) + else: + draw.rectangle((15,50,37,52), outline=255, fill=1) + elif channel == RST_PIN: + LINE2 = " Shutting down..." else: pass draw.text((xpos, top), LINE0, font=font, fill=255) - draw.text((xpos, top+12), LINE1, font=font, fill=255) - draw.text((xpos, top+22), LINE2, font=font, fill=255) - draw.text((xpos, top+32), LINE3, font=font, fill=255) - draw.text((xpos, top+42), LINE4, font=font, fill=255) - draw.text((xpos, top+52), LINE5, font=font, fill=255) + if len(LINE1) > CHAR_WIDTH: + draw.text((xpos, top+12), LINE1[:CHAR_WIDTH], font=font, fill=255) + else: + draw.text((xpos, top+12), LINE1, font=font, fill=255) + + if len(LINE2) > CHAR_WIDTH: + draw.text((xpos, top+28), LINE2[:CHAR_WIDTH], font=font, fill=255) + else: + draw.text((xpos, top+28), LINE2, font=font, fill=255) + + if len(LINE3) > CHAR_WIDTH: + draw.text((xpos, top+40), LINE3[:CHAR_WIDTH], font=font, fill=255) + else: + draw.text((xpos, top+40), LINE3, font=font, fill=255) + + if len(LINE4) > CHAR_WIDTH: + draw.text((xpos, top+52), LINE4[:CHAR_WIDTH], font=font, fill=255) + else: + draw.text((xpos, top+52), LINE4, font=font, fill=255) def main_process(channel): global serial @@ -127,10 +169,12 @@ def main_process(channel): else: # state > 0 && channel == 0 && not-yet-timeout, refresh screen draw_process(state) -GPIO.add_event_detect(JS_P_PIN, GPIO.RISING, callback=main_process, bouncetime=200) GPIO.add_event_detect(BTN1_PIN, GPIO.RISING, callback=main_process, bouncetime=200) GPIO.add_event_detect(BTN2_PIN, GPIO.RISING, callback=main_process, bouncetime=200) -GPIO.add_event_detect(BTN3_PIN, GPIO.RISING, callback=main_process, bouncetime=200) +GPIO.add_event_detect(BTN3_PIN, GPIO.RISING, callback=shutdown, bouncetime=200) +GPIO.add_event_detect(JS_L_PIN, GPIO.RISING, callback=select, bouncetime=200) +GPIO.add_event_detect(JS_R_PIN, GPIO.RISING, callback=select, bouncetime=200) + try: main_process(BTN1_PIN)