コード例 #1
0
async def _connect(connection, timeout_ms):
    device = connection.device
    if device in _connecting:
        return

    # Enable BLE and cancel in-progress scans.
    ensure_active()
    await _cancel_pending()

    # Allow the connected IRQ to find the device by address.
    _connecting.add(device)

    # Event will be set in the connected IRQ, and then later
    # re-used to notify disconnection.
    connection._event = connection._event or asyncio.ThreadSafeFlag()

    try:
        with DeviceTimeout(None, timeout_ms):
            ble.gap_connect(device.addr_type, device.addr)

            # Wait for the connected IRQ.
            await connection._event.wait()
            assert connection._conn_handle is not None

            # Register connection handle -> device.
            DeviceConnection._connected[connection._conn_handle] = connection
    finally:
        # After timeout, don't hold a reference and ignore future events.
        _connecting.remove(device)
コード例 #2
0
ファイル: encoder.py プロジェクト: Wind-stormger/Micropython
 def __init__(self,
              pin_x,
              pin_y,
              v=0,
              vmin=None,
              vmax=None,
              div=1,
              callback=lambda a, b: None,
              args=()):
     self._pin_x = pin_x
     self._pin_y = pin_y
     self._v = 0  # Hardware value always starts at 0
     self._cv = v  # Current (divided) value
     if ((vmin is not None) and v < min) or ((vmax is not None)
                                             and v > vmax):
         raise ValueError('Incompatible args: must have vmin <= v <= vmax')
     self._tsf = asyncio.ThreadSafeFlag()
     trig = Pin.IRQ_RISING | Pin.IRQ_FALLING
     try:
         xirq = pin_x.irq(trigger=trig, handler=self._x_cb, hard=True)
         yirq = pin_y.irq(trigger=trig, handler=self._y_cb, hard=True)
     except TypeError:  # hard arg is unsupported on some hosts
         xirq = pin_x.irq(trigger=trig, handler=self._x_cb)
         yirq = pin_y.irq(trigger=trig, handler=self._y_cb)
     asyncio.create_task(self._run(vmin, vmax, div, callback, args))
コード例 #3
0
async def main():
    flag = asyncio.ThreadSafeFlag()

    # Set the flag from within the loop.
    t = asyncio.create_task(task(1, flag))
    print("yield")
    await asyncio.sleep(0)
    print("set event")
    flag.set()
    print("yield")
    await asyncio.sleep(0)
    print("wait task")
    await t

    # Set the flag from scheduler context.
    print("----")
    t = asyncio.create_task(task(2, flag))
    print("yield")
    await asyncio.sleep(0)
    print("set event")
    micropython.schedule(set_from_schedule, flag)
    print("yield")
    await asyncio.sleep(0)
    print("wait task")
    await t

    # Flag already set.
    print("----")
    print("set event")
    flag.set()
    t = asyncio.create_task(task(3, flag))
    print("yield")
    await asyncio.sleep(0)
    print("wait task")
    await t
コード例 #4
0
    def __init__(self, connection):
        if not connection.is_connected():
            raise ValueError("Not connected")

        if connection._l2cap_channel:
            raise ValueError("Already has channel")
        connection._l2cap_channel = self

        self._connection = connection

        # Maximum size that the other side can send to us.
        self.our_mtu = 0
        # Maximum size that we can send.
        self.peer_mtu = 0

        # Set back to None on disconnection.
        self._cid = None
        # Set during disconnection.
        self._status = 0

        # If true, must wait for _IRQ_L2CAP_SEND_READY IRQ before sending.
        self._stalled = False

        # Has received a _IRQ_L2CAP_RECV since the buffer was last emptied.
        self._data_ready = False

        self._event = asyncio.ThreadSafeFlag()
コード例 #5
0
    def __init__(
        self,
        service,
        uuid,
        read=False,
        write=False,
        write_no_response=False,
        notify=False,
        indicate=False,
        initial=None,
        capture=False,
    ):
        service.characteristics.append(self)
        self.descriptors = []

        flags = 0
        if read:
            flags |= _FLAG_READ
        if write or write_no_response:
            flags |= (_FLAG_WRITE if write else 0) | (
                _FLAG_WRITE_NO_RESPONSE if write_no_response else 0)
            if capture:
                # Capture means that we keep track of all writes, and capture
                # their values (and connection) in a queue. Otherwise we just
                # track the most recent connection.
                flags |= _FLAG_WRITE_CAPTURE
            self._write_event = asyncio.ThreadSafeFlag()
            self._write_queue = deque(
                (), _WRITE_CAPTURE_QUEUE_LIMIT if capture else 1)
        if notify:
            flags |= _FLAG_NOTIFY
        if indicate:
            flags |= _FLAG_INDICATE
            # TODO: This should probably be a dict of connection to (ev, status).
            # Right now we just support a single indication at a time.
            self._indicate_connection = None
            self._indicate_event = asyncio.ThreadSafeFlag()
            self._indicate_status = None

        self.uuid = uuid
        self.flags = flags
        self._value_handle = None
        self._initial = initial
