Esempio n. 1
0
    async def init(self, timeout=5000):
        # Performs the ECU wakeup and initialize procedure if required (not ready).
        # ready state is True if it was finished successfully and false it failed (= timeout).
        # Also setup K-line by pulling it low before (what uart.sendbreak() normally does).

        tmr = tms()
        while True:
            self.connecting = True

            # K-line pulldown: only has to be done whenever the ECU was turned off
            tx = Pin(_TX_PIN, Pin.OUT)  # => pulls RX LOW (only when ECU connection achieved for first time)
            tx(0)
            sleep_ms(70)  # no intr here
            tx(1)
            del tx
            await d(130)

            self._uart.init(10400, timeout=self._uart_to, bits=8, parity=None, stop=1)
            self._wTmr = tms()

            try:
                await self.query((0xFE,), 0xFF)  # no resp excepted. alt: use 0x72 instead of 0xFF for response rType=0E
                await d(200)  # default delay might not be enough, just to be safe on startup
                await self.diag_query(0x00, 0xF0)  # return packet (02 04 00 FA) is validated, Exception otherwise
                self.ready = True  # this point is only reached when no error occurs
                return
            except ECUError:
                if tdiff(self._wTmr, tmr) > timeout:
                    return
                await d(500)  # relax
            finally:
                self.connecting = False
Esempio n. 2
0
    async def timer(self):
        io.oled.img("timer", voff=-10)

        self._area_text("Slow down\nto 0 km/h", voff=38, lspace=1.2)
        while ecu.speed > 0:
            await d(500)

        self._area_text("Buffering...", voff=38)
        await d(200)  # make sure gc collected
        cbuf = io.oled.prefetch_chrs("0123456789.", 50)  # for faster oled update

        try:
            io.led_g(1)
            self._area_text("Let's go!", voff=38)
            while ecu.speed <= 0:
                await d(0)
        finally:  # also if cancelled
            io.led_g(0)

        tmr = tms()
        cdiff = -1
        io.oled.fill(0)
        while ecu.speed < 100:
            diff = round(tdiff(tms(), tmr) / 1000, 1)
            if diff >= 10:
                diff = int(diff)
            if diff != cdiff:
                cdiff = diff
                self._area_big(diff, buf=cbuf)
            await d(0)  # todo scheduling required for speed update, but may be too slow for blitting every 0.1 s

        self.view = -5
        await blink(io.led_g, 180, 150, reps=3)
        await blink(io.buzz, 800)  # todo: test if you can hear it @ 100km/h
Esempio n. 3
0
    async def _uread(self, n=None):
        # Read and return <n> bytes (blocking) from UART. Exception on timeout.
        # Read all available (meaning non-blocking) bytes if <n> is None.

        r = b''
        if n is None:
            if self._uart.any():
                # todo use StreamReader.read()?
                r = self._uart.read()  # reads all
        else:
            # problem: StreamWriter is blocking (does not support timeouts neither in read nor in readexactly)
            #          therefore we are reading byte by byte (uart.any() returns only 1 or 0, not the amount!)
            while n > 0:
                # if n % 5 == 0: await d(0) # allow interrupts in large data bundles
                tmr = tms()
                while not self._uart.any():
                    if tdiff(tms(), tmr) > self._uart_to:
                        # todo use fir again?
                        # if self._fir >= 9:  # this must be the nth fail -> now reconnect required
                        self.ready = False
                        raise ECUError(0)  # UART timeout
                        # else:
                        #     self._fir += 1
                    await d(0)
                r += self._uart.read(1)
                n -= 1

        # if self._fir > 0:
        #     self._fir -= 1
        return r
Esempio n. 4
0
    async def _uwrite(self, msg):
        # Writes the bytes <msg> to the UART.
        # Waits for some ms, ensuring a minimum delay between two msgs (prevents UART timeout).

        diff = tdiff(tms(), self._wTmr)
        if diff < HondaECU._TX_DELAY:
            await d(HondaECU._TX_DELAY - diff)
        self._uart.write(msg)  # no StreamWriter, as it would cause too much scheduling
        self._wTmr = tms()
