Exemplo n.º 1
0
    def update_lcd(self):
        if not self.lcd1.connected:
            self.lcd1 = lcd.LCD(0x3f)

        if not self.lcd2.connected:
            self.lcd2 = lcd.LCD(0x20)
        UNUSED_PARAMS = ('GPS', 'TIME')

        if len(self.data) == 0:
            return

        while dataread.DataRead.POSSIBLE_DATA[self.lcd_itr] in UNUSED_PARAMS:
            self.lcd_itr += 1

        name = dataread.DataRead.POSSIBLE_DATA[self.lcd_itr]

        self.lcd1.send_string(
            name + '(' + Application.UNITS[name] + '): ' +
            str(self.data[name]), lcd.LCD.LINE_1)

        self.lcd_itr += 1

        while dataread.DataRead.POSSIBLE_DATA[self.lcd_itr] in UNUSED_PARAMS:
            self.lcd_itr1 += 1

        name = dataread.DataRead.POSSIBLE_DATA[self.lcd_itr]

        self.lcd1.send_string(
            name + '(' + Application.UNITS[name] + '): ' +
            str(self.data[name]), lcd.LCD.LINE_2)

        self.lcd_itr += 1
        self.update_lcd_label()
Exemplo n.º 2
0
 def __init__(self):
     self.lcd = lcd.LCD()
     self.alive = True
     self.run = None
     self.measurement = None
     self.state = None
     self.controller = None
Exemplo n.º 3
0
def main():
    mylcd = lcd.LCD()
    mylcd.clear()
    mylcd.text(0, 0, lcd.pi_char + "hello, world!")
    off = 7
    for c in lcd.bar_chars:
        mylcd.text(off, 1, c)
        off += 1
    on = True
    col_map = (lcd.RED, lcd.GREEN, lcd.BLUE, lcd.WHITE)
    col = 0
    try:
        while True:
            but = mylcd.buttonRead()
            if but is None or but == 0xc:
                break
            if but == 1:
                if not on:
                    on = True
            if on:
                col = (col + 1) % 4
                mylcd.text(4, 1, "%d" % col)
                mylcd.backlight(col_map[col])
                on = False
            mylcd.text(0, 1, "%02x" % but)
            time.sleep(0.25)
    except KeyboardInterrupt:
        pass
    finally:
        mylcd.off()
        print("bye")
Exemplo n.º 4
0
        def process(pipe, config):
            import lcd
            print('lcd process on', os.getpid())
            self.lcd = lcd.LCD(self.hat.config)
            self.lcd.pipe = pipe

            if self.lcd.use_glut:
                from OpenGL.GLUT import glutMainLoop, glutIdleFunc
                glutIdleFunc(self.lcd.poll)
                glutMainLoop()
            else:
                while True:
                    self.lcd.poll()
Exemplo n.º 5
0
def main():
    screen = lcd.LCD()
    while True:
        clock_line = time.strftime('%I:%M %p')
        day_line = time.strftime('%A')
        date_line = time.strftime('%B %d, %Y')

        if time.localtime().tm_sec % 2:
            clock_line = clock_line[:2] + ' ' + clock_line[3:]

        if clock_line[0] == '0':
            clock_line = clock_line[1:]

        screen.set_lines([clock_line, day_line, ' ', date_line])
        screen.send_lines()
Exemplo n.º 6
0
    def _update(self):
        self.timeout = None

        try:
            if self.lcd is None:
                self.lcd = lcd.LCD(self.ctrl.i2c, self.addr, self.height,
                                   self.width)

            if self.reset:
                self.lcd.reset()
                self.redraw = True
                self.reset = False

            cursorX, cursorY = -1, -1

            for y in range(self.height):
                for x in range(self.width):
                    c = self.page.data[x][y]

                    if self.redraw or self.screen[x][y] != c:
                        if cursorX != x or cursorY != y:
                            self.lcd.goto(x, y)
                            cursorX, cursorY = x, y

                        self.lcd.put_char(c)
                        cursorX += 1
                        self.screen[x][y] = c

            self.redraw = False

        except IOError as e:
            # Try next address
            #self.addr_num += 1
            #if len(self.addrs) <= self.addr_num: self.addr_num = 0
            #self.addr = self.addrs[self.addr_num]
            #self.lcd = None

            #self.log.warning('LCD communication failed, ' +
            #            'retrying on address 0x%02x: %s' % (self.addr, e))

            #self.log.warning('LCD not present.')

            #self.reset = True
            self.reset = False
Exemplo n.º 7
0
def main():
    mylcd = lcd.LCD()
    print("using", mylcd.__class__.__name__)
    mylcd.clear()
    offset = 1
    try:
        while True:
            but = mylcd.buttonRead()
            if but is None or but == 0xc:
                break
            elif but == lcd.BUTTON_LEFT | lcd.BUTTON_UP:
                offset -= 1
            elif but == lcd.BUTTON_RIGHT | lcd.BUTTON_UP:
                offset += 1
            show(mylcd, offset)
            time.sleep(1)
    except KeyboardInterrupt:
        pass
    finally:
        mylcd.off()
        print("bye")
Exemplo n.º 8
0
    def __init__(self):
        # read config
        self.config = {
            'remote': False,
            'host': '127.0.0.1',
            'actions': {},
            'pi.ir': True,
            'arduino.ir': False,
            'arduino.nmea.in': False,
            'arduino.nmea.out': False,
            'arduino.nmea.baud': 4800,
            'lcd': {}
        }
        self.configfilename = os.getenv('HOME') + '/.pypilot/hat.conf'
        print('loading config file:', self.configfilename)
        try:
            file = open(self.configfilename)
            config = pyjson.loads(file.read())
            file.close()
            for name in config:
                self.config[name] = config[name]
        except Exception as e:
            print('config failed:', e)

        try:
            configfile = '/proc/device-tree/hat/custom_0'
            f = open(configfile)
            hat_config = pyjson.loads(f.read())
            f.close()
            print('loaded device tree hat config')
            if not 'hat' in self.config or hat_config != self.config['hat']:
                self.config['hat'] = hat_config
                print('writing device tree hat to hat.conf')
                self.write_config()
        except Exception as e:
            print('failed to load', configfile, ':', e)

        if not 'hat' in self.config:
            if os.path.exists('/dev/spidev0.0'):
                print(
                    'assuming original 26 pin tinypilot with nokia5110 display'
                )
                self.config['hat'] = {
                    'lcd': {
                        'driver': 'nokia5110',
                        'port': '/dev/spidev0.0'
                    },
                    'lirc': 'gpio4'
                }
            self.write_config()

        self.servo_timeout = time.monotonic() + 1

        self.last_msg = {}
        self.last_msg['ap.enabled'] = False
        self.last_msg['ap.heading_command'] = 0

        if self.config['remote']:
            host = self.config['host']
        else:
            host = 'localhost'
        self.client = pypilotClient(host)
        self.client.registered = False
        self.watchlist = ['ap.enabled', 'ap.heading_command']
        for name in self.watchlist:
            self.client.watch(name)
        self.lcd = lcd.LCD(self)
        self.gpio = gpio.gpio()
        self.arduino = Arduino(self)

        self.poller = select.poll()
        self.poller.register(self.arduino.pipe, select.POLLIN)

        self.lirc = lircd.lirc(self.config)
        self.lirc.registered = False
        self.keytimes = {}
        self.keytimeouts = {}

        # keypad for lcd interface
        self.actions = []
        keypadnames = [
            'auto', 'menu', 'port1', 'starboard1', 'select', 'port10',
            'starboard10', 'tack', 'dodge_port', 'dodge_starboard'
        ]

        for i in range(len(keypadnames)):
            self.actions.append(ActionKeypad(self.lcd, i, keypadnames[i]))

        # stateless actions for autopilot control
        self.actions += [
            ActionEngage(self),
            ActionPypilot(self, 'disengage', 'ap.enabled', False),
            ActionHeading(self, 1),
            ActionHeading(self, -1),
            ActionHeading(self, 2),
            ActionHeading(self, -2),
            ActionHeading(self, 5),
            ActionHeading(self, -5),
            ActionHeading(self, 10),
            ActionHeading(self, -10),
            ActionPypilot(self, 'compassmode', 'ap.mode', 'compass'),
            ActionPypilot(self, 'gpsmode', 'ap.mode', 'gps'),
            ActionPypilot(self, 'windmode', 'ap.mode', 'wind'),
            ActionPypilot(self, 'center', 'servo.position', 0),
            ActionTack(self, 'tackport', 'port'),
            ActionTack(self, 'tackstarboard', 'starboard'),
            ActionNone()
        ]

        for action in self.actions:
            if action.name in self.config['actions']:
                action.keys = self.config['actions'][action.name]

        self.web = Web(self)

        def cleanup(signal_number, frame=None):
            print('got signal', signal_number, 'cleaning up', os.getpid())
            childpids = []
            processes = [self.arduino, self.web]
            for process in processes:
                if process.process:
                    childpids.append(process.process.pid)
            if signal_number == signal.SIGCHLD:
                pid = os.waitpid(-1, os.WNOHANG)
                if not pid[0] in childpids:
                    print('subprocess returned', pid, childpids)
                    # flask or system makes process at startup that dies
                    return
                print('child process', pid, childpids)
            while childpids:
                pid = childpids.pop()
                #print('kill!', pid, childpids, os.getpid())
                try:
                    os.kill(pid, signal.SIGTERM)  # get backtrace
                except ProcessLookupError:
                    pass  # ok, process is already terminated
                sys.stdout.flush()
            for process in processes:
                process.process = False
            if signal_number != 'atexit':
                raise KeyboardInterrupt  # to get backtrace on all processes
            sys.stdout.flush()

        for s in range(1, 16):
            if s != 9 and s != 13:
                signal.signal(s, cleanup)
        signal.signal(signal.SIGCHLD, cleanup)
        import atexit
        atexit.register(lambda: cleanup('atexit'))
