コード例 #1
0
ファイル: asyntest.py プロジェクト: njg001/micropython-async
async def run_ack():
    message = Message()
    ack1 = Message()
    ack2 = Message()
    count = 0
    while True:
        asyncio.create_task(message_wait(message, ack1, 1))
        asyncio.create_task(message_wait(message, ack2, 2))
        message.set(count)
        count += 1
        print('message was set')
        await ack1
        ack1.clear()
        print('Cleared ack1')
        await ack2
        ack2.clear()
        print('Cleared ack2')
        message.clear()
        print('Cleared message')
        await asyncio.sleep(1)
コード例 #2
0
class NEC_IR():
    def __init__(self, pin, callback, extended,
                 *args):  # Optional args for callback
        self._ev_start = Message()
        self._callback = callback
        self._extended = extended
        self._addr = 0
        self.block_time = 80 if extended else 73  # Allow for some tx tolerance (?)
        self._args = args
        self._times = array('i',
                            (0
                             for _ in range(_EDGECOUNT + 1)))  # +1 for overrun
        if platform == 'pyboard':
            ExtInt(pin, ExtInt.IRQ_RISING_FALLING, Pin.PULL_NONE, self._cb_pin)
        else:  # PR5962 ESP8266 hard IRQ's not supported
            pin.irq(handler=self._cb_pin,
                    trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING))
        self._edge = 0
        self._ev_start.clear()
        asyncio.create_task(self._run())

    async def _run(self):
        while True:
            await self._ev_start  # Wait until data collection has started
            # Compensate for asyncio latency
            latency = ticks_diff(ticks_ms(), self._ev_start.value())
            await asyncio.sleep_ms(self.block_time - latency
                                   )  # Data block should have ended
            self._decode()  # decode, clear event, prepare for new rx, call cb

    # Pin interrupt. Save time of each edge for later decode.
    def _cb_pin(self, line):
        t = ticks_us()
        # On overrun ignore pulses until software timer times out
        if self._edge <= _EDGECOUNT:  # Allow 1 extra pulse to record overrun
            if not self._ev_start.is_set():  # First edge received
                self._ev_start.set(ticks_ms())  # asyncio latency compensation
            self._times[self._edge] = t
            self._edge += 1

    def _decode(self):
        overrun = self._edge > _EDGECOUNT
        val = OVERRUN if overrun else BADSTART
        if not overrun:
            width = ticks_diff(self._times[1], self._times[0])
            if width > 4000:  # 9ms leading mark for all valid data
                width = ticks_diff(self._times[2], self._times[1])
                if width > 3000:  # 4.5ms space for normal data
                    if self._edge < _EDGECOUNT:
                        # Haven't received the correct number of edges
                        val = BADBLOCK
                    else:
                        # Time spaces only (marks are always 562.5µs)
                        # Space is 1.6875ms (1) or 562.5µs (0)
                        # Skip last bit which is always 1
                        val = 0
                        for edge in range(3, _EDGECOUNT - 2, 2):
                            val >>= 1
                            if ticks_diff(self._times[edge + 1],
                                          self._times[edge]) > 1120:
                                val |= 0x80000000
                elif width > 1700:  # 2.5ms space for a repeat code. Should have exactly 4 edges.
                    val = REPEAT if self._edge == 4 else BADREP
        addr = 0
        if val >= 0:  # validate. Byte layout of val ~cmd cmd ~addr addr
            addr = val & 0xff
            cmd = (val >> 16) & 0xff
            if addr == ((val >> 8) ^ 0xff) & 0xff:  # 8 bit address OK
                val = cmd if cmd == (val >> 24) ^ 0xff else BADDATA
                self._addr = addr
            else:
                addr |= val & 0xff00  # pass assumed 16 bit address to callback
                if self._extended:
                    val = cmd if cmd == (val >> 24) ^ 0xff else BADDATA
                    self._addr = addr
                else:
                    val = BADADDR
        if val == REPEAT:
            addr = self._addr  # Last valid addresss
        self._edge = 0  # Set up for new data burst and run user callback
        self._ev_start.clear()
        self._callback(val, addr, *self._args)
