Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-platform Bluetooth support #4589

Open
wants to merge 20 commits into
base: master
from

Conversation

@aykevl
Copy link
Contributor

commented Mar 9, 2019

Here is some Bluetooth support that I've been working on. It is not nearly finished, but advertising and basic setting/getting of characteristics already works.

Note: this work is being sponsored by a company called Sensorberg.

@aykevl aykevl requested review from glennrub and dpgeorge Mar 9, 2019

@pfalcon

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2019

Anything cross-platform would start with Unix port (well, Linux for things not mandated by POSIX), that's the way to implement API covering the widest array of diverse systems.

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 9, 2019

That's harder than you might think. The semantics of BlueZ are quite different from the semantics of all the BLE implementations for MCUs I've looked at, and requires unfortunate things like linking against dbus/glib and a separate thread to interact with dbus. Also, last time I looked BlueZ support for peripheral mode was still very immature.

One example of the differences is that BLE stacks for MCUs allow you to construct a raw advertisement packet. BlueZ simply doesn't allow this, which makes the implementation much harder.

In theory, you could also work directly with the hci socket on Linux, but that requires root access and does not work when you have BlueZ running at the same time (most modern Linux laptops with Bluetooth).


EDIT:

I think it is much easier to say "this module works on microcontrollers" and then implement support for multiple BLE stacks to make sure you're getting the cross-platform part right. This is why I've done the esp32 and nrf support at the same time. A NimBLE port would also be nice, and much easier than BlueZ.

@pfalcon

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2019

Forget about BlueZ, it's crappy bloatware.

In theory, you could also work directly with the hci socket on Linux

There're also L2CAP sockets which shouldn't have root requirements, etc. Yep, probably can't do advertizement using them, but advertizement to Bluetooth is the same as e.g. BGP to Internet protocols. What's important is not advertizement and other "control plane" stuff, but data communication API.

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 9, 2019

Don't confuse classic BT and BLE. The main thing that connects them is their name, and little else. Yes, you may be able to do L2CAP as non-root, but that's only a very small part of what this bluetooth package is about. While classic BT is nice to have, BLE is what is most interesting at the moment (nrf doesn't even have classic BT).

Forget about BlueZ, it's crappy bloatware.

That may be so, but it's required for non-root BLE.

@pfalcon

This comment has been minimized.

Copy link
Contributor

commented Mar 9, 2019

Don't confuse classic BT and BLE. The main thing that connects them is their name, and little else.

Looks like you aren't very familiar with BLE stack architecture, which isn't the best premise to write anything "cross-platform", again.

@dpgeorge

This comment has been minimized.

Copy link
Member

commented Mar 11, 2019

I couldn't get it to work on the esp32 yet due some weird crash so it's disabled at the moment.

I pushed a commit to master fcace26 which should fix this.

@aykevl aykevl force-pushed the aykevl:bluetooth branch from 82b5fa4 to 62de90d Mar 11, 2019

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 11, 2019

I pushed a commit to master fcace26 which should fix this.

Many thanks @dpgeorge, this fixes the issue! I would have needed a lot of time to find that bug.
This code now works on both the esp32 and the BBC micro:bit:

import bluetooth
bt = bluetooth.Bluetooth()
bt.active(1)
bt.advertise(100, 'MicroPython')
print('----')
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])
tx.write('foo')

ilyamordasov added a commit to ilyamordasov/micropython that referenced this pull request Mar 12, 2019

ilyamordasov added a commit to ilyamordasov/micropython that referenced this pull request Mar 12, 2019

ilyamordasov added a commit to ilyamordasov/micropython that referenced this pull request Mar 12, 2019

@glennrub

This comment has been minimized.

Copy link
Contributor

commented Mar 13, 2019

Very nice @aykevl. This is a great start to make a uniform API across targets providing BLE.
I have verified the current implementation on nr52832, and based on what is already implemented it works quite well. :)

Already with this limited feature set, i could envision this to be a second BLE wrapper for nrf-port for a while, and phase out the ubluepy when this gets up to a certain feature set. This will easy further development of a common API.

Have you given any thoughts on how to handle events (connect / disconnect / notifications etc)?

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 14, 2019

Already with this limited feature set, i could envision this to be a second BLE wrapper for nrf-port for a while,

I think having two wrappers complicates things, for example who will handle events? Also, I think it's not really necessary to keep them both around either, as I intend to finish this PR in the next ~2 weeks.

Have you given any thoughts on how to handle events (connect / disconnect / notifications etc)?

Yes, but I'm not sure what the best way would be. One requirement for me is that there are fine-grained events, not one big event loop. That way, multiple modules could independently register a service and handle events for that service (example: an independent DFU module). For connect/disconnect, I think a global event handler would be more appropriate.
These events are somewhat lower priority than most IRQs and you will likely want to do more advanced stuff (such as heap allocations) in them, so I think it would perhaps be better to use micropython.schedule. I'll have to investigate this further.

EDIT: I should also mention that I am being sponsored by a company called Sensorberg. They have agreed with merging this upstream under the MIT license.

@glennrub

This comment has been minimized.

Copy link
Contributor

commented Mar 15, 2019

I think having two wrappers complicates things, for example who will handle events? Also, I think it's not really necessary to keep them both around either, as I intend to finish this PR in the next ~2 weeks.

Yeah, i did not think running them at the same time (ublupy/bluetooth). With this timeline i would guess full replacement right away should work as well as long as the basic feature set is in place. Any plans for BLE REPL replacement? :)

multiple modules could independently register a service and handle events for that service (example: an independent DFU module).

This sounds reasonable.

For connect/disconnect, I think a global event handler would be more appropriate.

See what you mean. But i would like to challenge this a bit as well. :)
If i'm not misunderstanding the current code/design, this is limited to one role at the time, either Central/Pehipheral/Broadcaster/Scanner? Would it make sense to extend the API to facilitate for Bluetooth() instances (and not one singleton)? Even if not supporting more than one in the beginning, the API opens up for multiple roles/instances at the same time in the future? If so, would the global connect/disconnect event handler work ? or could events be supplied with a instance handle supplementing the global event in order to distinguish which of the links had an event?

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 18, 2019

Any plans for BLE REPL replacement? :)

The MVP should support NUS written in Python. I'm not sure I want to directly include support in C at the same time, but it would certainly be very useful in the future.

Central/Pehipheral/Broadcaster/Scanner

To be honest, I never really got the focus on these roles. There is no inherent limitation in the API to have multiple roles at the same time. While not yet supported, I don't see why you wouldn't be able to advertise while a central is connected and at the same time perform a scan for new devices and connect to them. The only limitation is the BLE stack like s110.

What may be useful, however, is support for presenting as multiple devices at once. I think s132 supports that? To the outside world it looks like there are multiple devices but they're actually running on a single radio and BLE stack. I haven't investigated this area a lot. But I think they cannot be separated entirely at the API level: it's still one stack that has to be enabled.

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 18, 2019

Another issue that I'd like to get some feedback on: how should notifications work?
Notifications are basically a signal from the peripheral to the central that a characteristic has been updated. This is used to send information from the peripheral to the central, for example to send serial data over NUS, or to send heart rate updates in a classic BLE example.

I see two possible implementations:

  1. Connections are managed by MicroPython. You can get a notification when a device connects or disconnects, but the only thing you have to do is send a notification and it'll get sent to all connected devices (if multiple connections are supported in the BLE stack).
  2. Connections are managed by the Python script. It will have to track of all connect/disconnect events and manually send a notification to all of the connected devices.

Example of the former:

bt = bluetooth.Bluetooth()
bt.active(1)
bt.advertise(100, 'MicroPython')
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])
bt.set_event_handler(handle_event)

while 1:
    time.sleep(1)
    tx.write('log something\n')

Example of the latter:

connected_devices = set()
def handle_event(code, device):
    # TODO: can we even do memory allocations in an event handler?
    if code == bluetooth.CONNECTED:
        connected_devices.add(device)
    elif code == bluetooth.DISCONNECTED:
        connected_devices.remove(device)

def log(msg):
    for device in connected_devices:
        try:
            tx.notify(msg, device)
        except OSError:
            pass # probably this device disconnected but the event hasn't yet triggered

bt = bluetooth.Bluetooth()
bt.active(1)
bt.advertise(100, 'MicroPython')
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])
bt.set_event_handler(handle_event)

while 1:
    time.sleep(1)
    log('log something\n')