Exemplo n.º 9
0
try:
    import micropython
except:
    pass


def mandelbrot():
    # returns True if c, complex, is in the Mandelbrot set
    # @micropython.native
    def in_set(c):
        z = 0
        for i in range(40):
            z = z * z + c
            if abs(z) > 60:
                return False
        return True

    lcd.clear()
    for u in range(91):
        for v in range(31):
            if in_set((u / 30 - 2) + (v / 15 - 1) * 1j):
                lcd.set(u, v)
    lcd.show()


# PC testing
import lcd

lcd = lcd.LCD(128, 32)
mandelbrot()
Exemplo n.º 10
0
#         This Source describes Open Hardware and is licensed under the        #
#                                 CERN-OHL-S v2.                               #
#                                                                              #
#         You may redistribute and modify this Source and make products        #
#    using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl).  #
#           This Source is distributed WITHOUT ANY EXPRESS OR IMPLIED          #
#    WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS  #
#     FOR A PARTICULAR PURPOSE. Please see the CERN-OHL-S v2 for applicable    #
#                                  conditions.                                 #
#                                                                              #
#                Source location: https://github.com/buildbotics               #
#                                                                              #
#      As per CERN-OHL-S v2 section 4, should You produce hardware based on    #
#    these sources, You must maintain the Source Location clearly visible on   #
#    the external case of the CNC Controller or other product you make using   #
#                                  this Source.                                #
#                                                                              #
#                For more information, email [email protected]              #
#                                                                              #
################################################################################

import lcd

if __name__ == "__main__":
    screen = lcd.LCD(1, 0x27)

    screen.clear()
    screen.display(0, 'Buildbotics', lcd.JUSTIFY_CENTER)
    screen.display(1, 'Controller', lcd.JUSTIFY_CENTER)
    screen.display(3, 'Booting...', lcd.JUSTIFY_CENTER)
Exemplo n.º 11
0
KEYPAD = keypad.Keypad(settings["keypad_characters"],
                       settings["keypad_row_pins"],
                       settings["keypad_col_pins"])

# initialize PIR
GPIO.setup(settings["pir_pin"], GPIO.IN)

# initialize twilio
# TWILIO_CLIENT = Client(settings["twilio_account_sid"], settings["twilio_auth_token"])

# initialize gas sensor
GAS_SENSOR = DigitalInputDevice(settings["gas_pin"])

# initialize LCD
LCD = lcd.LCD(settings["lcd_rs"], settings["lcd_e"], settings["lcd_d4"],
              settings["lcd_d5"], settings["lcd_d6"], settings["lcd_d7"],
              settings["lcd_chr"], settings["lcd_cmd"], settings["lcd_chars"],
              settings["lcd_line_1"], settings["lcd_line_2"])

# initialize relays and alarm
for i in range(1, 4):
    x = "relay" + str(i) + "_pin"
    if x in settings and settings[x] > 0:
        GPIO.setup(settings[x], GPIO.OUT)
        GPIO.output(settings[x], 1)
if "alarm_pin" in settings and settings["alarm_pin"] > 0:
    GPIO.setup(settings["alarm_pin"], GPIO.OUT)
    GPIO.output(settings["alarm_pin"], 1)

