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")