While the former is a bit more implementation work and less flexible, it is more modular. There is no central module that has to manage all connections: this is all done from within the Bluetooth wrapper. While it results in a bit more code size on devices that support more than one connection, I think it is ultimately far less error prone than the latter which is easy to get slightly wrong. The former also results in less Python code which usually leads to reduced RAM consumption. Remember that many of the more interesting BLE stuff requires notifications so it isn't really optional.
I would prefer to go with the former option, but would like to hear comments on this. Let me know if you can think of a use case that requires the flexibility of the latter.

@dpgeorge

This comment has been minimized.

Copy link
Member

commented Mar 19, 2019

how should notifications work?
...
I see two possible implementations:

On the one hand it's nice to push code into the Python level (ie approach 2) because it gives more flexibility and results in simpler/smaller firmware. On the other hand things that are low level and a necessary part of the stack which will be implemented the same way each time are good candidates to go in the C implementation (approach 1).

So I think it makes more sense to go for approach 1. Then Python code doesn't even need to know/worry whether multiple connections are supported or not, their BLE code remains the same. And there is already a lot to do on the Python side to configure and manage a BLE service, which is suitable for putting in Python-level libraries and/or helper functions, that adding more complexity in the Python code could make it difficult to maintain.

For BLE stacks that only support a single connection, approach 1 should be relatively simple to implement because it's likely that GAP/GATT callback functions already exist at the C level for other purposes. (And some BLE stacks may even handle notifications automatically so approach 2 would not be possible to implement on such stacks.)

I guess that for all characteristics that have a notify property there's rarely a case that they don't need to send a notification when their data changes, so having approach 1 do auto notification on characteristic change is not a big restriction. But if one day more flexibility is needed then a MANUAL_NOTIFY pseudo-property could be added which requires the user to do the notify.

On a related note, does the user need to restart advertising when the connection stops, or is that also automatic?

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 19, 2019

@dpgeorge thank you for your thoughts on the matter.

On a related note, does the user need to restart advertising when the connection stops, or is that also automatic?

This is automatic. At the moment, advertisement restarts on a disconnect event. This should be improved so advertisements continue to work when a device connects, and only when the max number of connections has been reached should it either switch to non-connectable advertisements or stop advertising. The former makes more sense to me (think of beacons that are connectable), while the latter seems to be more common in BLE devices.

@ilyamordasov

This comment has been minimized.

Copy link

commented Mar 19, 2019

Am I right there is no possibility to connect to the slave device directly knowing its address without scanning all available divices and matching their names/bdas???

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 19, 2019

Am I right there is no possibility to connect to the slave device directly knowing its address without scanning all available divices and matching their names/bdas???

Not sure what you're asking but this PR does not support central mode yet so it can't connect to any peripheral devices. If you're asking how other devices can connect to a BLE peripheral running MicroPython: that's completely up to them. They may scan first or connect directly when they know the MAC address.

@dpgeorge

This comment has been minimized.

Copy link
Member

commented Mar 19, 2019

This is automatic. At the moment, advertisement restarts on a disconnect event. This should be improved ...

This is an example where it might be more useful if the behaviour were controlled via Python code (not via the C driver). Because then the user could select how it worked: advertising stops, continues, changes, etc. The usual case is to handle just one connection, stop adv when connected and restart when disconnected. But adv can be more general than this, after all adv (and scanning) is used as the basis of BLE mesh.

@dpgeorge

This comment has been minimized.

Copy link
Member

commented Mar 20, 2019

For comparison, CircuitPython have a bleio module which is documented at https://circuitpython.readthedocs.io/en/latest/shared-bindings/bleio/__init__.html

Edit: see also a high-level wrapper for a UART NUS service: https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/master/adafruit_ble/uart.py

@dhalbert

This comment has been minimized.

Copy link

commented Mar 20, 2019

Also see the Adafruit library https://github.com/adafruit/Adafruit_CircuitPython_BLE, which implements a NUS service. We’ve tried to provide the basics in the native module, and then build the rest in Python.

Edit: [oops, crossed with @dpgeorge]

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Mar 28, 2019

I have pushed support for notifications. Notifications are as simple as adding bluetooth.FLAG_NOTIFY to the characteristic flags, the rest is done inside the bluetooth module. However, I found some instability on nrf chips so I'll need to investigate the exact cause (something about BLE_ERROR_GATTS_SYS_ATTR_MISSING).