Esempio n. 5
0
def main():
    if machine.reset_cause() == machine.HARD_RESET:
        ctrl.off()
    elif machine.reset_cause() == machine.SOFT_RESET:  # this must be a webapp reset, so start it again
        start_net()
    else:
        tmr = tms()
        while ctrl.switch_pressed():  # wait for switch to be released. NC = remains on until timeout
            if tdiff(tms(), tmr) > _SW_PWRUP_TIMEOUT:  # break light flash switch NC or hold down long for special fun
                start_net()
                break
        else:  # not pressed long enough
            if not ctrl.powered():  # bike not powered on startup; was motion wakeup
                ctrl.off()  # nothing should be on, but ok...
                deepsleep()

    while True:
        if ctrl.powered():  # bike (and maybe network) running
            loop.create_task(task_ecu())
            loop.create_task(task_ctrl())
            loop.run_until_complete(await_pwroff())  # wait for poweroff (bike shutdown)

            # -> bike powered off

            # only required if net started afterwards, so no wrong data is displayed:
            reset_loop()  # clear ecu and ctrl task as these are not required now
            ctrl.clear()
            ecu.reset()

            if ctrl.switch_pressed():  # switch held down during shutdown
                start_net(ctrl.mode * 60 if ctrl.mode > 0 else _NET_DEFAULT_ACTIVE_TIME)  # will only set tmr if alr active
            elif ctrl.mode == 10:
                ctrl.off()
                return  # to console
            else:
                if not net.stay_on():
                    ctrl.off()
                    net.stop()  # stop running network (explicitly kick clients), we want to deepsleep
                    deepsleep()
                else:  # stay_on time not over -> reschedule task
                    loop.create_task(task_net())

        # -> only network running, should stay on (and check for powerup meanwhile)
        loop.run_until_complete(await_pwron())
Esempio n. 6
0
def run():
    if machine.reset_cause() == machine.HARD_RESET:
        io.off()
        show_logo()
    elif machine.reset_cause() == machine.SOFT_RESET:  # this must be a webapp reset, so start it again
        start_net()
        show_logo()
    else:
        tmr = tms()
        while io.switch_pressed():  # wait for switch to be released. NC = remains on until timeout
            if tdiff(tms(), tmr) > _SW_PWRUP_TIMEOUT:  # brakelight flash switch NC or hold down long for special fun
                start_net()
                break
        else:  # BLF switch not pressed (or long enough)
            if not io.powered():  # bike not powered on startup; was motion wakeup
                io.off()  # nothing should be on, but ok...
                deepsleep()
            else:
                show_logo()

    while True:
        if io.powered():  # bike (and maybe network) running
            loop.create_task(task_ctrl.run())  # first start display
            loop.create_task(task_ecu())
            loop.run_until_complete(await_pwroff())  # wait for poweroff (bike shutdown)

            # -> bike powered off

            # only required if net started afterwards, so no wrong data is displayed:
            reset_loop()  # clear ecu and ctrl task as these are not required now
            io.clear()
            ecu.reset()

            if io.switch_pressed():  # switch held down during shutdown
                start_net()
            elif not net.stay_on():
                io.off()
                net.stop()  # stop running network (explicitly kick clients), we want to deepsleep
                deepsleep()
            else:  # stay_on time not over -> reschedule task
                loop.create_task(task_net())

        # -> only network running, should stay on (and check for powerup meanwhile)
        loop.run_until_complete(await_pwron())
