Merge remote-tracking branch 'origin/display-florian-backup' into display-threading

Conflicts:
	client-barcode/freitagskasse.py
This commit is contained in:
Florian Streibelt 2011-10-19 01:08:05 +02:00
commit e7c73198f5
2 changed files with 268 additions and 203 deletions

View File

@ -1,74 +1,291 @@
import serial import serial
from thread import start_new_thread, allocate_lock
import time
import threading
class Display(threading.Thread):
class Display:
def __init__(self,portname="/dev/ttyUSB0"): def __init__(self,portname="/dev/ttyUSB0"):
threading.Thread.__init__(self)
self.serialport=None self.serialport=None
self.open_port(portname) 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): def __del__(self):
if (not self.screensaver == None):
self.screensaver = None
if (not self.serialport == None): if (not self.serialport == None):
self.serialport.close() self.serialport.close()
self.serialport=None self.serialport=None
def open_port(self,portname): def open_port(self):
self.serialport = serial.Serial(portname,9600,timeout=2,rtscts=True, dsrdtr=True)
print ("Initializing display:\n %s\n" % self.serialport ) 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.cmd_reset()
self.write("Hello world") 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"
#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): def cmd_reset(self):
#reset the display #reset the display
self.write("\x1b\x40") self.cmd("\x1b\x40")
def cmd_cursor_show(self,on=True): def cmd_cursor_show(self,on=True):
#show or hide the cursor #show or hide the cursor
if (on): if (on):
self.write("\x1f\x43\x01") self.cmd("\x1f\x43\x01")
else: else:
self.write("\x1f\x43\x00") self.cmd("\x1f\x43\x00")
def cmd_blink(self,rate=127): def cmd_blink(self,rate=127):
self.write("\x1f\x45%c" % rate) 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): def cmd_display_on(self,on=True):
# blink-command: # blink-command:
# where the last value defines the blink rate, # where the last value defines the blink rate,
# with 0=always on, 255=always off # with 0=always on, 255=always off
if (on): if (on):
if (not self.brightness==0):
return
#print("setting display to on: %s \n" % str(on))
self.cmd_blink(0) self.cmd_blink(0)
self.brightness=5
else: else:
if (self.brightness==0):
return
#print("setting display to on: %s \n" % str(on))
self.cmd_blink(255) self.cmd_blink(255)
self.brightness=0
def cmd_curmode_overwrite(self): def cmd_curmode_overwrite(self):
cmd_curmode(1) self.cmd_curmode(1)
def cmd_curmode_vscroll(self): def cmd_curmode_vscroll(self):
cmd_curmode(2) self.cmd_curmode(2)
def cmd_curmode_hscroll(self): def cmd_curmode_hscroll(self):
cmd_curmode(3) self.cmd_curmode(3)
def cmd_curmode(self,val=2): def cmd_curmode(self,val=2):
self.write("\x1f%c" % val) self.cmd("\x1f%c" % chr(val))
def cmd_clear(self): def cmd_clear(self):
self.write("\x0c") self.cmd("\x0c")
def cmd_time(self): def cmd_time(self):
# activate timer display in lower right corner. # activate timer display in lower right corner.
# actual time has to be set via display_set_timer. # actual time has to be set via display_set_timer.
self.write("\x1f\x55") self.cmd("\x1f\x55")
def cmd_time_set(self,h,m): 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 # configures hour and minutes of the internal clock and
# displays the time in the lower right corner. # displays the time in the lower right corner.
# turns off when something gets written into the line. # turns off when something gets written into the line.
# two bytes have to follow with hour and minute # two bytes have to follow with hour and minute
self.write("\x1F\x54%c%c" % (h,m) ) 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): 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) 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.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")

View File