For comparison, CircuitPython have a bleio module which is documented at https://circuitpython.readthedocs.io/en/latest/shared-bindings/bleio/__init__.html

That's very interesting! They seem to handle notifications inside the module as well.

@dmartauz

This comment has been minimized.

Copy link

commented Apr 2, 2019

@aykevl Good work, looking forward to test your implementation on ESP32. Are you planning to do some more development or do you consider it done?

Also +1 for Sensorberg for permission to merge upstream.

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Apr 4, 2019

I have pushed another change that adds a .on_update() method to characteristics to register writes by a central. For example:

def callback(char, data):
    print('data:', data)
rx.on_update(callback)

This works on both nrf52 and nrf51. Unfortunately, I haven't yet managed to get this working on the esp32, it crashes with a LoadProhibited on this line:

nlr->prev = *top;

When I replace mp_call_function_2_protected with mp_call_function_2 (thinking it is something in exception handling), it crashes on this line with a load from address 0:

return MP_STATE_THREAD(stack_top) - (char*)&stack_dummy;

The crash for the second try is here:

Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC      : 0x400dd09e  PS      : 0x00060230  A0      : 0x800dd0ba  A1      : 0x3ffd4310  
A2      : 0x00000001  A3      : 0x00000001  A4      : 0x3ffb61b0  A5      : 0x00000080  
A6      : 0x00000001  A7      : 0x00000000  A8      : 0x800dd09e  A9      : 0x3ffd42f0  
A10     : 0x00000000  A11     : 0x00000000  A12     : 0x3ffb2b88  A13     : 0x00000000  
A14     : 0x00000001  A15     : 0x00000000  SAR     : 0x00000008  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

Backtrace: 0x400dd09e:0x3ffd4310 0x400dd0b7:0x3ffd4340 0x400dfe75:0x3ffd4360 0x400dc045:0x3ffd4390 0x400dc0a2:0x3ffd43b0 0x400f76f9:0x3ffd43e0 0x400f2332:0x3ffd4410 0x40143d16:0x3ffd4430 0x40144976:0x3ffd4450 0x401417be:0x3ffd4490 0x40092b7d:0x3ffd44c0

Does anyone have an idea what might be going wrong on the esp32? I'm suspecting it has something to do with being handled in a different task. I have tried to increase the stack size for callbacks, but that didn't help.

@aykevl aykevl marked this pull request as ready for review Apr 4, 2019

aykevl added some commits Apr 29, 2019

extmod/modbluetooth: fix multiple services
One application profile does not map to a single service, but it really
maps to a single application. This resulted in a number of
connect/disconnect events equal to the number of registered services,
which of course is wrong unless exactly one service is registered.

Make sure we create one application profile at start and use that the
whole time.
extmod/modbluetooth: implement device.disconnect()
This commit allows the Python code to explicitly disconnect a central
device using device objects from connect or write events.
nrf: Enable ubinascii module.
This costs about 1kB in code size but is very useful to convert MAC
addresses to hex format: MAC addresses will be returned in raw form in a
future commit.
extmod/modbluetooth: Expose raw MAC as .config('mac').
Instead of returning a human-readable string with .address() on both the
Bluetooth and Device object, return a raw MAC address with a
.config('mac') call. This is more extensible and more in line with how
the network module does it. The MAC address can easily be converted back
to hex format with the ubinascii module.

@aykevl aykevl force-pushed the aykevl:bluetooth branch from e13f4c7 to 5b3afbc Aug 2, 2019

@aykevl

This comment has been minimized.

Copy link
Contributor Author

commented Aug 2, 2019

I have rebased this branch and fixed a critical issue that caused memory corruption. I think this PR is ready for review.

@KaranRajPradhan you may want to try again after the last update. The code you posted was likely affected by this bug.

@vanminh0910

This comment has been minimized.

Copy link

commented Aug 4, 2019

Thanks for your great great work to support the Bluetooth, one of very interesting feature of the ESP32. I have clone and compile the unchanged code from the branch and test this code but cannot connect from my phone or PC, even though the bluetooth service is advertised corretcly and can be seen on my phone/PC.

Here is the code I used to test:

import bluetooth, time

bt = bluetooth.Bluetooth()
if bt.active() == False:
bt.active(True)
bt.advertise(100, "MicroPython")
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])

