k4ever/client-barcode/display.py

292 lines
7.4 KiB
Python

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.terminate()
self.screensaver = None
if (not self.serialport == None):
self.serialport.close()
self.serialport=None
def open_port(self):
self.mutex_get()
try:
self.serialport = serial.Serial(self.portname,9600,timeout=2,rtscts=True, dsrdtr=True)
#print ("Initializing display on port:\n %s\n" % self.serialport )
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
self.mutex_release()
pass
#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"
def terminate(self):
self.runme = False
#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_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.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):
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=10
self.timeout_message=20
self.timeout_off=32
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.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")