Esempio n. 7
0
    def __init__(self):
        super().__init__()

        # assuming module references don't change over time, so once e.g. ecu is defined, only its contents will
        # change. data is stored in format {obj1: {...}, obj2: {...}, ...}
        self.obj = {o: locals()[o] for o in _OBJS}  # e.g. obj['ecu'] = <ECU object at 3abf00c1>
        self.data = {o: {} for o in _OBJS}
        # initial update cannot be done here (write only allowed after setup()) -> _update

        self.conn_tmr = tms()  # for checking if client is connected
Esempio n. 8
0
 def start(self, stay_on=0):
     # with stay_on you can optionally specify a time (minutes), how long the network
     # is expected to stay on after start even if bike is powered off (0 = shutdown network on poweroff)
     global _stay_on_for, _stay_on_tmr
     _stay_on_for = stay_on * 60000  # minutes to ms
     _stay_on_tmr = tms()
     if not self.active:
         self.active = True
         self._set_ap()
         self._set_sta()
         super().start(self._port)
Esempio n. 9
0
    def __init__(self, uart, uart_timeout=800):
        # note that <uart_timeout> is the timeout for reading a single byte from UART, meaning that reading e. g.
        # 10 bytes could take up to 10*<uart_timeout>. timeout exceed cause an Error and set ECU to not ready state

        self._uart = uart
        self._uart_to = uart_timeout
        # self.sreader = asyncio.StreamReader(uart)
        self._wTmr = tms()  # to make sure there is a delay between two msgs being sent over UART

        self.ready = False  # set to False whenever the ECU has to be woken up using init-method
        # self._fir = 0  # fails in a row counter. will be increased and set back to zero if read was successful
        self.connecting = False  # set to True while the ECU is trying to connect to K-Line
Esempio n. 10
0
    def routine(self):  # main routine, executed all the time the client is active
        self.obj['io'].oled.println("handle client")

        if tdiff(tms(), self.conn_tmr) > _WS_INACT_TO*1000:
            self.close()
            self.obj['io'].oled.println("closed client")
            return

        msg = self.read()
        if msg:  # client is asking for sth (not empty or None)
            msg = msg.decode('utf-8')
            try:
                for m in json.loads('[' + msg.replace("}{", "},{") + ']'):  # can be multiple, therefore this shit...
                    self.obj['io'].oled.println(repr(m))
                    self.execute(m)
            except ValueError:  # invalid JSON
                pass

        self._update()  # update data locally and submit changes to the client