def callback(dev, char, data):
print('char_irq', dev.config('mac'), dev.connected(), char.uuid(), data)
rx.irq(callback, bluetooth.IRQ_WRITE)
print('done')

On my phone, I use both classic bluetooth app (blueterm) and BLE scan but not any works. Can anyone point me where the problem is? Thanks.

@silbo

This comment has been minimized.

Copy link

commented Aug 6, 2019

@aykevl huge thanks for all the great work that went into this. is it already possible to receive and send data currently ?

@bruno963852

This comment has been minimized.

Copy link

commented Aug 7, 2019

I have tested the basic functions with ESP32-WROVER and it works like a charm! Advertising, read, write and notify.

@silbo

This comment has been minimized.

Copy link

commented Aug 7, 2019

I have tested the basic functions with ESP32-WROVER and it works like a charm! Advertising, read, write and notify.

@bruno963852 Thats awesome, which branch are you working with exactly ? https://github.com/aykevl/micropython/tree/bluetooth ?

@bruno963852

This comment has been minimized.

Copy link

commented Aug 7, 2019

I have tested the basic functions with ESP32-WROVER and it works like a charm! Advertising, read, write and notify.

@bruno963852 Thats awesome, which branch are you working with exactly ? https://github.com/aykevl/micropython/tree/bluetooth ?

Exactly! If you're using a module with PSRAM you have to alter the sdkconfig.spiram file to enable bluetooth, just add the lines:

# Bluetooth
CONFIG_BT_ENABLED=y
CONFIG_BLUEDROID_PINNED_TO_CORE=0
CONFIG_BT_ACL_CONNECTIONS=4
CONFIG_GATTS_ENABLE=y
@vanminh0910

This comment has been minimized.

Copy link

commented Aug 8, 2019

@bruno963852, can you share which mobile app you used to talk to the esp32?

@bruno963852

This comment has been minimized.

@silbo

This comment has been minimized.

Copy link

commented Aug 8, 2019

@bruno963852 could you also share the MicroPython code that you are using? I think I am just missing the notify function for read and write that is why it's not working.

@bruno963852

This comment has been minimized.

Copy link

commented Aug 8, 2019

@silbo, the code posted by @vanminh0910 works:

import bluetooth

bt = bluetooth.Bluetooth()
bt.active(True)
bt.advertise(100, "MicroPython")
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])

def callback(dev, char, data):
	print('char_irq', dev.config('mac'), dev.connected(), char.uuid(), data)

rx.irq(callback, bluetooth.IRQ_WRITE) # Register the callback to execute on data received

print('done')

You can write data using tx.write('my data') and the data you send using the app will be printed by the callback.

@silbo

This comment has been minimized.

Copy link

commented Aug 8, 2019

@bruno963852 aha yea thanks a lot, it works on android with bluedroid stack only it seems. I tried on iOS and MAC OS don't work. BLE is so complicated, have to implement all the different stacks it seems :D ?!?!

@KaranRajPradhan

This comment has been minimized.

Copy link

commented Aug 9, 2019

I have rebased this branch and fixed a critical issue that caused memory corruption. I think this PR is ready for review.

@KaranRajPradhan you may want to try again after the last update. The code you posted was likely affected by this bug.

Thanks for this @aykevl , that solves the problem. I'm on the process of testing it and everything seems to work fine.
Although, I'm not sure if we have read events implemented?

@silbo

This comment has been minimized.

Copy link

commented Aug 9, 2019

@KaranRajPradhan you are testing on android ? seems to be the only platform that currently works, as far as I tested.

@superted6851

This comment has been minimized.

Copy link

commented Aug 11, 2019

@silbo I tested on iOS and MacOS, using LightBlue and BlueSee, respectively, it seems to work fine on both platforms. I tested with a Wipy V3 and ESP-DevKitCV4 (WROVER), both connected and remained connected. The only issues I saw with MacOS and iOS was with nrf52830, it would not connect to iOS and MacOS disconnected after about 30 seconds. I also had the same issue with NUS WebBluetooth REPL and uBluepy. So might be something in the connection parameters for nrf boards.

@Afantor

This comment has been minimized.

Copy link

commented Aug 12, 2019

@aykevl @glennrub @bruno963852 I have verified the current implementation on ESP32, and based on what is already implemented it works quite well. :)
But now I can not work on nRF52832 board, it code worked, but it can't connect to my mobile phone.
The same code on ESP32, it work good. And read char from my phone app.