コード例 #3
0
class AppBase:
    def __init__(self, conn_id, config, hardware, verbose):
        self.verbose = verbose
        self.initial = True
        self._status = False  # Server status
        self.wlock = asyncio.Lock()
        self.rxmsg = Message()  # rx data ready
        self.tim_boot = Delay_ms(func=self.reboot)
        config.insert(0, conn_id)
        config.append('cfg')  # Marker defines a config list
        self.cfg = ''.join((ujson.dumps(config), '\n'))
        i2c, syn, ack, rst = hardware
        self.chan = asi2c_i.Initiator(i2c, syn, ack, rst, verbose, self._go, (), self.reboot)
        self.sreader = asyncio.StreamReader(self.chan)
        self.swriter = asyncio.StreamWriter(self.chan, {})
        self.lqueue = []  # Outstanding lines

    # Runs after sync acquired on 1st or subsequent ESP8266 boots.
    async def _go(self):
        self.verbose and print('Sync acquired, sending config')
        if not self.wlock.locked():  # May have been acquired in .reboot
            await self.wlock.acquire()
        self.verbose and print('Got lock, sending config', self.cfg)
        self.swriter.write(self.cfg)
        await self.swriter.drain()  # 1st message is config
        while self.lqueue:
            self.swriter.write(self.lqueue.pop(0))
            await self.swriter.drain()
        self.wlock.release()
        # At this point ESP8266 can handle the Pyboard interface but may not
        # yet be connected to the server
        if self.initial:
            self.initial = False
            self.start()  # User starts read and write tasks

    # **** API ****
    async def await_msg(self):
        while True:
            line = await self.sreader.readline()
            h, p = chr(line[0]), line[1:]  # Header char, payload
            if h == 'n':  # Normal message
                self.rxmsg.set(p)
            elif h == 'b':
                asyncio.create_task(self.bad_wifi())
            elif h == 's':
                asyncio.create_task(self.bad_server())
            elif h == 'r':
                asyncio.create_task(self.report(ujson.loads(p)))
            elif h == 'k':
                self.tim_boot.trigger(4000)  # hold off reboot (4s)
            elif h in ('u', 'd'):
                up = h == 'u'
                self._status = up
                asyncio.create_task(self.server_ok(up))
            else:
                raise ValueError('Unknown header:', h)

    async def write(self, line, qos=True, wait=True):
        ch = chr(0x30 + ((qos << 1) | wait))  # Encode args
        fstr =  '{}{}' if line.endswith('\n') else '{}{}\n'
        line = fstr.format(ch, line)
        try:
            await asyncio.wait_for(self.wlock.acquire(), 1)
            self.swriter.write(line)
            await self.swriter.drain()
        except asyncio.TimeoutError:  # Lock is set because ESP has crashed
            self.verbose and print('Timeout getting lock: queueing line', line)
            # Send line later. Can avoid message loss, but this
            self.lqueue.append(line)  # isn't a bomb-proof guarantee
        finally:
            if self.wlock.locked():
                self.wlock.release()

    async def readline(self):
        await self.rxmsg
        line = self.rxmsg.value()
        self.rxmsg.clear()
        return line

    # Stopped getting keepalives. ESP8266 crash: prevent user code from writing
    # until reboot sequence complete
    async def reboot(self):
        self.verbose and print('AppBase reboot')
        if self.chan.reset is None:  # No config for reset
            raise OSError('Cannot reset ESP8266.')
        asyncio.create_task(self.chan.reboot())  # Hardware reset board
        self.tim_boot.stop()  # No more reboots
        if not self.wlock.locked():  # Prevent user writes
            await self.wlock.acquire()

    def close(self):
        self.verbose and print('Closing channel.')
        self.chan.close()

    def status(self):  # Server status
        return self._status

    # **** For subclassing ****

    async def bad_wifi(self):
        await asyncio.sleep(0)
        raise OSError('No initial WiFi connection.')

    async def bad_server(self):
        await asyncio.sleep(0)
        raise OSError('No initial server connection.')

    async def report(self, data):
        await asyncio.sleep(0)
        print('Connects {} Count {} Mem free {}'.format(data[0], data[1], data[2]))

    async def server_ok(self, up):
        await asyncio.sleep(0)
        print('Server is {}'.format('up' if up else 'down'))
コード例 #4
0
async def run_message_test():
    message = Message()
    asyncio.create_task(wait_message(message))
    await asyncio.sleep(1)
    message.set('Hello world')
    await asyncio.sleep(1)
コード例 #5
0
async def main(msg, uart, objs):
    global interactive
    board = False
    devices = False
    device = False
    dev = None
    logger = False  # Stops log stream.
    fw = Message()  # Forwards main uart to device.
    while True:
        await msg
        fw.set(msg.value())
        if not board:
            if not devices:
                if not device:
                    if msg.value() == ESC:
                        board = True
                        await board_menu()
                else:  # device
                    if msg.value() == b'0':
                        dev.toggle()
                        await device_menu(dev)
                    elif msg.value() == b'1':
                        fw.clear()  # Clears last byte.
                        asyncio.create_task(pass_through(dev, uart, fw))
                        #await device_menu(dev)
                    elif msg.value() == b'2':
                        pass
                    elif msg.value() == b'3':
                        await get_config(dev)
                        await device_menu(dev)
                    elif msg.value() in BACKSPACE:
                        device = False
                        devices = True
                        await devices_menu(objs)
                    elif msg.value() == ESC:
                        await device_menu(dev)
            else:  # devices
                if msg.value() == ESC:
                    await devices_menu(objs)
                elif msg.value() in BACKSPACE:
                    devices = False
                    board = True
                    await board_menu()
                else:
                    devices = False
                    device = True
                    try:
                        dev = objs[int(msg.value())]
                        await device_menu(dev)
                    except:
                        await devices_menu(objs)
        else:  # board
            if msg.value() == ESC:
                board = True
                await board_menu()
            elif msg.value() == b'0':
                board = False
                devices = True
                await devices_menu(objs)
            elif msg.value() == b'1':
                await data_files()
                await board_menu()
            elif msg.value() == b'2':
                await last_log()
                await board_menu()
            elif msg.value() in BACKSPACE:
                interactive = False
                logger = True
                msg.clear()
                return
        msg.clear()
        await asyncio.sleep(0)