@ -42,7 +42,6 @@ display_fifo = None
scroll_line1 = None scroll_line1 = None
scroll_line2 = None scroll_line2 = None
idlemessage = None
offset_line1 = 0 offset_line1 = 0
offset_line2 = 0 offset_line2 = 0
@ -56,158 +55,6 @@ SCREENSAVER_OFF = 2* 10*60
lock = allocate_lock() lock = allocate_lock()
#Helper-Function, scrolls text in a specific line.
def display_scroll_text(line,text):
global scroll_line1,scroll_line2
global offset_line1,offset_line2
lock.acquire()
if (line==1): #clear the line on invocation:
send_display("\x1f\x24\x01%c\x18" % chr(line) )
scroll_line1 = text
offset_line1=0
if (line==2): #clear the line on invocation:
send_display("\x1f\x24\x01%c\x18" % chr(line) )
scroll_line2 = text
offset_line2=0
lock.release()
def display_handle_scroll(line,text,offset):
if (text):
l = len(text)
if (l<21):
if (offset == 0):
send_display("\x1f\x24\x01%c%s" % (chr(line),text[offset:(20+offset)]))
offset=1
else:
send_display("\x1f\x24\x01%c%s" % (chr(line),text[offset:(20+offset)]))
missing_chars=20+offset-l
if (missing_chars>0):
send_display(text[:missing_chars])
offset=((offset+1)%l)
else:
offset=0 #reset offset
return offset
def display_cmd_dim(x):
global brightness
if (brightness!=x):
if (x==0): #turn off:
send_display("\x1F\x45%c" % chr(255) )
brightness = x
return
else:
if (brightness==0): #turn on, then set wanted brightness:
send_display("\x1F\x45%c" % chr(0) )
brightness = x
send_display("\x1F\x58%c" % chr(x-1) )
def display_thread(x):
global scroll_line1,scroll_line2
global offset_line1,offset_line2
global screensaver
global idlemessage
offset_line1=0
offset_line2=0
while(True):
lock.acquire()
offset_line1 = display_handle_scroll(1,scroll_line1,offset_line1)
offset_line2 = display_handle_scroll(2,scroll_line2,offset_line2)
if (screensaver <= SCREENSAVER_OFF):
screensaver=screensaver+1
if ((screensaver >= SCREENSAVER_DIM) and (screensaver <= (SCREENSAVER_DIM+7))): #activate first stage of screensaver:
x = (8-( screensaver - SCREENSAVER_DIM))/2
display_cmd_dim(1+x)
if (screensaver == SCREENSAVER_TIMEOUT):
now = time.localtime()
send_display("\x0c\x1F\x54%c%c\x1f\x03" % (chr(now.tm_hour),chr(now.tm_min)));
if (scroll_line2):
scroll_line1=scroll_line2
else:
scroll_line1=idlemessage
scroll_line2=None
offset_line1=0
offset_line2=0
if (screensaver == SCREENSAVER_OFF):
display_cmd_dim(0)
lock.release()
time.sleep(.5)
def send_display(s):
global display_fifo
if not display_fifo:
try:
fd = os.open( "/tmp/display", os.O_WRONLY)
display_fifo = os.fdopen(fd,"w")
except OSError:
display_fifo = None
pass
return
except IOError:
display_fifo = None
pass
return
try:
display_fifo.write(s)
display_fifo.flush()
except IOError:
display_fifo = None
pass
return
#Front-End Funtion to display a Screen
# with heading
def display_screen(title,message):
global scroll_line1,scroll_line2
global offset_line1,offset_line2
global screensaver
offset_line1=0
offset_line2=0
screensaver=0
display_cmd_dim(5)
if (len(title)<21):
scroll_line1=None
send_display("\x1f\x24\x01%c\x18%s" % (chr(1),'\xdb'*20) )
if (len(title)<20):
pos=1+(20-len(title))/2
else:
pos=1
send_display("\x1f\x24%c%c%s" % (chr(pos),chr(1),title) )
else:
display_scroll_text(1,title)
display_scroll_text(2,message)
#Front-End function to send data to the display.
def print_display(s):
global scroll_line1,scroll_line2
global offset_line1,offset_line2
global screensaver
lock.acquire()
screensaver=0
offset_line1=0
offset_line2=0
scroll_line1=None
scroll_line2=None
display_cmd_dim(5)
send_display(s)
lock.release()
def clear(): def clear():
os.system('clear') os.system('clear')
@ -328,7 +175,7 @@ class Status:
if self.logged_in(): if self.logged_in():
print('Eingeloggt als: %s%s%s' % (COLOR_SOME, self.login_name, COLOR_RESET)) print('Eingeloggt als: %s%s%s' % (COLOR_SOME, self.login_name, COLOR_RESET))
print() print()
print_display('\x0cHallo %-14s' % (self.login_name[:13]+"!") ) myDisplay.write('\x0cHallo %-14s' % (self.login_name[:13]+"!") )
if self.transfers: if self.transfers:
initial_command, initial_balance = self.transfers[0] initial_command, initial_balance = self.transfers[0]
@ -360,11 +207,11 @@ class Status:
mylabel="Pfand "+command.commodity_label()[:9] mylabel="Pfand "+command.commodity_label()[:9]
if (mycmd==3): if (mycmd==3):
mylabel=("%-13s" % (command.commodity_label()[:13]))+"+P" mylabel=("%-13s" % (command.commodity_label()[:13]))+"+P"
print_display('\x0b%-15s %4.2f' % (asciify(mylabel)[:15],abs(command.difference()))); myDisplay.write('\x0b%-15s %4.2f' % (asciify(mylabel)[:15],abs(command.difference())));
print_display('\x0b\nSUMME: {%02i} %8.2f' % ((i-1),initial_balance - self.balance)); myDisplay.write('\x0b\nSUMME: {%02i} %8.2f' % ((i-1),initial_balance - self.balance));
else: else:
print_display('\x0b%-15s %4.2f' % (command.label()[:15],abs(command.difference()))); myDisplay.write('\x0b%-15s %4.2f' % (command.label()[:15],abs(command.difference())));
print_display('\x0b\nSUMME: {%02i} %8.2f' % ((i-1),initial_balance - self.balance)); myDisplay.write('\x0b\nSUMME: {%02i} %8.2f' % ((i-1),initial_balance - self.balance));
if len(self.transfers) > 1: if len(self.transfers) > 1:
show_total(self.balance - initial_balance, plus='+') show_total(self.balance - initial_balance, plus='+')
@ -373,13 +220,13 @@ class Status:
if self.balance < 0: if self.balance < 0:
warn_balance() warn_balance()
print_display('\x0b\nKonto: %5.2f!' % (self.balance) ) myDisplay.write('\x0b\nKonto: %5.2f!' % (self.balance) )
print() print()
print(COLOR_MUCH + 'Committen nicht vergessen.' + COLOR_RESET) print(COLOR_MUCH + 'Committen nicht vergessen.' + COLOR_RESET)
else: else:
print('Kontostand beträgt: %s%.2f Euro%s' % (COLOR_MUCH, self.balance, COLOR_RESET)) print('Kontostand beträgt: %s%.2f Euro%s' % (COLOR_MUCH, self.balance, COLOR_RESET))
display_screen("KONTOSTAND","%s: %.2f Euro" % (self.login_name,self.balance)) myDisplay.display_screen("KONTOSTAND","%s: %.2f Euro" % (self.login_name,self.balance))
if self.balance < 0: if self.balance < 0:
print() print()
warn_balance() warn_balance()
@ -387,7 +234,7 @@ class Status:
print(COLOR_MUCH + 'Bitte einloggen.' + COLOR_RESET) print(COLOR_MUCH + 'Bitte einloggen.' + COLOR_RESET)
print() print()
print('Scanne dazu deine ID-Karte mit dem Barcode-Leser.') print('Scanne dazu deine ID-Karte mit dem Barcode-Leser.')
display_screen("LOGIN","Bitte scanne Deinen login-Token! *** ") myDisplay.display_screen("LOGIN","Bitte scanne Deinen login-Token! *** ")
print() print()
def logged_in(self): def logged_in(self):
@ -416,7 +263,7 @@ class Status:
try: try:
command.run(self.login_name) command.run(self.login_name)
except urllib2.HTTPError as e: except urllib2.HTTPError as e:
print_display('\x0cFEHLER: Server Error%20s' % str(e)[:20]) myDisplay.display_screen("Server error",'Server Error: %s' % str(e))
error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e)) error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e))
break break
else: else:
@ -499,11 +346,11 @@ class Status:
error_page(_PRODUCT_FIRST) error_page(_PRODUCT_FIRST)
return return
if prev.includes_deposit(): if prev.includes_deposit():
print_display('\x0cFEHLER: schon Pfand %20s' % prev.item_name()[:20]) myDisplay.write('\x0cFEHLER: schon Pfand %20s' % prev.item_name()[:20])
error_page('FEHLER: Pfand für Produkt "%s" bereits aktiviert' % prev.item_name()) error_page('FEHLER: Pfand für Produkt "%s" bereits aktiviert' % prev.item_name())
return return
if prev.deposit_value() <= 0: if prev.deposit_value() <= 0:
print_display('\x0cFEHLER: Pfandfrei! %20s' % prev.item_name()[:20]) myDisplay.write('\x0cFEHLER: Pfandfrei! %20s' % prev.item_name()[:20])
error_page('FEHLER: Produkt "%s" hat kein Pfand' % prev.item_name()) error_page('FEHLER: Produkt "%s" hat kein Pfand' % prev.item_name())
return return
before = prev.difference() before = prev.difference()
@ -545,14 +392,14 @@ def print_prompt():
def handle(line, status): def handle(line, status):
global idlemessage
if line == 'exit': if line == 'exit':
clear() clear()
print_display("\x0c") myDisplay.write("\x0c")
myDisplay.terminate()
sys.exit(0) sys.exit(0)
if status.logged_in(): if status.logged_in():
idlemessage=" Comitten nicht vergessen! ***" myDisplay.setIdlemessage(" Comitten nicht vergessen! ***")
if line in CODES: if line in CODES:
call = CODES[line] call = CODES[line]
method = call[0] method = call[0]
@ -563,15 +410,15 @@ def handle(line, status):
item = status.find(line) item = status.find(line)
except urllib2.HTTPError as e: except urllib2.HTTPError as e:
if e.code == 404: # URL not found == item not found with REST if e.code == 404: # URL not found == item not found with REST
print_display('\x0cERROR: %13sCode ist unbekannt' % ( line[:13])) myDisplay.display_screen("FEHLER","Code ist unbekannt: '%s'" % ( line[:23]))
error_page('FEHLER: Aktion oder Ware "%s" nicht bekannt' % line) error_page('FEHLER: Aktion oder Ware "%s" nicht bekannt' % line)
else: else:
print_display('\x0cERROR: Server Error%20s' % str(e)[:20]) myDisplay.display_screen("Server error",'%20s' % str(e)[:20])
error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e)) error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e))
else: else:
status.buy(item) status.buy(item)
else: else:
idlemessage="Mir ist langweilig!" myDisplay.setIdlemessage("Mir ist langweilig!")
try: try:
status.login(line) status.login(line)
except urllib2.HTTPError as e: except urllib2.HTTPError as e:
@ -584,7 +431,7 @@ def handle(line, status):
pass pass
if item is None: if item is None:
display_screen("FEHLER","Nutzer ist unbekannt: '%s' *** " % line) myDisplay.display_screen("FEHLER","Nutzer ist unbekannt: '%s' *** " % line)
error_page('FEHLER: Produkt oder Nutzer "%s" nicht bekannt' % line, error_page('FEHLER: Produkt oder Nutzer "%s" nicht bekannt' % line,
hint_message='Ist in der WebApp unter "Einstellungen" ' \ hint_message='Ist in der WebApp unter "Einstellungen" ' \
@ -592,8 +439,9 @@ def handle(line, status):
'als erlaubt markiert?') 'als erlaubt markiert?')
else: else:
item_info_page(item) item_info_page(item)
else: else:
print_display('\x0cFEHLER: Server Error%20s' % str(e)[:20]) myDisplay.display_screen("FEHLER",'Server Error %20s' % str(e)[:20])
error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e)) error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e))
except urllib2.URLError as e: except urllib2.URLError as e:
error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e)) error_page('FEHLER bei Kommunikation mit Server "%s"' % str(e))
@ -615,21 +463,19 @@ def main():
global myDisplay global myDisplay
myDisplay = Display("/dev/ttyUSB0") myDisplay = Display("/dev/ttyUSB0")
myDisplay.start()
myDisplay.cmd_reset() myDisplay.cmd_reset()
myDisplay.cmd_cursor_show(False)
print_display("\x1b\x40\x1f\x43\x00") myDisplay.display_screen("HINWEIS","Herzlich willkommen bei der Freitagsrunde! *** ")
start_new_thread(display_thread,(1,)) time.sleep(5)
#display_scroll_text(1,"Line1: Text, dumm scrollend!")
#display_scroll_text(4,"Line2: Und hier Text, auch dumm scrollend!")
display_screen("HINWEIS","Herzlich willkommen bei der Freitagsrunde! *** ")
while True: while True:
clear() clear()
status.dump() status.dump()
print_prompt() print_prompt()
line = read_line(sys.stdin, timeout=3*60.0, timeout_func=status.logout) line = read_line(sys.stdin, timeout=3*60.0, timeout_func=status.logout)
if line: if line:
print_display('\x0cBarcode:\n%20s' % line[:20]) myDisplay.write('\x0cBarcode:\n%20s' % line[:20])
handle(line, status) handle(line, status)
@ -637,5 +483,7 @@ if __name__ == '__main__':
try: try:
main() main()
except KeyboardInterrupt: except KeyboardInterrupt:
myDisplay.terminate()
myDisplay.write("\x1b\x40Goodbye!")
pass pass
print_display("\x1b\x40Goodbye!")