brilliantlabsAR / monocle-micropython

Micropython ported to the Monocle
ISC License
218 stars 27 forks source link

Bluetooth Protocol #3

Closed josuah closed 1 year ago

josuah commented 1 year ago

Implementation of a Bluetooth-based video streaming protocol both-ways in/out of the monocle.

josuah commented 1 year ago

If I understand correctly, we have three options for implementing video streaming (in/out) over bluetooth:

josuah commented 1 year ago

Video Distribution Profile - https://www.bluetooth.com/specifications/specs/video-distribution-profile-1-1/

The other bluetooth protocols mensioning "video" seems to simply be a layer used by VDP, or for a "TV remote control" use-case.

Image

VDP also has our use-case supported:

Image

josuah commented 1 year ago

Basic Imaging Profile - https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=457085

BIP has the extra overhead of RFCOMM and OBEX. Might be done that way for reducing development effort and reusing something TCP-like: a higher level protocol somehow.

Image

BIP also has our use-case supported:

Image

josuah commented 1 year ago

iOS looks much more restricted as it does not allow any of these three options: https://support.apple.com/en-us/HT204387 Except maybe after enrolling for an MFI program.

josuah commented 1 year ago

https://devzone.nordicsemi.com/f/nordic-q-a/61028/confusion-to-use-l2cap-vs-gatt-for-max-throughput-with-ios Discussion about throughput on iOS with Nordic devices.

josuah commented 1 year ago

https://devstreaming-cdn.apple.com/videos/wwdc/2019/901myoscpux9y7nry55/901/901_whats_new_in_core_bluetooth.pdf#page=27 Apple WWDC19 conference: What is New in Core Bluetooth?

josuah commented 1 year ago

Interesting to note: iOS only gives access to something higher in the stack: "Core Bluetooth" on top of GATT

Image

josuah commented 1 year ago

Android gives full access to L2CAP and above.

josuah commented 1 year ago

Since iOS only gives access to GATT (based on top of Bluetooth Low-Energy), the maximum throughput would be:

Image

josuah commented 1 year ago

GATT is described on this document starting with page 1468: https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=521059

josuah commented 1 year ago

Although, iOS seems to provide an API for dealing with L2CAP directly: https://developer.apple.com/documentation/iobluetooth/iobluetoothl2capchannel

siliconwitch commented 1 year ago

Maybe we can try these calculations and see what might be possible. Seems the limitation would be the iOS connection intervals etc https://novelbits.io/bluetooth-5-speed-maximum-throughput/

josuah commented 1 year ago

Follow-up from this and the call: fiddling with BLE packets directly might be the best compromise, and is largely supported given a rather low-level access to BLE is offered by vendors.

josuah commented 1 year ago
General form:

0x00     0x01     0x02                                    0x512
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Type   │ ID     │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘

Example of transfer:

Micropython opening a file, asking to read it.

 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Start  │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬────────────────────────┐
 │ Stop   │ 0x01   │ Data                   │
 └────────┴────────┴────────────────────────┘

Micropython opening another file, asking to read it.

 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Start  │ 0x02   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x02   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘

Micropython opening another file before file 2 closes.

 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Start  │ 0x03   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘

The two transfer can run concurrently, no need to implement
any scheduling strategy or priority system.

 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x02   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x02   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x03   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬───────────────────────┐
 │ Stop   │ 0x02   │ Data                  │
 └────────┴────────┴───────────────────────┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x03   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x03   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x03   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬────────────────────┐
 │ Stop   │ 0x03   │ Data               │
 └────────┴────────┴────────────────────┘

The file 1 closes on micropython. Nothing to say about it, we already
did a "Stop".

A new file opens, we can use the now-unused file ID (file descriptor) 0x01.

 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Start  │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘

The other file descriptors close on micropython side now, for which we do
nothing as every "Stop" byte was sent, we just keep going the existing
transfers.

 ┌────────┬────────┬──────────────────────────── ─ ─ ─ ──┐
 │ Cont   │ 0x01   │ Data                                │
 └────────┴────────┴──────────────────────────── ─ ─ ─ ──┘
 ┌────────┬────────┬────────────────────────┐
 │ Stop   │ 0x01   │ Data                   │
 └────────┴────────┴────────────────────────┘
josuah commented 1 year ago

The above is a proposal discussed on the chat. Nothing I am working on as of 2022-11-13, only in brainstorming phase. Feel free to comment!