コード例 #6
0
    async def exchange_mtu(self, mtu=None):
        if not self.is_connected():
            raise ValueError("Not connected")

        if mtu:
            ble.config(mtu=mtu)

        self._mtu_event = self._mtu_event or asyncio.ThreadSafeFlag()
        ble.gattc_exchange_mtu(self._conn_handle)
        await self._mtu_event.wait()
        return self.mtu
コード例 #7
0
 def __init__(self, func=None, args=(), duration=1000):
     self._func = func
     self._args = args
     self._durn = duration  # Default duration
     self._retn = None  # Return value of launched callable
     self._tend = None  # Stop time (absolute ms).
     self._busy = False
     self._trig = asyncio.ThreadSafeFlag()
     self._tout = asyncio.Event()  # Timeout event
     self.wait = self._tout.wait  # Allow: await wait_ms.wait()
     self._ttask = self._fake  # Timer task
     asyncio.create_task(self._run())
コード例 #8
0
ファイル: security.py プロジェクト: Josverl/micropython-stubs
async def pair(
    connection,
    bond=True,
    le_secure=True,
    mitm=False,
    io=_IO_CAPABILITY_NO_INPUT_OUTPUT,
    timeout_ms=20000,
):
    ble.config(bond=bond, le_secure=le_secure, mitm=mitm, io=io)

    with connection.timeout(timeout_ms):
        connection._pair_event = asyncio.ThreadSafeFlag()
        ble.gap_pair(connection._conn_handle)
        await connection._pair_event.wait()
コード例 #9
0
    def __init__(self, service, def_handle, value_handle, properties, uuid):
        self.service = service
        self.connection = service.connection

        # Used for read/write/notify ops.
        self._def_handle = def_handle
        self._value_handle = value_handle

        # Which operations are supported.
        self.properties = properties

        # Allows comparison to a known uuid.
        self.uuid = uuid

        if properties & _FLAG_READ:
            # Fired for each read result and read done IRQ.
            self._read_event = None
            self._read_data = None
            # Used to indicate that the read is complete.
            self._read_status = None

        if (properties & _FLAG_WRITE) or (properties
                                          & _FLAG_WRITE_NO_RESPONSE):
            # Fired for the write done IRQ.
            self._write_event = None
            # Used to indicate that the write is complete.
            self._write_status = None

        if properties & _FLAG_NOTIFY:
            # Fired when a notification arrives.
            self._notify_event = asyncio.ThreadSafeFlag()
            # Data for the most recent notification.
            self._notify_queue = deque((), 1)
        if properties & _FLAG_INDICATE:
            # Same for indications.
            self._indicate_event = asyncio.ThreadSafeFlag()
            self._indicate_queue = deque((), 1)
コード例 #10
0
    def __init__(self, characteristic, uuid, read=False, write=False, initial=None):
        characteristic.descriptors.append(self)

        # Workaround for https://github.com/micropython/micropython/issues/6864
        flags = 0
        if read:
            flags |= _FLAG_DESC_READ
        if write:
            self._write_connection = None
            self._write_event = asyncio.ThreadSafeFlag()
            flags |= _FLAG_DESC_WRITE

        self.uuid = uuid
        self.flags = flags
        self._value_handle = None
        self._initial = initial
コード例 #11
0
    async def read(self, timeout_ms=1000):
        self._check(_FLAG_READ)
        # Make sure this conn_handle/value_handle is known.
        self._register_with_connection()
        # This will be set by the done IRQ.
        self._read_status = None
        # This will be set by the result and done IRQs. Re-use if possible.
        self._read_event = self._read_event or asyncio.ThreadSafeFlag()

        # Issue the read.
        ble.gattc_read(self._connection()._conn_handle, self._value_handle)

        with self._connection().timeout(timeout_ms):
            # The event will be set for each read result, then a final time for done.
            while self._read_status is None:
                await self._read_event.wait()
            if self._read_status != 0:
                raise GattError(self._read_status)
            return self._read_data
コード例 #12
0
    def __init__(self,
                 duration_ms,
                 interval_us=None,
                 window_us=None,
                 active=False):
        self._queue = []
        self._event = asyncio.ThreadSafeFlag()
        self._done = False

        # Keep track of what we've already seen.
        self._results = set()

        # Ideally we'd start the scan here and avoid having to save these
        # values, but we need to stop any previous scan first via awaiting
        # _cancel_pending(), but __init__ isn't async.
        self._duration_ms = duration_ms
        self._interval_us = interval_us or 1280000
        self._window_us = window_us or 11250
        self._active = active
コード例 #13
0
    async def write(self, data, response=False, timeout_ms=1000):
        self._check(_FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE)

        # If we only support write-with-response, then force sensible default.
        if response is None and (self.properties & _FLAGS_WRITE) and not (self.properties & _FLAG_WRITE_NO_RESPONSE):
            response = True

        if response:
            # Same as read.
            self._register_with_connection()
            self._write_status = None
            self._write_event = self._write_event or asyncio.ThreadSafeFlag()

        # Issue the write.
        ble.gattc_write(self._connection()._conn_handle, self._value_handle, data, response)

        if response:
            with self._connection().timeout(timeout_ms):
                # The event will be set for the write done IRQ.
                await self._write_event.wait()
                if self._write_status != 0:
                    raise GattError(self._write_status)