Esempio n. 11
0
def task_view_menu():  # todo add async
    io.oled.fill(0)
    io.oled.text("MENU", y=14, hspace=3)

    VSPACING = 13
    idx_sel = -1

    def blit_opt(txt, **kw):
        nonlocal idx_sel
        idx_sel += 1
        io.oled.text(txt, y=30 + idx_sel * VSPACING, **kw)

    blit_opt("Brakeflash")
    blit_opt("Turn LED " + ("on" if True else "off"))  # todo read relay state
    blit_opt("Turn WiFi " +
             ("on" if False else "off"))  # todo read relay state
    blit_opt("Timer 0-100")
    blit_opt("Silent Warn")
    blit_opt("Horn Warn")
    blit_opt("Close")

    IDX_SEL_MAX = idx_sel

    # idx in range of possible selections (0-max), show = 0 or 1
    def sel_draw(idx, show):
        io.oled.rect(-1, 28 + idx * VSPACING, io.oled.w + 2, 12, show)

    def sel_move():
        nonlocal idx_sel
        sel_draw(idx_sel, 0)
        idx_sel += 1
        if idx_sel > IDX_SEL_MAX:
            idx_sel = 0
        sel_draw(idx_sel, 1)
        io.oled.show()

    sel_draw(IDX_SEL_MAX, 1)  # initial selection: back
    io.oled.show()

    # todo: loop for checking if button pressed short (move) or long (-> break loop)
    # todo: meanwhile check: reblit menu if wifi/led state changes (over network)
    # todo: also break loop if no action for 12 sec
    for i in range(4):
        sleep_ms(400)
        sel_move()

    io.oled.fill(0)
    if idx_sel == 0:
        io.oled.img("brake")
        io.oled.show()
        # todo flash until key pressed
    elif idx_sel in (4, 5):
        for i in range(20):  # todo async endless
            io.oled.img("warn")
            io.oled.show()
            sleep_ms(150)
            io.oled.fill(0)
            io.oled.show()
            sleep_ms(100)
    elif idx_sel == 3:
        io.oled.img("timer", voff=-10)
        if True:  # todo: kmh is > 0
            io.oled.text("Slow down", y=io.oled.h - 35)
            io.oled.text("to 0 km/h", y=io.oled.h - 26)
            io.oled.show()

            while False:  # todo: kmh > 0 and not pressed button
                pass
            sleep_ms(1000)  # todo

        io.oled.fill_rect(0, io.oled.h - 35, io.oled.w, 35, 0)
        io.oled.text("Prefetching...", y=io.oled.h - 31)
        io.oled.show()
        cbuf = io.oled.prefetch_chrs("0123456789.",
                                     50)  # for faster oled update

        io.oled.fill_rect(0, io.oled.h - 35, io.oled.w, 35, 0)
        io.oled.text("Get going!", y=io.oled.h - 31)
        io.oled.show()

        while False:  # todo: kmh <= 0 and not pressed button
            pass
        sleep_ms(1000)  # todo

        tmr = tms()
        area = (0, 0, io.oled.w, io.oled.h)
        cdiff = -1
        while True:  # todo: km/h < 100
            # todo exit on click
            diff = round(tdiff(tms(), tmr) / 1000, 1)
            if diff >= 10:
                diff = int(diff)
            if diff != cdiff:
                cdiff = diff
                io.oled.fill_rect(*(area + (0, )))  # clear previous area
                io.oled.big(diff, buf=cbuf)
                io.oled.show()
Esempio n. 12
0
async def task_ctrl():  # mode based on switch (e.g. break light flash)
    ctrl.sw_pressed = False
    sw_tmr = tms()  # timer to check duration of switch down
    lap_tmr = tms()  # timer for special mode 0-100 km/h measurement (reset at 0 km/h)

    while True:
        # check switch (BLF and special modes):
        if ctrl.sw_pressed != ctrl.switch_pressed():  # just pressed or released (state is updated after methodcal)
            if ctrl.sw_pressed:  # just pressed:
                sw_tmr = tms()  # set timer to check duration later
                if ctrl.mode != 0:  # switch pressed while in special mode
                    ctrl.mode = -ctrl.mode  # to reset from any special mode to mode 0
                    ctrl.led_g(1)
            else:  # just released -> apply mode now
                if ctrl.mode < 0:
                    if ctrl.mode == -1:  # was mode 1 before
                        ctrl.set_rly('BL', False)
                    ctrl.mode = 0  # reset to mode 0 without break light flashing
                    ctrl.led_g(0)
                elif ctrl.mode == 0:
                    for _ in range(_SW_BL_FLASH_COUNT):
                        ctrl.set_rly('BL', True)
                        sleep_ms(90)
                        ctrl.set_rly('BL', False)
                        sleep_ms(70)
                elif ctrl.mode == 2:
                    lap_tmr = tms()  # this val is only used if this mode is set when driving and then reaching >100
                elif ctrl.mode == 7:  # activate network if not active (no min active time -> until pwrdown)
                    start_net(0)  # already running? just change stayon time to "until poweroff"
                    ctrl.mode = 0  # instant reset
                elif ctrl.mode == 8:  # disable the network iface
                    net.stop()
                    ctrl.mode = 0  # instant reset

                ctrl.seg_clear()
        elif ctrl.sw_pressed and ctrl.mode >= 0:  # held down -> check duration
            if tdiff(tms(), sw_tmr) >= _SW_HOLD_THRESH:  # special mode
                ctrl.mode += 1
                ctrl.seg_digit(ctrl.mode % 10)
                ctrl.led_g(1)
                await d(150)
                ctrl.led_g(0)
                sw_tmr = tms()  # for next special mode
            if ctrl.mode != 0:
                await d(0)  # let ECU work
                continue  # skip io.part, cause increasing special mode is non-interruptable on 7-seg

        # mode-dependent, but ecu independet stuff:
        if ctrl.mode == 1:  # warn mode
            ctrl.set_rly('BL', not ctrl.rly['BL'])
            await d(180)

        # handle cockpit stuff depending on ecu:
        if ecu.ready:  # ECU connected
            if ctrl.mode == 2:  # set timer and green LED based on speed
                if ecu.speed == 0:
                    lap_tmr = tms()
                    ctrl.led_g(1)
                elif ecu.speed >= 100:
                    lap_time = tdiff(tms(), lap_tmr)  # e. g. 15762 ms (= 15.8s)
                    ctrl.led_g(1)
                    lt_s = lap_time // 1000  # seconds (front part) e.g. 15
                    lt_h = round((lap_time - lt_s * 1000) / 100)  # hundreth e.g. 8
                    ctrl.seg_clear()
                    await d(1000)
                    ctrl.seg_show_num(lt_s, lt_h)
                    ctrl.led_g(0)
                    ctrl.mode = 0
                    del lap_tmr  # will be reset when mode is set to 1 again
                elif tdiff(tms(), lap_tmr) > 60000:  # reset mode as it does not seem to be used
                    ctrl.mode = 0
                    await blink(ctrl.led_g)
                else:  # measurement
                    ctrl.led_g(0)

            if not ecu.engine or ecu.rpm <= 0:  # engine not running (probably parking) or engine just starting up
                ctrl.seg_char('-')
            elif ecu.idle or ecu.gear is None:
                if ecu.sidestand or ecu.speed < _REV_CIRCLE_SPEED_THRESH and ecu.tp > 0:  # revving
                    ctrl.seg_circle()
                    await d(int(-28*log(ecu.rpm) + 262))
                else:
                    await ctrl.seg_flash(250)
                continue  # skip second yield
            else:
                # shift light if required:
                ctrl.seg_digit(ecu.gear)
                if ecu.rpm > _SHIFT_LIGHT_RPM_THRESH and ecu.gear < 6:
                    await ctrl.seg_flash(60)
                    continue  # skip second yield

        await d(0)  # let ECU work
