class TwolineDisplay: __lcd = None __animIdx = -1 __animChars = [] __screenMode = "" __port = 1 __logger = None def __init__(self, logger): self.__logger = logger return None def open(self): addr = self.__find_device(self.__port) if (addr < 1): raise exception self.__lcd = CharLCD(i2c_expander='PCF8574', address=addr, port=self.__port, cols=16, rows=2, dotsize=8, #charmap='A02', auto_linebreaks=True, backlight_enabled=True) self.__lcd.clear() self.__create_custom_chars() return True def close(self): self.__lcd.clear() self.__lcd.close() self.__lcd = None return True def __find_device(self,port): bus = smbus.SMBus(port) # 1 indicates /dev/i2c-1 for device in range(128): try: bus.read_byte(device) #print(hex(device)) return device except: # exception if read_byte fails pass return -1 def clear(self): self.__lcd.clear() self.__screenMode = "" def show_centered(self,line,text): self.__setScreenModeToText() self.__logger.debug("Display: " + text) self.__lcd.cursor_pos = (line, 0) self.__lcd.write_string(text.center(16)) def show_centered(self,line0,line1): self.__setScreenModeToText() self.__logger.debug("Display: " + (line0 if line0 is not None else "") + " || " + (line1 if line1 is not None else "")) if (line0 is not None): self.__lcd.cursor_pos = (0, 0) self.__lcd.write_string(line0.center(16)) if (line1 is not None): self.__lcd.cursor_pos = (1, 0) self.__lcd.write_string(line1.center(16)) def update_value_time_trend(self,value,mins,trend): self.__setScreenModeToEgv() valStr = "--" trendChars = " " if (value > 0): valStr = str(value) trendChars = self.__get_trend_chars(trend) print(valStr + " " + str(mins)) valStr = valStr.replace("0","O") valStr = valStr.rjust(6) self.__lcd.cursor_pos = (0, 0) self.__lcd.write_string(valStr) self.__lcd.cursor_pos = (1, 4) self.__lcd.write_string(trendChars) ageStr = self.update_age(mins) def update_age(self, mins): self.__setScreenModeToEgv() ageStr = "now" if (mins > 50): ageStr = "50+" elif (mins > 0): ageStr = str(mins) + "m" ageStr = ageStr.replace("0","O") ageStr = ageStr.rjust(3) self.__lcd.cursor_pos = (1, 13) self.__lcd.write_string(ageStr) def updateAnimation(self): self.__setScreenModeToEgv() self.__animIdx += 1 if (self.__animIdx >= len(self.__animChars)): self.__animIdx = 0 char = self.__animChars[self.__animIdx] self.__lcd.cursor_pos = (0, 15) self.__lcd.write_string(char) def __setScreenModeToEgv(self): if (not self.__screenMode == "egv"): self.__logger.debug("Display mode EGV") self.__screenMode = "egv" self.__lcd.clear() def __setScreenModeToText(self): if (not self.__screenMode == "text"): self.__logger.debug("Display mode Text") self.__screenMode = "text" self.__lcd.clear() def __get_trend_chars(self,trend): if(trend == Trend.NONE): return "**" if(trend == Trend.DoubleUp): return "\x01\x01" if(trend == Trend.SingleUp): return "\x01 " if(trend == Trend.FortyFiveUp): return "\x02 " if(trend == Trend.Flat): return "-\x7e" if(trend == Trend.FortyFiveDown): return "\x03 " if(trend == Trend.SingleDown): return "\x04 " if(trend == Trend.DoubleDown): return "\x04\x04" if(trend == Trend.NotComputable): return "NC" if(trend == Trend.RateOutOfRange): return "HI" return "??" #self.__lcd.write_string('\x02\x02 \x02 \x03 -\x7e \x05 \x06 \x06\x06') def __create_custom_chars(self): upArrow = ( 0b00000, 0b00100, 0b01110, 0b10101, 0b00100, 0b00100, 0b00100, 0b00100 ) self.__lcd.create_char(1, upArrow) upSlight = ( 0b00000, 0b00000, 0b00111, 0b00011, 0b00101, 0b01000, 0b10000, 0b00000 ) self.__lcd.create_char(2, upSlight) dnSlight = ( 0b00000, 0b00000, 0b10000, 0b01000, 0b00101, 0b00011, 0b00111, 0b00000 ) self.__lcd.create_char(3, dnSlight) dnArrow = ( 0b00000, 0b00100, 0b00100, 0b00100, 0b00100, 0b10101, 0b01110, 0b00100 ) self.__lcd.create_char(4, dnArrow) self.__animChars = [ '\x05', '\x06', '\x07' ] anim1 = ( 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000, 0b00010, 0b00000 ) self.__lcd.create_char(5, anim1) anim2 = ( 0b00000, 0b00000, 0b00000, 0b00100, 0b01010, 0b00100, 0b00000, 0b00000 ) self.__lcd.create_char(6, anim2) anim3 = ( 0b01100, 0b10010, 0b10010, 0b01100, 0b00000, 0b00000, 0b00000, 0b00000 ) self.__lcd.create_char(7, anim3)
class ScreenManager: """Manages Screens Creates the arborescence needed for a LedPanel and manages it Please call cleanup() once you have finished. """ def __init__(self, panel): self.panel = panel self.lcd_lock = threading.RLock() self.gpio_lock = threading.Lock() home = StartScreen('HOME', 'LedPanel 289', self, 'Made by N.V.Zuijlen') main_menu = MenuScreen('MAIN_MENU', 'Menu', self) manual_menu = MenuScreen('MANUAL_MENU', 'Manuel', self) universe_selector = ValueScreen('UNIVERSE_SELECTOR', 'Choix Univers', self, self.panel.start_universe, 0, math.inf) channel_selector = ValueScreen('CHANNEL_SELECTOR', 'Choix Adresse', self, self.panel.start_channel+1, 1, DMX_UNIVERSE_SIZE) blackout = ToggleScreen('BLACKOUT', 'Blackout', self) test_pattern = MacroScreen('TEST_PATTERN', 'Test leds', self, macros.TestPixels(panel.columns, panel.rows)) ip_info = InformationScreen('IP_INFO', 'Adresse IP', self, get_ip_address()) universe_selector.setCallback(lambda uni: self.panel.setAddress(universe=uni)) channel_selector.setCallback(lambda chan: self.panel.setAddress(channel=chan)) blackout.setCallback(lambda off: self.panel.setOnOff(not off)) home.addChild(main_menu) main_menu.addChild(universe_selector) main_menu.addChild(channel_selector) main_menu.addChild(manual_menu) main_menu.addChild(ip_info) manual_menu.addChild(blackout) manual_menu.addChild(test_pattern) self.current = home with self.lcd_lock: self.lcd = CharLCD(i2c_expander='PCF8574', address=0x3F, cols=20, rows=4, auto_linebreaks=False, backlight_enabled=False) self.lcd.cursor_mode = 'hide' # UP/DOWN arrow. Use as char \x00 self.lcd.create_char(0, ( 0b00100, 0b01110, 0b11111, 0b00000, 0b00000, 0b11111, 0b01110, 0b00100 )) self.updateScreen() #self.backlightOn() def listenToGPIO(self): for pin in [UP_BUTTON, DOWN_BUTTON, OK_BUTTON, BACK_BUTTON]: GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.add_event_detect( pin, GPIO.RISING, callback=self.getGPIOCallback(), bouncetime=200 ) def getGPIOCallback(self): def GPIOCallback(channel): with self.gpio_lock: GPIO.output(STATUS_LED, GPIO.HIGH) #self.backlightOn() if channel == UP_BUTTON: print("UP", channel) self.current.onUp() elif channel == DOWN_BUTTON: print("DOWN", channel) self.current.onDown() elif channel == OK_BUTTON: print("OK", channel) self.current.onOK() elif channel == BACK_BUTTON: print("BACK", channel) self.current.onBack() self.updateScreen() GPIO.output(STATUS_LED, GPIO.LOW) return GPIOCallback def backlightOn(self): self.on_time = datetime.now() with self.lcd_lock: self.lcd.backlight_enabled = True self.panel.threadSafeSchedule( 11*1000, self.turn_off_backlight_if_inactivity ) def turn_off_backlight_if_inactivity(self): if datetime.now() - self.on_time >= timedelta(seconds=10): with self.lcd_lock: self.lcd.backlight_enabled = False def updateScreen(self): self.current.computeDisplay() with self.lcd_lock: self.lcd.clear() self.lcd.write_string(self.current.first_line) self.lcd.crlf() self.lcd.write_string(self.current.second_line) def cleanup(self): GPIO.cleanup() with self.lcd_lock: self.lcd.close(clear=True)
if argv1 == 'rr': file = open('/srv/http/data/system/version') version = file.read().rstrip('\n') file.close() spaces = ' ' splash = '' if rows == 4: spaces += ' ' splash = rn splash += spaces + irr + rn + spaces + version lcd.write_string(splash) else: lcd.auto_linebreaks = True lcd.clear() lcd.write_string(argv1.replace('^', rn)) lcd.close() quit() lcd.clear() import math import unicodedata def second2hhmmss(sec): hh = math.floor(sec / 3600) mm = math.floor((sec % 3600) / 60) ss = sec % 60 HH = hh > 0 and str(hh) + ':' or '' mmt = str(mm) MM = hh > 0 and (mm > 9 and mmt + ':'
time.sleep(5) # Main body of code try: while True: line = tn.read_until("\n") # Read one line l1 = line.split() add = [" "," "," "," "," "," "," "," "," "," "] l1.extend(add) print(l1)[0],(l1)[1],(l1)[2],(l1)[3],(l1)[4],(l1)[5],(l1)[6],(l1)[7],(l1)[8] lcd.write_string((l1)[0]) lcd.write_string(" "+(l1)[1]) lcd.write_string(" "+(l1)[2]) lcd.cursor_pos = (1, 0) lcd.write_string((l1)[3]) lcd.write_string(" "+(l1)[4]) lcd.cursor_pos = (2, 0) lcd.write_string((l1)[5]) lcd.write_string(" "+(l1)[6]) time.sleep(10) #i add time between spot. If you want different seconds, change 10 lcd.close(clear=True) if b'abcd' in line: # last line, no more read break except KeyboardInterrupt: # If there is a KeyboardInterrupt (when you press ctrl+c), exit the pr$ print("Cleaning up!") lcd.close(clear=True)
class LCD: # Guard critical sections with shared class-lock LOCK = Lock() AXIS = 'XYZABC' POST_DECIMAL_PLACE = 1 PRE_DECIMAL_PLACE = 3 # Sign + Decimal Point + Digits before + Digits after WIDTH = 1 + 1 * (PRE_DECIMAL_PLACE > 0) + PRE_DECIMAL_PLACE + POST_DECIMAL_PLACE STATUS_LEN = 18 SW_I2C_PORT = 11 SW_I2C_SDA = 23 SW_I2C_SCL = 24 CONNECTED_CHAR = 0 DISCONNECTED_CHAR = 1 CONNECTED_SYMBOL = ( 0b01110, 0b10001, 0b10001, 0b10001, 0b11111, 0b11011, 0b11011, 0b11111, ) DISCONNECTED_SYMBOL = ( 0b01110, 0b10000, 0b10000, 0b10000, 0b11111, 0b11011, 0b11011, 0b11111, ) def __init__(self): # Adress and port expander type are fixed # Hide the specific implementation used try: self._lcd = CharLCD('PCF8574', 0x26, port=self.SW_I2C_PORT) except Exception: self.connected = False else: self.connected = True self._lcd.create_char(self.CONNECTED_CHAR, self.CONNECTED_SYMBOL) self._lcd.create_char(self.DISCONNECTED_CHAR, self.DISCONNECTED_SYMBOL) def print_pose(self, pose: List[float]): """ Prints a pose on the lower three rows of the display """ if self.connected: rows = 3 * [''] for i, (ax, val) in enumerate(zip(self.AXIS, pose)): if i >= 3: space = ' ' unit = chr(223) val = math.degrees(val) else: space = '' unit = ' mm' rows[ i % 3] += f'{ax}{val:+0{self.WIDTH}.{self.POST_DECIMAL_PLACE}f}{unit}{space}' display_str = '\r\n'.join(rows) # Critical section with self.LOCK: # Set cursor to start of second row and write positions self._lcd.cursor_pos = (1, 0) self._lcd.write_string(display_str) def print_connection(self, is_connected: bool): if self.connected: # Critical section with self.LOCK: # Move cursor to upper right corner self._lcd.cursor_pos = (0, self.STATUS_LEN + 1) if is_connected: self._lcd.write_string(chr(self.CONNECTED_CHAR)) else: self._lcd.write_string(chr(self.DISCONNECTED_CHAR)) def print_status(self, status: str): if self.connected: # Critical section with self.LOCK: self._lcd.home() if len(status) > self.STATUS_LEN: status = status[:self.STATUS_LEN + 1] else: status += ' ' * (self.STATUS_LEN - len(status)) # Critical section with self.LOCK: self._lcd.write_string(status) def __del__(self): if self.connected: # Critical section with self.LOCK: self._lcd.close()
class Display(): def __init__(self): self.lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1, cols=20, rows=4, dotsize=8, charmap='A00', auto_linebreaks=True) def rus_test(self): line = 'БГДЖЗИЙЛПУФЦЧШЩЬЫЮЯ ' line1 = line[0:8] line2 = line[8:16] line3 = line[16:19] str_out = '\x00\x01\x02\x03\x04\x05\x06\x07' for l in [line1, line2, line3]: for char in enumerate(l): self.lcd.create_char(char[0], chars_dict[char[1]]) self.lcd.write_string(str_out[:len(l)]) sleep(2) self.lcd.clear() self.lcd.backlight_enabled = False self.lcd.close(clear=True) def clear(self): self.lcd.clear() def welcome_message(self): # Здравствуйте # Нажмите # одну из кнопок # ЗДУЙ # ЖИЮП for char in enumerate('ЗДУЙЖИДП'): self.lcd.create_char(char[0], chars_dict[char[1]]) self.lcd.cursor_pos = (0, 4) self.lcd.write_string('\x00\x01PABCTB\x02\x03TE!') self.lcd.cursor_pos = (2, 6) self.lcd.write_string('HA\x04M\x05TE') self.lcd.cursor_pos = (3, 3) self.lcd.write_string('O\x06H\x02 \x05\x00 KHO\x07OK') def turn_off(self): self.lcd.clear() self.lcd.backlight_enabled = False self.lcd.close(clear=True) def print_rus_string(self, strings): """ Печатает набор строк на экране LCD2004 Подставляет русские символы, не более 8-ми :param strings: список вида [((row, col), string), ...] (row, col) - позиция начала строки string - содержание строки :return: True - строка выведена, False - строка не выведена """ strings = list(strings) long_string = '' # начальное преобразование и проверка словаря строк для вывода for item in strings: row = item[0][0] col = item[0][1] string = item[1].upper()[:min(20, len(item[1]))] if row > 3 | col > 19: raise ValueError('Illegal position') # формирование одной длинной строки для проверки long_string += item[1] strings[strings.index(item)] = ((row, col), string) rus_letters = list(chars_dict.keys( )) # строка русских символов (словарь индивидуальных символов) # выделение и проверка количества символов, требующих подстановки individual_chars = list( set([item for item in long_string.upper() if item in rus_letters])) if len(individual_chars) > 8: raise ValueError('Too many RUS symbols: {:d}'.format( len(individual_chars))) else: print('Total RUS characters: {:d}'.format(len(individual_chars))) # создание словаря escape - последовательностей for char in enumerate(individual_chars): self.lcd.create_char(char[0], chars_dict[char[1]]) # создание словаря строк для печати (английские буквы + escape последовательности) strings_to_print = [] for item in strings: row = item[0][0] col = item[0][1] string = item[1] string_to_print = '' for letter in list(string): if letter in individual_chars: string_to_print += escapes[individual_chars.index(letter)] else: string_to_print += eng_rus[letter] strings_to_print.append(((row, col), string_to_print)) for item in strings_to_print: self.lcd.cursor_pos = item[0] self.lcd.write_string(item[1])