# initialize DHT11 sensor
DHT11_TEMP = None
DHT11_HUM = None
Exemplo n.º 12
0
def featurize_LCD_VLAD(list_of_demonstrations,
                       kinematics,
                       layer,
                       net_name,
                       folder,
                       dimensions,
                       batch_size,
                       fname,
                       config=[True, True, True]):
    M = dimensions[0]
    a = dimensions[1]

    print "Featurizing LCD + VLAD: ", layer, net_name, folder, M, a, batch_size

    BATCH_SIZE = batch_size

    if constants.SIMULATION:
        BATCH_SIZE = 5

    data_X_PCA = {}
    data_X_CCA = {}
    data_X_GRP = {}

    size_sampled_matrices = [
        utils.sample_matrix(kinematics[demo],
                            sampling_rate=BATCH_SIZE).shape[0]
        for demo in list_of_demonstrations
    ]
    PC = min(100, min(size_sampled_matrices))
    print "PC: ", PC

    for demonstration in list_of_demonstrations:
        print demonstration
        W = kinematics[demonstration]
        Z = load_cnn_features(demonstration, layer, folder, net_name)
        W_new = utils.sample_matrix(W, sampling_rate=BATCH_SIZE)

        Z_batch = None
        W_batch = None
        j = 1

        Z_new = None

        IPython.embed()

        PATH_TO_ANNOTATION = constants.PATH_TO_DATA + constants.ANNOTATIONS_FOLDER + demonstration + "_" + str(
            constants.CAMERA) + ".p"
        start, end = utils.get_start_end_annotations(PATH_TO_ANNOTATION)

        Z = []

        IPython.embed()

        for i in range(Z):

            vector_W = W[i]
            W_batch = utils.safe_concatenate(W_batch, vector_W)

            vector_Z = Z[i]
            vector_Z = vector_Z.reshape(M, a, a)
            vector_Z = lcd.LCD(vector_Z)
            Z_batch = utils.safe_concatenate(Z_batch, vector_Z)

            if (j == BATCH_SIZE):
                print "NEW BATCH", str(i)
                Z_batch_VLAD = encoding.encode_VLAD(Z_batch)
                Z_new = utils.safe_concatenate(Z_new, Z_batch_VLAD)

                # Re-initialize batch variables
                j = 0
                Z_batch = None
                W_batch = None

            j += 1

        # tail case
        if Z_batch is not None:
            print "TAIL CASE"
            print "NEW BATCH", str(i)
            Z_batch_VLAD = encoding.encode_VLAD(Z_batch)
            Z_new = utils.safe_concatenate(Z_new, Z_batch_VLAD)

        if config[0]:
            Z_new_pca = utils.pca_incremental(Z_new, PC=PC)
            print Z_new_pca.shape
            assert W_new.shape[0] == Z_new_pca.shape[0]
            X_PCA = np.concatenate((W_new, Z_new_pca), axis=1)
            data_X_PCA[demonstration] = X_PCA

        if config[1]:
            Z_new_cca = utils.cca(W_new, Z_new)
            print Z_new_cca.shape
            assert W_new.shape[0] == Z_new_cca.shape[0]
            X_CCA = np.concatenate((W_new, Z_new_cca), axis=1)
            data_X_CCA[demonstration] = X_CCA

        if config[2]:
            Z_new_grp = utils.grp(Z_new)
            print Z_new_grp.shape
            assert W_new.shape[0] == Z_new_grp.shape[0]
            X_GRP = np.concatenate((W_new, Z_new_grp), axis=1)
            data_X_GRP[demonstration] = X_GRP

    if config[0]:
        pickle.dump(data_X_PCA,
                    open(PATH_TO_FEATURES + fname + "_PCA" + ".p", "wb"))
    if config[1]:
        pickle.dump(data_X_CCA,
                    open(PATH_TO_FEATURES + fname + "_CCA" + ".p", "wb"))
    if config[2]:
        pickle.dump(data_X_GRP,
                    open(PATH_TO_FEATURES + fname + "_GRP" + ".p", "wb"))
Exemplo n.º 13
0
Arquivo: C2B5.py Projeto: linor/c2-b5
        checksum = checksum ^ c
        i2cbus.write_byte(address, c)
        time.sleep(0.0005)

    i2cbus.write_byte(address, checksum)
    time.sleep(0.0005)