Esempio n. 13
0
class IOTasks:
    VIEW_ECU_ATTR = (  # add all ECU attributes (with description + unit) that should be displayed in a view
        ("ect", "Engine\nCoolant", "° Celsius"),
        ("iat", "Intake Air", "° Celsius"),
        ("bat", "Battery", "Volt"),
        ("map", "Manifold\nPressure", "kPa"),
    )

    def __init__(self):
        self._area = None  # used to hold an OLED area to be cleared later (should be reset on each task change)
        self.task = None  # currently running oled view task gen-object (will be killed on view change)
        self.view = 1  # current view state (int), that may map to one task function (see __num_to_task())
        self.stay_on = False  # set to True if the ECU is expected to stay on because of the current view

    def _area_clear(self):
        if self._area is not None:
            io.oled.fill_rect(*(self._area + (0,)))  # clear previous area

    def _area_big(self, t, **kw):  # clears old area and displays the txt with big font
        self._area_clear()
        self._area = io.oled.big(t, **kw)
        io.oled.show()

    def _area_text(self, t, **kw):
        self._area_clear()
        self._area = io.oled.text(t, **kw)
        io.oled.show()

    async def brakeflash(self):
        io.oled.img("brake")
        io.oled.show()

        while True:
            io.set_rly('BL', True)
            sleep_ms(90)  # no intr (not to be canceled here)
            io.set_rly('BL', False)
            await d(70)

    async def timer(self):
        io.oled.img("timer", voff=-10)

        self._area_text("Slow down\nto 0 km/h", voff=38, lspace=1.2)
        while ecu.speed > 0:
            await d(500)

        self._area_text("Buffering...", voff=38)
        await d(200)  # make sure gc collected
        cbuf = io.oled.prefetch_chrs("0123456789.", 50)  # for faster oled update

        try:
            io.led_g(1)
            self._area_text("Let's go!", voff=38)
            while ecu.speed <= 0:
                await d(0)
        finally:  # also if cancelled
            io.led_g(0)

        tmr = tms()
        cdiff = -1
        io.oled.fill(0)
        while ecu.speed < 100:
            diff = round(tdiff(tms(), tmr) / 1000, 1)
            if diff >= 10:
                diff = int(diff)
            if diff != cdiff:
                cdiff = diff
                self._area_big(diff, buf=cbuf)
            await d(0)  # todo scheduling required for speed update, but may be too slow for blitting every 0.1 s

        self.view = -5
        await blink(io.led_g, 180, 150, reps=3)
        await blink(io.buzz, 800)  # todo: test if you can hear it @ 100km/h

    async def warn(self):
        self.stay_on = True
        io.oled.text("Hold switch\nto add horn" if self.view != -4 else "Press to stop", voff=40, lspace=1.2)

        try:
            while True:
                if self.view == -4:
                    io.set_rly('HO', not io.rly['HO'])

                for _ in range(3):  # horn on/off time = x * breaklight on/off time
                    io.set_rly('BL', not io.rly['BL'])

                    if io.rly['BL']:
                        self._area = io.oled.img("warn", voff=-6)
                    else:
                        self._area_clear()
                    io.oled.show()

                    await d(180)
        finally:  # make sure to turn off relay when task gets cancelled
            io.set_rly('BL', False)
            if self.view == -4:
                io.set_rly('HO', False)
            self.stay_on = False

    async def view_gear(self):
        cgear = None  # currently displayed on OLED#

        if not ecu.ready:
            await d(100)  # since view gear is the first task, it will be killed and restarted immediately

        while True:
            if ecu.sidestand:  # parking
                ngear = 'P'
            elif ecu.rpm <= 0 or not ecu.engine:  # engine not running, but no sidestand
                ngear = 'X'
            elif ecu.speed <= _DRIVING_SPEED_THRESH:  # idling while standing
                ngear = '-'
            elif ecu.idle or ecu.gear is None:  # idling while driving = probably shifting
                await blink(io.oled.power, 200, 350, 0)
                continue  # skip second yield and gear-change-check
            else:
                ngear = ecu.gear

            if ngear != cgear:
                self._area_big(ngear)
                cgear = ngear

            await d(0)

    async def view_ecu(self, attr_nr):
        io.oled.text(IOTasks.VIEW_ECU_ATTR[attr_nr][1], voff=-33, lspace=1.2)
        io.oled.text(IOTasks.VIEW_ECU_ATTR[attr_nr][2], y=105)

        cval = None
        while True:
            nval = getattr(ecu, IOTasks.VIEW_ECU_ATTR[attr_nr][0])
            if cval != nval:
                cval = nval
                self._area_big(cval, voff=8)

            await d(100)

    async def _kill_task(self):
        if self.task is not None:
            await d(0)  # the task has to be started, otherwise cancel will block  todo: remove if possible
            cancel(self.task)
            await d(0)  # be sure it gets killed

        io.oled.fill(0)  # prepare oled for next task
        self._area = None  # no area in use

    async def _setup_task(self):  # starts the task that should run given self.view
        await self._kill_task()
        self.task = self.__num_to_task(self.view)
        if self.task is not None:
            loop.create_task(self.task)

    def __num_to_task(self, nr):  # returns view task: simple views (> 0), menu view (= 0), special modes (< 0)
        if nr == 1:
            return self.view_gear()
        elif 0 <= nr-2 < len(IOTasks.VIEW_ECU_ATTR):
            return self.view_ecu(nr-2)
        elif nr == -1:
            return self.brakeflash()
        elif nr == -2:
            return self.timer()
        elif nr == -3 or nr == -4:  # -4 = with horn
            return self.warn()
        # -5 = timer finished (time displayed, do not change) => None
        # 0 = menu -> no view => None
        # else = invalid => None

    def __menu_sel_to_view(self, sel_idx):
        # Maps the index of a menu selection to the corresponding view and returns it. setup_task has to be called.
        # For some menu entries only one action takes place, but the view will return to gear view.
        if sel_idx == 0:  # brakeflash
            return -1
        elif sel_idx == 1:  # timer
            return -2
        elif sel_idx == 2:  # led on/off
            io.set_rly('LED', not io.rly['LED'])
        elif sel_idx == 3:  # wifi on/off
            if not net.active:
                start_net(0)  # until bike shutdown
            else:
                net.stop()
        elif sel_idx == 4:  # warn mode
            return -3

        return 1  # for selection 'Close', no selection (None/-1), and the ones without a specific view (autoreturn)

    async def run(self):  # reacts to switch state changes (eg by mode change), should run all the time
        menu = MenuView()

        if ecu.ready:  # this should not happen, but just in case the ECU is ready before display task starts, show gear
            await self._setup_task()  # initial task

		engine_warm = None  # ECT heated up? if not, blue LED on
		
		while True:
            if not ecu.ready and io.powered():  # wait for ECU to be connected (only if powered, otherwise don't wait)
                await self._kill_task()  # suspend current view task

                while not ecu.ready:
                    while ecu.connecting:
                        await blink(io.led_b, 100, 400)
                    else:
                        await d(300)

                await self._setup_task()  # now bring it up again
				engine_warm = None  # resetting blue LED required

            if (not io.sw_pressed) & io.switch_pressed():  # new BLF switch press; binary and to avoid short-circuiting
                sw_tmr = tms()
                while tdiff(tms(), sw_tmr) < _SW_HOLD_THRESH and io.switch_pressed():  # until released or long press
                    await d(10)

                if io.sw_pressed:  # long press
                    if self.view > 0:
                        self.view = 0  # show menu
                        await self._kill_task()
                        menu.show()
                    elif self.view == 0:  # menu selection
                        self.view = self.__menu_sel_to_view(menu.selected())
                        await self._setup_task()
                    elif self.view == -3:  # silent warn
                        self.view = -4  # horn warn
                        await self._setup_task()  # restart required to load text
                else:  # short press
                    if self.view > 0:
                        self.view += 1  # display next view
                        if self.view > 1+len(IOTasks.VIEW_ECU_ATTR):
                            self.view = 1
                        await self._setup_task()
                    elif self.view == 0:
                        menu.select_next()
                    elif self.view == -5:  # timer finished
                        self.view = -2  # restart timer
                        await self._setup_task()
                    else:  # exit special mode
                        self.view = 1
                        await self._setup_task()

			if engine_warm != (ecu.ect >= _ENGINE_WARM_THRESH):
				engine_warm = (ecu.ect >= _ENGINE_WARM_THRESH)
				io.led_b(int(engine_warm))  # blue LED on if engine not warm yet
			
            await d(0)  # let ECU work