The code is here:
`import bluetooth, time

bt = bluetooth.Bluetooth()
if bt.active() == False:
bt.active(True)
bt.advertise(100, "MicroESP32")
tx = bluetooth.Characteristic('6E400002-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_NOTIFY)
rx = bluetooth.Characteristic('6E400003-B5A3-F393-E0A9-E50E24DCCA9E', bluetooth.FLAG_READ|bluetooth.FLAG_WRITE)
s = bt.add_service('6E400001-B5A3-F393-E0A9-E50E24DCCA9E', [tx, rx])

def callback(dev, char, data):
print('char_irq', dev.config('mac'), dev.connected(), char.uuid(), data)
tx.write(data)

rx.irq(callback, bluetooth.IRQ_WRITE)
print('done')`

@silbo

This comment has been minimized.

Copy link

commented Aug 14, 2019

@superted6851 thanks for the info, I will test again when I get time : )

@silbo

This comment has been minimized.

Copy link

commented Aug 19, 2019

@superted6851 you are right the apps you mentioned work, but I can't get it to work with WebBluetooth in the browser, which is want to use for my application. Also the Adafruit Bluefruit LE Connect app doesn't work. Still need some investigation and testing 👍

@vanminh0910

This comment has been minimized.

Copy link

commented Aug 20, 2019

@silbo Same to me. The app recommended by @superted6851 works well but not other BLE app. Not sure why.

@superted6851

This comment has been minimized.

Copy link

commented Aug 20, 2019

@silob Webluetooth will work on MacOS if you use chrome browser, you can check connectivity by checking the bluetooth internals chrome://bluetooth-internals/. You should be able to connect and read/write characteristics. Currently webluetooth is in active development so not all browsers are fully supported. You can then write your web-app using the webluetooth API.

If you specifically are talking about REPL over webluetooth then this currently only works with Nordic UART service (NUS), therefore only nrf boards are supported. I think this might be the same for Adafruit Bluefruit LE connect app. If you look at the supported device for the app they are all nordic chipset based.

I can find and connect to the esp32 using Bluefruit LE connect app but I can not send/receive data with esp32, I cannot even connect with nrf52. The cross platform bluetooth support does not use NUS as it is proprietary, and I think Bluefruit expects NUS protocol hence why it will not work

@dhalbert

This comment has been minimized.

Copy link

commented Aug 20, 2019

If you specifically are talking about REPL over webluetooth then this currently only works with Nordic UART service (NUS), therefore only nrf boards are supported. I think this might be the same for Adafruit Bluefruit LE connect app. If you look at the supported device for the app they are all nordic chipset based.

NUS is proprietary in that it uses 128-bit UUIDs generated by Nordic, but there's no licensing requirement for it, and you don't have to use Nordic's code. Some people have implemented it on ESP32 (e.g., https://forum.arduino.cc/index.php?topic=580958.0, but see caveat).

The Adafruit Bluefruit LE app does depend on NUS for the vast majority of its functionality. There's a somewhat ad hoc protocol implemented on top of that for the control functionality the app provides (button presses, color picker, etc.). But it also provides generic UART capability.

@dmazzella

This comment has been minimized.

Copy link
Contributor

commented Aug 20, 2019

If you specifically are talking about REPL over webluetooth then this currently only works with Nordic UART service (NUS), therefore only nrf boards are supported. I think this might be the same for Adafruit Bluefruit LE connect app. If you look at the supported device for the app they are all nordic chipset based.

NUS is proprietary in that it uses 128-bit UUIDs generated by Nordic, but there's no licensing requirement for it, and you don't have to use Nordic's code. Some people have implemented it on ESP32 (e.g., https://forum.arduino.cc/index.php?topic=580958.0, but see caveat).
The Adafruit Bluefruit LE app does depend on NUS for the vast majority of its functionality. There's a somewhat ad hoc protocol implemented on top of that for the control functionality the app provides (button presses, color picker, etc.). But it also provides generic UART capability.

for an idea of how to implement it using api similar to "bluepy" you can take a look at:
api_repl.py

@dmazzella

This comment has been minimized.

Copy link
Contributor

commented Aug 20, 2019

for reference: #4893

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.