if __name__ == '__main__':
    driveJoystick = None
    lastDriveJoystickMovement = 0
    lastDriveCommand = 0
    domeJoystick = None
    lastDomeJoystickMovement = 0
    lastJoystickInit = time.time()
    lcdScreen = lcd.LCD()
    lcdScreen.init()
    lastDomeDirection = 0
    lastDomeSpeed = 0
    lastDomeUpdate = 0

    genericAudioFiles = findFiles('/home/pi/audio/generic/')
    chatAudioFiles = findFiles('/home/pi/audio/chat/')
    happyAudioFiles = findFiles('/home/pi/audio/happy/')
    sadAudioFiles = findFiles('/home/pi/audio/sad/')
    whistleAudioFiles = findFiles('/home/pi/audio/whistle/')
    screamAudioFiles = findFiles('/home/pi/audio/scream/')

    domeAudioFiles = list(genericAudioFiles)
    domeAudioPending = []
    driveAudioFiles = list(genericAudioFiles)
Exemplo n.º 14
0
sensor.set_contrast(1)
sensor.set_brightness(0)
sensor.set_saturation(2)
sensor.set_pixformat(sensor.RGB565)

# Note: QQVGA2 is the LCD resolution.
sensor.set_framesize(sensor.QQVGA2)

# The following registers fine-tune the image
# sensor window to align it with the FIR sensor.
sensor.__write_reg(0xFF, 0x01)  # switch to reg bank
sensor.__write_reg(0x17, 0x1D)  # set HSTART
sensor.__write_reg(0x18, 0x47)  # set HSTOP

# Initialize LCD
lcd = lcd.LCD()
#lcd.clear(0x00)
lcd.set_backlight(True)

# FPS clock
clock = time.clock()

# Ambient temperature
ta = 0.0
# Minimum object temperature
to_min = 0.0
# Maximum object temperature
to_max = 0.0

while (True):
    clock.tick()
Exemplo n.º 15
0
            if key == '#':
                offset += 2
            elif key == '*' and offset > 0:
                offset -= 2
            else:
                return key

    def input_number(self, value, update_function):
        while True:
            update_function(value)
            k = self._keypad.get_single_key()
            if k == '#':
                break
            if k == '*':
                value = value / 10
            else:
                value *= 10
                value += k

        return value

import max7301
if __name__ == "__main__":
    import lcd
    lcd = lcd.LCD('localhost')
    io_device = max7301.MAX7301()
    ui = UI(io_device = io_device, lcd = lcd)
    print ui.choose('krobin moechte', ['pizza', 'doener'])

Exemplo n.º 16
0
    def __init__(self):
        self.ticks = 0
        self.lcd_itr = 0
        self.data = {}

        self.window = Gtk.Window(title='TDR')
        self.window.connect('destroy', Gtk.main_quit)
        self.window.set_resizable(False)
        self.window.set_size_request(800, 600)
        self.window.set_position(Gtk.WindowPosition.CENTER)

        self.container = Gtk.Fixed()
        self.window.add(self.container)

        self.bluetooth_label = Gtk.Label(label='Bluetooth: disconnected')
        self.container.put(self.bluetooth_label, 50, 50)

        self.data_label = Gtk.Label(label='Current data:')
        self.container.put(self.data_label, 50, 150)

        self.label = Gtk.Label()
        self.container.put(self.label, 100, 210)

        self.arduino_label = Gtk.Label()
        self.container.put(self.arduino_label, 500, 210)

        self.lcd_label = Gtk.Label()
        self.container.put(self.lcd_label, 500, 270)

        self.clear_reg_button = Gtk.Button(label='Clear register')
        self.clear_reg_button.connect('clicked',
                                      Application.clear_reg_button_clicked)
        self.container.put(self.clear_reg_button, 100, 500)

        self.graph_label = Gtk.Label(label='Graph settings:')
        self.container.put(self.graph_label, 400, 360)

        self.graph_win = Gtk.CheckButton(label='Display graphs')
        self.graph_win.connect('toggled', Application.checkbox_toggle)
        self.container.put(self.graph_win, 420, 390)

        self.sizex_entry = Gtk.Entry()
        self.sizex_entry.connect('changed', self.on_size_changed)
        self.container.put(self.sizex_entry, 420, 440)

        self.sizey_entry = Gtk.Entry()
        self.sizey_entry.connect('changed', self.on_size_changed)
        self.container.put(self.sizey_entry, 420, 480)

        self.graphparams_entry = Gtk.Entry()
        self.graphparams_entry.connect('changed', self.on_params_changed)
        self.container.put(self.graphparams_entry, 420, 520)

        self.sizex_entry.set_text(str(grapher.sizex))
        self.sizey_entry.set_text(str(grapher.sizey))
        self.graphparams_entry.set_text(grapher.graph_params)

        self.container.put(Gtk.Label(label='X size for graphics (inches)'),
                           600, 440)
        self.container.put(Gtk.Label(label='Y size for grahics (inches)'), 600,
                           480)
        self.container.put(Gtk.Label(label='Parameters for the graph'), 600,
                           520)

        self.window.show_all()

        self.datareader1 = dataread.DataRead('/dev/ttyACM0')
        self.datareader2 = dataread.DataRead('/dev/ttyACM1')
        self.bluetoothdv = bluetoothio.BluetoothIO()

        self.lcd1 = lcd.LCD(0x3f)
        self.lcd2 = lcd.LCD(0x20)

        self.update_arduino_label()
        self.update_lcd_label()

        self.graphprocess = Process(target=grapher.update_graph, args=[''])

        if not os.path.exists('register.json'):
            with open('register.json', 'w') as file:
                file.write('[\n]')
