I wanted a screen that would show the CPU % of all 4 cores. Much like htop does.
I modified the bakebit_nanohat_oled.py source file. (though this forum wont let me attach a .py file. so included below.
Copy and paste into your bakebit_nanohat_oled.py source file, located in
NanoHatOLED Mine/BakeBit/Software/Python folder, and reboot.

Pressing K2 the first time will show the stock screen, pressing it again will show this new one.
Currently I am running this with my NanoPi NEO Air, the only extra step I had to do is "pip install Pillow" for it to work.
P.S. I am just scratching the surface learning embedded Linux, and Python so take it into consideration.


NanoHat OLED.jpg
Image of what the OLED looks like
NanoHat OLED.jpg (146.39 KiB) Viewed 7413 times



Code: Select all

#!/usr/bin/env python
#
# BakeBit example for the basic functions of BakeBit 128x64 OLED (http://wiki.friendlyarm.com/wiki/index.php/BakeBit_-_OLED_128x64)
#
# The BakeBit connects the NanoPi NEO and BakeBit sensors.
# You can learn more about BakeBit here:  http://wiki.friendlyarm.com/BakeBit
#
# Have a question about this example?  Ask on the forums here:  http://www.friendlyarm.com/Forum/
#
# NOTE: When Instlling on NanoPiAir you may need to: "pip isntall Pillow"
#      for this to work
#
'''
## License

The MIT License (MIT)

BakeBit: an open source platform for connecting BakeBit Sensors to the NanoPi NEO.
Copyright (C) 2016 FriendlyARM

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

'''

import bakebit_128_64_oled as oled
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import time
import sys
import subprocess
import threading
import signal
import os
import socket
import psutil

global width
width=128
global height
height=64

global pageCount
pageCount=2
global pageIndex
pageIndex=0
global showPageIndicator
showPageIndicator=False

oled.init()  #initialze SEEED OLED display
oled.setNormalDisplay()      #Set display to normal mode (i.e non-inverse mode)
oled.setHorizontalMode()

global drawing
drawing = False

global image
image = Image.new('1', (width, height))
global draw
draw = ImageDraw.Draw(image)
global fontb24
fontb24 = ImageFont.truetype('DejaVuSansMono-Bold.ttf', 24);
global font14
font14 = ImageFont.truetype('DejaVuSansMono.ttf', 14);
global smartFont
smartFont = ImageFont.truetype('DejaVuSansMono-Bold.ttf', 10);
global fontb14
fontb14 = ImageFont.truetype('DejaVuSansMono-Bold.ttf', 14);
global font11
font11 = ImageFont.truetype('DejaVuSansMono.ttf', 11);
global font10
font10 = ImageFont.truetype('DejaVuSansMono.ttf', 10);
global font12
font12 = ImageFont.truetype('DejaVuSansMono.ttf', 12);


global lock
lock = threading.Lock()

def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # doesn't even have to be reachable
        s.connect(('10.255.255.255', 1))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP

def get_temp():

    tempI = int(open('/sys/class/thermal/thermal_zone0/temp').read());
    if tempI>1000:
        tempI = tempI/1000

    tempStr = "CPU TEMP: %sC" % str(tempI)

    return tempStr

def draw_page():
    global drawing
    global image
    global draw
    global oled
    global font
    global font14
    global smartFont
    global width
    global height
    global pageCount
    global pageIndex
    global showPageIndicator
    global width
    global height
    global lock
 
   

    lock.acquire()
    is_drawing = drawing
    page_index = pageIndex
    lock.release()

    if is_drawing:
        return

    lock.acquire()
    drawing = True
    lock.release()
   
    # Draw a black filled box to clear the image.           
    draw.rectangle((0,0,width,height), outline=0, fill=0)
    # Draw current page indicator
    if showPageIndicator:
        dotWidth=4
        dotPadding=2
        dotX=width-dotWidth-1
        dotTop=(height-pageCount*dotWidth-(pageCount-1)*dotPadding)/2
        for i in range(pageCount):
            if i==page_index:
                draw.rectangle((dotX, dotTop, dotX+dotWidth, dotTop+dotWidth), outline=255, fill=255)
            else:
                draw.rectangle((dotX, dotTop, dotX+dotWidth, dotTop+dotWidth), outline=255, fill=0)
            dotTop=dotTop+dotWidth+dotPadding

    if page_index==0:
        text = time.strftime("%A")
        draw.text((2,2),text,font=font14,fill=255)
        text = time.strftime("%e %b %Y")
        draw.text((2,18),text,font=font14,fill=255)
        text = time.strftime("%X")
        draw.text((2,40),text,font=fontb24,fill=255)
   
    elif page_index==1:
        # Draw some shapes.
        # First define some constants to allow easy resizing of shapes.
        padding = 2
        top = padding
        bottom = height-padding
        # Move left to right keeping track of the current x position for drawing shapes.
        x = 0
   IPAddress = get_ip()
        cmd = "top -bn1 | grep load | awk '{printf \"CPU Load: %.2f\", $(NF-2)}'"
        CPU = subprocess.check_output(cmd, shell = True )

        cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%sMB %.f%%\", $3,$2,$3*100/$2 }'"
        MemUsage = subprocess.check_output(cmd, shell = True )

        cmd = "df -h | awk '$NF==\"/\"{printf \"Disk: %d/%dGB %s\", $3,$2,$5}'"
        Disk = subprocess.check_output(cmd, shell = True )

        draw.text((x, top),       "IP: " + str(IPAddress),  font=font12, fill=255)
        draw.text((x, top+20),    str(CPU), font=font12, fill=255)
        draw.text((x, top+35),    str(MemUsage),  font=font12, fill=255)
        draw.text((x, top+50),    str(Disk),  font=font12, fill=255)

   
    elif page_index==2:       
       
        top=0
       
        # Draw a black filled box to clear the image.
        draw.rectangle((0, 0, width, height), outline=0, fill=0)
       
        # Get each of the 4 cores CPU useage
        cpu = psutil.cpu_percent(interval=1, percpu=True)       
   
        temp1r = "[                ]%3d" % int(cpu[0])
        temp2r = "[                ]%3d" % int(cpu[1])
        temp3r = "[                ]%3d" % int(cpu[2])   
        temp4r = "[                ]%3d" % int(cpu[3])   

        # Print the CPU's %
        draw.text((0, top     ), temp1r, font=font10, fill=255)   
        draw.text((0, top + 10), temp2r, font=font10, fill=255)   
        draw.text((0, top + 20), temp3r, font=font10, fill=255)   
        draw.text((0, top + 30), temp4r, font=font10, fill=255)

        # Draw the graphs   
        for x in range(0, int(cpu[0])):
           draw.line((x+4, 3, x+4, 7), fill=255)
   
        for x in range(0, int(cpu[1])):
           draw.line((x+4, 13, x+4, 17), fill=255)
   
        for x in range(0, int(cpu[2])):
           draw.line((x+4, 23, x+4, 27), fill=255)
   
        for x in range(0, int(cpu[3])):
           draw.line((x+4, 33, x+4, 37), fill=255)       

        tempStr = get_temp()
        draw.text((15, top+53),    tempStr,  font=font11, fill=255)

       
    elif page_index==3: #shutdown -- no
        draw.text((2, 2),  'Shutdown?',  font=fontb14, fill=255)

        draw.rectangle((2,20,width-4,20+16), outline=0, fill=0)
        draw.text((4, 22),  'Yes',  font=font11, fill=255)

        draw.rectangle((2,38,width-4,38+16), outline=0, fill=255)
        draw.text((4, 40),  'No',  font=font11, fill=0)

    elif page_index==4: #shutdown -- yes
        draw.text((2, 2),  'Shutdown?',  font=fontb14, fill=255)

        draw.rectangle((2,20,width-4,20+16), outline=0, fill=255)
        draw.text((4, 22),  'Yes',  font=font11, fill=0)

        draw.rectangle((2,38,width-4,38+16), outline=0, fill=0)
        draw.text((4, 40),  'No',  font=font11, fill=255)

    elif page_index==5:
        draw.text((2, 2),  'Shutting down',  font=fontb14, fill=255)
        draw.text((2, 20),  'Please wait',  font=font11, fill=255)

    oled.drawImage(image)

    lock.acquire()
    drawing = False
    lock.release()


def is_showing_power_msgbox():
    global pageIndex
    lock.acquire()
    page_index = pageIndex
    lock.release()
    if page_index==3 or page_index==4:
        return True
    return False


def update_page_index(pi):
    global pageIndex
    lock.acquire()
    pageIndex = pi
    lock.release()

def receive_signal(signum, stack):
    global pageIndex

    lock.acquire()
    page_index = pageIndex
    lock.release()

    if page_index==5:
        return

    if signum == signal.SIGUSR1:
        #print 'K1 pressed'
        if is_showing_power_msgbox():
            if page_index==3:
                update_page_index(4)
            else:
                update_page_index(3)
        else:
            pageIndex=0

        draw_page()

    if signum == signal.SIGUSR2:
        #print 'K2 pressed %d' % page_index
        if is_showing_power_msgbox():
            if page_index==4:
                update_page_index(5)
 
            else:
                update_page_index(0)
               
        else:
            if page_index==1:
                update_page_index(2)
               
            elif page_index==2:
                update_page_index(1)
               
            else:
                update_page_index(1)

        draw_page()
       

    if signum == signal.SIGALRM:
        #print 'K3 pressed'
        if is_showing_power_msgbox():
            update_page_index(0)

        else:
            update_page_index(3)

        draw_page()


image0 = Image.open('friendllyelec.png').convert('1')
oled.drawImage(image0)
time.sleep(2)

signal.signal(signal.SIGUSR1, receive_signal)
signal.signal(signal.SIGUSR2, receive_signal)
signal.signal(signal.SIGALRM, receive_signal)

while True:
    try:
       
        draw_page()

        lock.acquire()
        page_index = pageIndex
        lock.release()

        if page_index==5:
            time.sleep(2)
            while True:
                lock.acquire()
                is_drawing = drawing
                lock.release()
                if not is_drawing:
                    lock.acquire()
                    drawing = True
                    lock.release()
                    oled.clearDisplay()
                    break
                else:
                    time.sleep(.1)
                    continue
            time.sleep(1)
            os.system('systemctl poweroff')
            break
        time.sleep(1)
    except KeyboardInterrupt:                                                                                                         
        break                     
    except IOError:                                                                             
        print ("Error")