Esempio n. 14
0
 def stay_on(self):  # returns True, if the chip is expected not to shutdown because of stay_on time
     return tdiff(tms(), _stay_on_tmr) < _stay_on_for
Esempio n. 15
0
 def execute(self, msg):  # execute a msg object (must be dict unpacked from json)
     global _stay_on_for, _stay_on_tmr
     try:
         if 'PING' in msg:  # send stay-on-time (secs) as ACK
             self.obj['io'].oled.println("do ACK")
             self.send(ACK=max((_stay_on_for - tdiff(tms(), _stay_on_tmr)) // 1000, 0))
             self.obj['io'].oled.println("acknowledged PING " + str(msg["PING"]))
             self.conn_tmr = tms()  # reset timer
         elif 'SET' in msg and 'TO' in msg:  # client wants to set local variable
             self._set_var(msg['SET'], msg['TO'])
         elif 'CMD' in msg:  # ESP command without args
             cmd = msg['CMD']
             if cmd == "reboot":
                 reset()  # soft reset
             elif cmd == "deepsleep":
                 deepsleep()
             elif cmd == "console":
                 raise Exception("net return")
             elif cmd == "ifconfig":  # returns AP and STA IP and Port; 0.0.0.0 if not connected
                 aw = ""
                 ap = network.WLAN(network.AP_IF)
                 if ap.active():
                     aw += "AP:\n{}\n\n".format(ap.ifconfig())
                 sta = network.WLAN(network.STA_IF)
                 if sta.active():
                     aw += "Station:\n{}\n\n".format(sta.ifconfig())
                 aw += "Port: " + str(read_cfg("port"))
                 self.send(ALERT=aw)
             elif cmd == "netls":
                 self.send(ALERT='\n\n'.join(["ID: %s\nPW: %s" % (kid, kpw) for (kid, kpw) in read_cfg("knets")]))
             elif cmd == "netadd":
                 cfg = read_cfg()
                 knets = cfg["knets"]
                 for i in range(len(knets)):
                     if knets[i][0] == msg['ID']:
                         knets[i][1] = msg['PW']
                         break
                 else:  # not found
                     cfg["knets"].append((msg['ID'], msg['PW']))
                 write_cfg(cfg)
             elif cmd == "netrm":
                 cfg = read_cfg()
                 knets = cfg["knets"]
                 for i in range(len(knets)):
                     if knets[i][0] == msg['ID']:
                         knets.pop(i)
                         break
                 else:
                     return  # not found -> nothing to do
                 write_cfg(cfg)
             elif cmd == "nettime":
                 _stay_on_for = int(msg['VAL']) * 1000  # ms
                 _stay_on_tmr = tms()
             elif cmd == "text":
                 self.obj['io'].oled.clear()
                 self.obj['io'].oled.text(msg["MSG"])
                 self.obj['io'].oled.show()
             elif cmd == "println":
                 self.obj['io'].oled.println(msg["MSG"])
         # elif 'GET' in msg:  # client wants to get local variable(s)
         #     if not msg['GET']:  # empty string or None -> enquiring all cached data
         #         self.send(UPDATE=self.data)
         #     else:
         #         self._get_var(msg['GET'])
     except ValueError:  # not in JSON format
         pass
Esempio n. 16
0
from pwr import deepsleep
from machine import reset
from uasyncio import get_event_loop
import network


_CONFIG_FILE = "netconf.json"  # this file must contain, hostname, password, known networks, port (...)
_OBJS = ('ecu', 'io')  # all non-private vars in these objects will be monitored and sent to clients on update
_WS_INACT_TO = 14  # client is closed when no message (incl PING!) received for _ s (>= WS_SYN_INTERVAL)
_AP_CONF = ('192.168.0.1', '255.255.255.0', '192.168.0.1', '')  # ip, subnet, gateway, dns
_HTML_INDEX = "/html/index.html"  # None = unused
_HTML_404 = "/404.html"  # None = unused

# global because both NetServer and NetClient need access
_stay_on_for = 0  # chip is expected to remain on even if bike powered off for this time
_stay_on_tmr = tms()  # in respect to this timer (set on network start)

loop = get_event_loop()  # current event loop (same as in main())


def read_cfg(key=None):  # key can be specified for a single entry, otherwise returns all data
    try:
        with open(_CONFIG_FILE, 'r') as f:
            dat = json.loads(f.read())
            if key is not None:
                return dat[key]
            return dat
    except KeyError:
        return None