コード例 #14
0
    def __init__(self, connection, disc_type, parent, timeout_ms, *args):
        self._connection = connection

        # Each result IRQ will append to this.
        self._queue = []
        # This will be set by the done IRQ.
        self._status = None

        # Tell the generator to process new events.
        self._event = asyncio.ThreadSafeFlag()

        # Must implement the _start_discovery static method. Instances of this
        # type are returned by __anext__.
        self._disc_type = disc_type

        # This will be the connection for a service discovery, and the service for a characteristic discovery.
        self._parent = parent

        # Timeout for the discovery process.
        # TODO: Not implemented.
        self._timeout_ms = timeout_ms

        # Additional arguments to pass to the _start_discovery method on disc_type.
        self._args = args
コード例 #15
0
import uasyncio as asyncio
from machine import Timer

tsf = asyncio.ThreadSafeFlag()


def cb(_):
    tsf.set()


async def foo():
    while True:
        await tsf.wait()
        # Could set an Event here to trigger multiple tasks
        print('Triggered')


tim = Timer(1)
tim.init(period=1000, callback=cb)
asyncio.run(foo())
コード例 #16
0
async def advertise(
    interval_us,
    adv_data=None,
    resp_data=None,
    connectable=True,
    limited_disc=False,
    br_edr=False,
    name=None,
    services=None,
    appearance=0,
    manufacturer=None,
    timeout_ms=None,
):
    global _incoming_connection, _connect_event

    ensure_active()

    if not adv_data and not resp_data:
        # If the user didn't manually specify adv_data / resp_data then
        # construct them from the kwargs. Keep adding fields to adv_data,
        # overflowing to resp_data if necessary.
        # TODO: Try and do better bin-packing than just concatenating in
        # order?

        adv_data = bytearray()

        resp_data = _append(
            adv_data,
            resp_data,
            _ADV_TYPE_FLAGS,
            struct.pack("B", (0x01 if limited_disc else 0x02) +
                        (0x18 if br_edr else 0x04)),
        )

        if name:
            resp_data = _append(adv_data, resp_data, _ADV_TYPE_NAME, name)

        if services:
            for uuid in services:
                b = bytes(uuid)
                if len(b) == 2:
                    resp_data = _append(adv_data, resp_data,
                                        _ADV_TYPE_UUID16_COMPLETE, b)
                elif len(b) == 4:
                    resp_data = _append(adv_data, resp_data,
                                        _ADV_TYPE_UUID32_COMPLETE, b)
                elif len(b) == 16:
                    resp_data = _append(adv_data, resp_data,
                                        _ADV_TYPE_UUID128_COMPLETE, b)

        if appearance:
            # See org.bluetooth.characteristic.gap.appearance.xml
            resp_data = _append(adv_data, resp_data, _ADV_TYPE_APPEARANCE,
                                struct.pack("<H", appearance))

        if manufacturer:
            resp_data = _append(
                adv_data,
                resp_data,
                _ADV_TYPE_MANUFACTURER,
                struct.pack("<H", manufacturer[0]) + manufacturer[1],
            )

    _connect_event = _connect_event or asyncio.ThreadSafeFlag()
    ble.gap_advertise(interval_us,
                      adv_data=adv_data,
                      resp_data=resp_data,
                      connectable=connectable)

    try:
        # Allow optional timeout for a central to connect to us (or just to stop advertising).
        with DeviceTimeout(None, timeout_ms):
            await _connect_event.wait()

        # Get the newly connected connection to the central and start a task
        # to wait for disconnection.
        result = _incoming_connection
        _incoming_connection = None
        # This mirrors what connecting to a central does.
        result._run_task()
        return result
    except asyncio.CancelledError:
        # Something else cancelled this task (to manually stop advertising).
        ble.gap_advertise(None)
    except asyncio.TimeoutError:
        # DeviceTimeout waiting for connection.
        ble.gap_advertise(None)
        raise
コード例 #17
0
    raise SystemExit

import micropython

try:
    micropython.schedule
except AttributeError:
    print("SKIP")
    raise SystemExit

try:
    # Unix port can't select/poll on user-defined types.
    import uselect as select

    poller = select.poll()
    poller.register(asyncio.ThreadSafeFlag())
except TypeError:
    print("SKIP")
    raise SystemExit


async def task(id, flag):
    print("task", id)
    await flag.wait()
    print("task", id, "done")


def set_from_schedule(flag):
    print("schedule")
    flag.set()
    print("schedule done")
コード例 #18
0
 def __init__(self, pin, trigger):
     self.pin = pin
     self.flag = asyncio.ThreadSafeFlag()
     self.pin.irq(lambda pin: self.flag.set(), trigger, hard=True)
コード例 #19
0
    def _run_task(self):
        # Event will be already created this if we initiated connection.
        self._event = self._event or asyncio.ThreadSafeFlag()

        self._task = asyncio.create_task(self.device_task())