Exemplo n.º 17
0
        lcd.gotoxy(0,3)
        lcd.pr(padN('{:20}'.format(wstr),lcd_width,True))

        
if __name__ == '__main__':

    s = 'This is a very long string that must be rotated'
    r = RotatingString(s,16)
    for i in range(50):
        print(r.tick())

    if False:
        import bb595
        import lcd
        import random
        s8 = bb595.bb595()
        lcd = lcd.LCD(s8)
        lcd.begin()
        lcd.clear()
        lcd.backlight(0)
        last = datetime.datetime.now()

        while True:
            now = datetime.datetime.now()
            if now > (last + datetime.timedelta(seconds=1)):
                update_display(lcd,{'zones':'3', 'remaining':4922},None)
                last = now
            else:
                s8.shift8(random.randrange(256),'triacs')
  
Exemplo n.º 18
0
    def __init__(self):
        # read config
        try:
            configfile = '/proc/device-tree/hat/custom_0'
            f = open(configfile)
            self.hatconfig = json.loads(f.read())

            f.close()
        except Exception as e:
            print('failed to load', configfile, ':', e)
            print('assuming original 26 pin tinypilot')
            self.hatconfig = False

        self.config = {
            'remote': False,
            'host': 'pypilot',
            'actions': {},
            'lcd': {}
        }
        self.configfilename = os.getenv('HOME') + '/.pypilot/hat.conf'
        print('loading config file:', self.configfilename)
        try:
            file = open(self.configfilename)
            config = json.loads(file.read())
            file.close()
            for name in config:
                self.config[name] = config[name]
        except Exception as e:
            print('config failed:', e)

        self.lastpollheading = time.time()
        self.servo_timeout = time.time() + 1

        self.longsleep = 30
        self.last_msg = {}

        self.client = False
        self.lcd = lcd.LCD(self)
        self.gpio = gpio.gpio()
        self.arduino = arduino.arduino(self.hatconfig)
        self.lirc = lirc.lirc()
        self.buzzer = buzzer.buzzer(self.hatconfig)

        # keypad for lcd interface
        self.actions = []
        keypadnames = ['auto', 'menu', 'up', 'down', 'select', 'left', 'right']

        for i in range(7):
            self.actions.append(ActionKeypad(self.lcd, i, keypadnames[i]))

        # stateless actions for autopilot control
        self.actions += [
            ActionEngage(self),
            ActionPypilot(self, 'disengage', 'ap.enabled', False),
            ActionHeading(self, 1),
            ActionHeading(self, -1),
            ActionHeading(self, 2),
            ActionHeading(self, -2),
            ActionHeading(self, 10),
            ActionHeading(self, -10),
            ActionPypilot(self, 'compassmode', 'ap.mode', 'compass'),
            ActionPypilot(self, 'gpsmode', 'ap.mode', 'gps'),
            ActionPypilot(self, 'windmode', 'ap.mode', 'wind'),
            ActionTack(self, 'tackport', 'port'),
            ActionTack(self, 'tackstarboard', 'starboard')
        ]

        for action in self.actions:
            if action.name in self.config['actions']:
                action.keys = self.config['actions'][action.name]

        self.web = Web(self)