You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
7.4 KiB
291 lines
7.4 KiB
import serial |
|
from thread import start_new_thread, allocate_lock |
|
import time |
|
import threading |
|
|
|
class Display(threading.Thread): |
|
def __init__(self,portname="/dev/ttyUSB0"): |
|
threading.Thread.__init__(self) |
|
self.serialport=None |
|
self.runme=True |
|
self.idlemessage=None |
|
self.portlock = allocate_lock() |
|
self.portname=portname |
|
self.brightness=5 |
|
self.scroll_line1 = None |
|
self.scroll_line2 = None |
|
self.offset_line1 = 0 |
|
self.offset_line2 = 0 |
|
self.screensaver = Screensaver(self) |
|
self.open_port() |
|
|
|
def __del__(self): |
|
if (not self.screensaver == None): |
|
self.screensaver = None |
|
|
|
if (not self.serialport == None): |
|
self.serialport.close() |
|
self.serialport=None |
|
|
|
def open_port(self): |
|
try: |
|
self.serialport = serial.Serial(self.portname,9600,timeout=2,rtscts=False, dsrdtr=False) |
|
#print ("Initializing display on port:\n %s\n" % self.serialport ) |
|
self.mutex_get() |
|
self.cmd_reset() |
|
self.mutex_release() |
|
except Exception as e: |
|
#print ("Exception opening serial port '%s' for display\n" % self.portname) |
|
#print ("Ignoring and trying to open it again later\n") |
|
#print (e) |
|
self.serialport = None |
|
|
|
|
|
#Helper-Function, scrolls text in a specific line. |
|
def display_scroll_text(self,line,text): |
|
if (line==1): #clear the line on invocation: |
|
self.cmd("\x1f\x24\x01%c\x18" % chr(line) ) |
|
self.scroll_line1 = text |
|
self.offset_line1=0 |
|
if (line==2): #clear the line on invocation: |
|
self.cmd("\x1f\x24\x01%c\x18" % chr(line) ) |
|
self.scroll_line2 = text |
|
self.offset_line2=0 |
|
|
|
|
|
def display_handle_scroll(self,line,text,offset): |
|
if (text): |
|
l = len(text) |
|
if (l<21): |
|
if (offset == 0): |
|
self.cmd("\x1f\x24\x01%c%s" % (chr(line),text[offset:(20+offset)])) |
|
offset=1 |
|
else: |
|
self.cmd("\x1f\x24\x01%c%s" % (chr(line),text[offset:(20+offset)])) |
|
missing_chars=20+offset-l |
|
if (missing_chars>0): |
|
self.cmd(text[:missing_chars]) |
|
offset=((offset+1)%l) |
|
else: |
|
offset=0 #reset offset |
|
return offset |
|
|
|
|
|
def run(self): |
|
#print "Starting Display thread" |
|
self.screensaver.start() |
|
while(self.runme): |
|
#print("display thread loop\n") |
|
self.mutex_get() |
|
#print("display got mutex and handles scroll\n") |
|
self.offset_line1 = self.display_handle_scroll(1,self.scroll_line1,self.offset_line1) |
|
self.offset_line2 = self.display_handle_scroll(2,self.scroll_line2,self.offset_line2) |
|
self.mutex_release() |
|
time.sleep(.5) |
|
print "Exiting Display thread" |
|
|
|
|
|
|
|
|
|
#Front-End Funtion to display a Screen |
|
# with heading |
|
def display_screen(self,title,message): |
|
self.mutex_get() |
|
|
|
self.offset_line1=0 |
|
self.offset_line2=0 |
|
self.screensaver.idle_reset(); |
|
self.cmd_brightness(5) |
|
|
|
if (len(title)<21): |
|
self.scroll_line1=None |
|
self.cmd("\x1f\x24\x01%c\x18%s" % (chr(1),'\xdb'*20) ) |
|
if (len(title)<20): |
|
pos=1+(20-len(title))/2 |
|
else: |
|
pos=1 |
|
self.cmd("\x1f\x24%c%c%s" % (chr(pos),chr(1),title) ) |
|
else: |
|
self.display_scroll_text(1,title) |
|
|
|
self.display_scroll_text(2,message) |
|
self.mutex_release() |
|
|
|
|
|
|
|
|
|
def cmd_reset(self): |
|
#reset the display |
|
self.cmd("\x1b\x40") |
|
|
|
def cmd_cursor_show(self,on=True): |
|
#show or hide the cursor |
|
if (on): |
|
self.cmd("\x1f\x43\x01") |
|
else: |
|
self.cmd("\x1f\x43\x00") |
|
|
|
def cmd_blink(self,rate=127): |
|
self.cmd("\x1f\x45%c" % chr(rate)) |
|
|
|
|
|
def cmd_brightness(self,level): |
|
if (self.brightness==level): |
|
return |
|
#print("setting brightness to %i \n" %level) |
|
if (level==0): #turn off: |
|
self.cmd_display_on(False) |
|
self.brightness = 0 |
|
return |
|
else: |
|
if (self.brightness==0): #turn on, then set wanted brightness: |
|
self.cmd_display_on(True) |
|
self.brightness = level |
|
self.cmd("\x1F\x58%c" % chr(level-1) ) |
|
|
|
def cmd_display_on(self,on=True): |
|
# blink-command: |
|
# where the last value defines the blink rate, |
|
# with 0=always on, 255=always off |
|
if (on): |
|
if (not self.brightness==0): |
|
return |
|
#print("setting display to on: %s \n" % str(on)) |
|
self.cmd_blink(0) |
|
self.brightness=5 |
|
else: |
|
if (self.brightness==0): |
|
return |
|
#print("setting display to on: %s \n" % str(on)) |
|
self.cmd_blink(255) |
|
self.brightness=0 |
|
|
|
def cmd_curmode_overwrite(self): |
|
self.cmd_curmode(1) |
|
|
|
def cmd_curmode_vscroll(self): |
|
self.cmd_curmode(2) |
|
|
|
def cmd_curmode_hscroll(self): |
|
self.cmd_curmode(3) |
|
|
|
def cmd_curmode(self,val=2): |
|
self.cmd("\x1f%c" % chr(val)) |
|
|
|
def cmd_home(self): |
|
self.cmd("\x0b") |
|
|
|
def cmd_clear(self): |
|
self.cmd("\x0c") |
|
|
|
def cmd_time(self): |
|
# activate timer display in lower right corner. |
|
# actual time has to be set via display_set_timer. |
|
self.cmd("\x1f\x55") |
|
|
|
def cmd_time_set(self,h=None,m=None): |
|
if (h==None or m==None): |
|
now = time.localtime() |
|
h=now.tm_hour |
|
m=now.tm_min |
|
# configures hour and minutes of the internal clock and |
|
# displays the time in the lower right corner. |
|
# turns off when something gets written into the line. |
|
# two bytes have to follow with hour and minute |
|
self.cmd("\x1F\x54%c%c" % (chr(h),chr(m)) ) |
|
self.cmd_curmode_hscroll() # makes the time more robust... |
|
|
|
def cmd(self,text): #for commands: do not reset screensaver timeout |
|
self.write(text,False) |
|
|
|
def write(self,text,idle_reset=True): #for data: reset screensaver timeout |
|
if (not self.serialport == None): |
|
if (idle_reset): |
|
self.screensaver.idle_reset(); |
|
self.scroll_line1=None |
|
self.scroll_line2=None |
|
self.serialport.write(text) |
|
else: |
|
self.open_port() |
|
|
|
def setIdlemessage(self,text): |
|
self.idlemessage=text |
|
|
|
def getIdlemessage(self): |
|
return self.idlemessage |
|
|
|
def mutex_get(self): |
|
self.portlock.acquire() |
|
|
|
def mutex_release(self): |
|
self.portlock.release() |
|
|
|
def terminate(self): |
|
self.runme=False |
|
if (not self.screensaver == None): |
|
self.screensaver.terminate() |
|
self.screensaver = None |
|
|
|
|
|
import threading |
|
import time |
|
|
|
class Screensaver (threading.Thread): |
|
def __init__(self,display): |
|
threading.Thread.__init__(self) |
|
self.display=display |
|
self.runme=True |
|
self.idlecounter=0 |
|
self.timeout_dim=30 |
|
self.timeout_message=60 |
|
self.timeout_off=300 |
|
self.mutex = allocate_lock() |
|
threading.Thread.__init__(self) |
|
|
|
def run(self): |
|
#print "Starting Screensaver thread" |
|
while(self.runme): |
|
self.mutex.acquire() |
|
self._main_loop() |
|
self.mutex.release() |
|
time.sleep(.5) |
|
#print "Exiting Screensaver thread" |
|
|
|
def terminate(self): |
|
self.runme = False |
|
|
|
|
|
def idle_reset(self): |
|
self.mutex.acquire() |
|
self.idlecounter=0 |
|
self.display.cmd_brightness(5) |
|
self.mutex.release() |
|
|
|
|
|
def _main_loop(self): |
|
if (self.idlecounter < self.timeout_off): |
|
self.idlecounter+=1 |
|
if (self.idlecounter>=self.timeout_dim and self.idlecounter <= (self.timeout_dim+7)): |
|
x = (8-( self.idlecounter - self.timeout_dim))/2 |
|
self.display.mutex_get() |
|
self.display.cmd_brightness(1+x) |
|
self.display.mutex_release() |
|
return |
|
|
|
if (self.idlecounter==self.timeout_message): |
|
self.display.mutex_get() |
|
self.display.cmd_time_set() |
|
self.display.scroll_line1 = self.display.getIdlemessage() |
|
self.display.scroll_line2 = None |
|
self.display.mutex_release() |
|
return |
|
|
|
if (self.idlecounter==self.timeout_off): |
|
self.display.mutex_get() |
|
self.display.cmd_display_on(False) |
|
self.display.mutex_release() |
|
return |
|
|
|
def __del__(self): |
|
print("bye") |
|
|
|
|