Skip to content

WIP: bleio rewrite #1289

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

Merged
merged 32 commits into from
Nov 7, 2018
Merged

WIP: bleio rewrite #1289

merged 32 commits into from
Nov 7, 2018

Conversation

arturo182
Copy link
Collaborator

@arturo182 arturo182 commented Oct 21, 2018

Here is the WIP of the bleio rewrite, it was done in July and August, but I rebased it on the current master, so not 100% everything will work out of the box, but at least this can give a good starting point for the ble work.

I tried to make the API as simple as possible, while still being robust and not limiting more advanced users. I think we could make a separate python API based on this one, like @tannewt suggested way back, so the users can easily create services alike Battery Service, etc.

I also tried to document as much as possible, so the generated docs should give some insight to the API and usage. See the Device class for usage:

import bleio

# Peripheral
periph = bleio.Device()

serv = bleio.Service(bleio.UUID(0x180f))
periph.add_service(serv)

chara = bleio.Characteristic(bleio.UUID(0x2919))
chara.read = True
chara.notify = True
serv.add_characteristic(chara)

periph.start_advertising()

# Central
scanner = bleio.Scanner()
entries = scanner.scan(2500)

my_entry = None
for entry in entries:
    if entry.name is not None and entry.name == 'MyDevice':
        my_entry = entry
        break

central = bleio.Device(my_entry.address)
central.connect()

Also added a UUIDType enum-like class for determining UUID type.
Use the new in the Adapter singleton.
This was the last class from ubluepy and so that module is now gone.
The Device class offers both Peripheral and Central functionality.
See the inline docs for more info.
Moved the functions to classes that they belong to.
Because of the very specific way nRF requires service registration
(characteristics can be added only to last added service), we would
have to write the Python code in a specific way. With this patch the
user has more freedom.
@arturo182 arturo182 force-pushed the bleio branch 2 times, most recently from 8e959e6 to 01a6bbc Compare October 21, 2018 14:39
@dhalbert
Copy link
Collaborator

Thanks! Could you say a little something about how it differs from ubluepy and your thinking when making the changes?

@dhalbert
Copy link
Collaborator

Thanks for all this work! I'm starting a review with comments after educating myself on BLE, going over bluepy (not specifically ubluepy) and then your code.

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like how you have cleaned up the non-Pythonic parts of ubluepy, creating classes where necessary, and using properties where appropriate.

I haven't reviewed in any detail common-hal code at all, because I'm completely unfamiliar with the Softdevice API. I'm willing to merge it in and start testing it.

We still should create wrappers on top of this for various Profiles and maybe some common Central use cases.

What are your thoughts about handling things that DefaultDelegate does in ubluepy?

#include "ble.h"

#if (BLUETOOTH_SD == 132) && (BLE_API_VERSION == 2)
#define NRF52
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this cover SD140 as well?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that for SD140 this define is not needed as it uses the NRF528xx defines. This is just for legacy reasons


#if (MICROPY_PY_BLE_NUS == 1)

static const char default_name[] = "CP-REPL"; // max 8 chars or uuid won't fit in adv data
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"CIRCPY", maybe? Is this max 7 + 1 null or max 8?
"CIRCUITP" is 8


//| .. attribute:: write
//|
//| A `bool` specifying if the characteristic allows writting to its value.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"writting" -> "writing" here and several other places.

//| =========================================================
//|
//| Provides access a to BLE device, either in a Peripheral or Central role.
//| When a device is created without any parameter passed to the constructor,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Device now does both Peripheral and Central, but this seems like two classes mostly stuck together. They share .name and .services, but even those mean somewhat different things. I would be inclined to go back to two different classes, so that they really do different things and you don't have to keep checking whether you're one kind of Device or the other.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my idea was that we want to make the API as simple as possible, so we don't want to bother the user with terms like Peripheral and Central and having them try to figure out which one they need to use, it's easier to just have one.


//| .. attribute:: type
//|
//| The UUID type. One of:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to have UUID16 and UUID128, possibly as subclasses of an abstract UUID, if there is really code to be shared. We can use the Python type system. We can do isinstance() to figure out the type, instead of checking a field.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that might be better.


#include "shared-bindings/bleio/UUIDType.h"

//| .. currentmodule:: bleio
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class would go away if we have UUID16 and UUID128.

@dhalbert
Copy link
Collaborator

dhalbert commented Nov 5, 2018

@arturo182 I know you're working on other projects. Let me know if you have time to respond to this, or if I should just proceed. Even a quick response to some of the queries would be helpful. Tnx.

@arturo182
Copy link
Collaborator Author

I'm so sorry! I'll respond later today, but in general I think you can proceed with what you think is best for the project.

@arturo182
Copy link
Collaborator Author

Thanks! Could you say a little something about how it differs from ubluepy and your thinking when making the changes?

It differs quite a lot since I made many breaking changes. I wanted the API to be something that I would find intuitive and easy to use, to be like other CP APIs, easy for beginners.

Truth be told, it's been some time since I wrote this and I should've pushed it earlier, because now I have a hard time remembering all the details of my decisions.

Also, as you say, I've been quite busy working on other projects and I'm not sure how much time I will be able to spend on this, so if you feel it's going to be easier for you to polish this PR up before it's merged or even abandon it and only pick pieces to use as a base for a different API, I'll understand.

@tannewt tannewt merged commit 4bc24c4 into adafruit:master Nov 7, 2018
tannewt added a commit that referenced this pull request Nov 7, 2018
@arturo182 arturo182 deleted the bleio branch November 7, 2018 20:17
@dhalbert
Copy link
Collaborator

dhalbert commented Nov 7, 2018

Wow, merging #1319 merged #1289 automatically, because #1319 included the commits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants