Skip to content
Snippets Groups Projects
Commit cca3c5c6 authored by Torben Petersen's avatar Torben Petersen
Browse files

Adds Module for OLED Display

parent f1d70428
No related branches found
No related tags found
No related merge requests found
from . import Module
import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_GPIO.GPIO as GPIO
import Adafruit_SSD1306
import RPi.GPIO
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import sys
import socket
gpio = GPIO.RPiGPIOAdapter(RPi.GPIO, RPi.GPIO.BOARD)
class OLEDDisplay(Module):
def __init__(self, *args, **kwargs):
super(OLEDDisplay, self).__init__( *args, **kwargs )
setup_display()
def on_message(self, client, userdata, msg):
#react to recieved messages
logger.debug("on_message {} {}".format( msg.topic, msg.payload ))
def on_connect(self, client, userdata, flags, rc):
#subscribe to topics and do other stuff
def run(self):
self.running = True
while self.running:
#do stuff. What stuff?
time.sleep(50)
def setup_display(self):
# Create display
self.display = LCTCDisplay( gpio )
self.display.clear()
# Create menu entries
# TODO(rh): If no network is attached, this fails -> catch error here
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
myip = s.getsockname()[0]
s.close()
# ENDTODO(rh)
mainmenu = Menu()
controlentry = mainmenu.add( "Control" )
controlmenu = controlentry.submenu()
networkentry = mainmenu.add( "Network" )
networkmenu = networkentry.submenu()
networkmenu.add( "IP: " + str(myip) )
networkmenu.add( "Hostname: " + str( socket.gethostname() ) )
# button control
buttons = LCTCButtonControl(gpio, self.display, mainmenu)
# TODO(rh): Update thread for Menu required...
class LCTCDisplay:
OLED_RST = 26
OLED_DC = 22
SPI_PORT = 0
SPI_DEVICE = 0
LINE_OFFSET = 8
def __init__(self, gpio):
self.spi = SPI.SpiDev(self.SPI_PORT, self.SPI_DEVICE, max_speed_hz = 8000000)
# initialize display object
self.disp = Adafruit_SSD1306.SSD1306_128_64(gpio=gpio, rst=self.OLED_RST, dc=self.OLED_DC, spi=self.spi)
self.disp.begin()
# Clear display.
self.disp.clear()
self.disp.display()
# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
self.width = self.disp.width
self.height = self.disp.height
self.image_buffer = Image.new('1', (self.width, self.height))
self.font = ImageFont.load_default()
# Get drawing object to draw on image.
self.draw = ImageDraw.Draw(self.image_buffer)
def clear(self):
# Draw a black filled box to clear the image.
self.draw.rectangle((0,0, self.width, self.height), outline=0, fill=0)
def render(self, menu):
menu.render( self.draw, self.font, self.LINE_OFFSET, self.width, self.height )
self.disp.image( self.image_buffer )
self.disp.display()
class LCTCButtonControl:
BUTTONS = {12: 'left', 16: 'right', 11: 'down', 13: 'up'}
def __init__(self, gpio, display, menu):
self.state = dict()
self.display = display
# Set default menu and render it
self.menu = menu
for button in self.BUTTONS:
gpio.setup( button, GPIO.IN )
self.state[button] = gpio.is_low( button )
gpio.add_event_detect(button, GPIO.BOTH, callback=self.button_changed)
self.display.render( self.menu )
def button_changed(self, button):
state = not self.state[button]
self.state[button] = state
dir = self.BUTTONS[button]
if state:
if dir == 'down':
if self.menu.active is None:
self.menu.active = 0
elif self.menu.active < (len(self.menu.entries) - 1):
self.menu.active += 1
elif dir == 'up':
if self.menu.active is not None and self.menu.active > 0:
self.menu.active -= 1
elif dir == 'right':
# Check if active menu entry exists
if self.menu.active is not None:
# get entry from list
entry = self.menu.entries[ self.menu.active ]
# if the MenuEntry has a child
if entry.child is not None:
# display child
self.menu = entry.child
else:
logger.log( "Action on {}".format( entry.label ) )
elif dir == 'left':
if self.menu.parent is not None:
self.menu = self.menu.parent
self.display.render( self.menu )
class Menu:
def __init__(self, parent = None):
self.entries = list()
self.active = None
self.parent = parent
def add(self, label):
entry = MenuEntry( label, self )
self.entries.append( entry )
return entry
def render(self, draw, font, line_height, width, height):
INDICATOR_OFFSET = 120
draw.rectangle((0, 0, width, height), outline=0, fill=0)
x = 2
y = -2 + 2 * line_height
for i, entry in enumerate(self.entries):
fill = 255
if self.active is not None and i == self.active:
draw.rectangle((x, y+1, width, y+line_height+2), outline=0, fill=255)
fill = 0
draw.text((x,y), entry.label, font=font, fill=fill)
# if submenu available -> draw small rectangle
if entry.child is not None:
draw.line([(x + INDICATOR_OFFSET, y + 4), (x + INDICATOR_OFFSET + 2, y + 4 + 2), (x+INDICATOR_OFFSET, y+8), (x + INDICATOR_OFFSET, y+4)], fill=fill, width=1)
y += line_height
class MenuEntry:
def __init__(self, label, parent):
self.label = label
self.parent = parent
self.child = None
def submenu(self):
self.child = Menu(self.parent)
return self.child
if __name__ == '__main__':
# Raspberry Pi pin configuration:
gpio = GPIO.RPiGPIOAdapter(RPi.GPIO, RPi.GPIO.BOARD)
# Create display
display = LCTCDisplay( gpio )
display.clear()
# Create menu entries
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
myip = s.getsockname()[0]
s.close()
mainmenu = Menu()
controlentry = mainmenu.add( "Control" )
controlmenu = controlentry.submenu()
networkentry = mainmenu.add( "Network" )
networkmenu = networkentry.submenu()
networkmenu.add( "IP: " + str(myip) )
networkmenu.add( "Hostname: " + str( socket.gethostname() ) )
# button control
buttons = LCTCButtonControl(gpio, display, mainmenu)
while True:
time.sleep(100)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment