Skip to content

BLE: feature gatt client - Generic GattClient implementation #4781

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

Conversation

pan-
Copy link
Member

@pan- pan- commented Jul 19, 2017

Description

This PR adds a generic implementation of the GattClient. This implementation relies on the pal::GattClient being provided by the vendor.

Status

READY

Migrations

NO

pan- added 10 commits July 19, 2017 12:18
Base types like the connection handle type or the attribute handle used
accross all the layers were defined in the upper layer. It is not right to
makes lower layers needed those types dependent on the upper layer.

This change introduce a new header defining those base types shared
accross high and lovel layer.
In case of faillure during descriptor discovery, the error code can help
the user to determine the cause of the error.
@pan-
Copy link
Member Author

pan- commented Jul 19, 2017

@apalmieriGH @nvlsianpu Could you have a look at this PR ? It should help you in the process of providing a pal::GattClient or pall::AttClient.

@pan- pan- requested review from apalmieriGH and nvlsianpu July 19, 2017 13:36
pan- added 3 commits July 21, 2017 13:46
* Include necessary AttServerMessage header.
* Force AttClient::write_request to be pure virtual member function.
@AnotherButler
Copy link
Contributor

@pan- Thanks for the PR. Because we use the PR subject titles in our release notes, could you please change your subject line to imperative mood? We recommend changing it to "BLE: implement generic GattClient". Thanks so much.

@theotherjimmy
Copy link
Contributor

@pan- any news?

@pan-
Copy link
Member Author

pan- commented Aug 8, 2017

@theotherjimmy Not from our ble partners unfortunately.

@nvlsianpu
Copy link
Contributor

@pan I will review this until end of week.

@nvlsianpu
Copy link
Contributor

nvlsianpu commented Aug 11, 2017

  • ble/BLETypes.h - OK
  • ble/ArrayView.h - OK
  • ble/CharacteristicDescriptorDiscovery.h - OK : added error code to parameters for discovery process termination.
  • ble/DiscoveredCharacteristic.h - OK: got rid of unnecessary ble/ for include
  • ble/Gap.h OK: Handle_t turned from uint16_t to uintptr_t (in result).
  • ble/GatAttribite.h OK: Handle_t turned from uint16_t to uintptr_t (in result).
  • ble/GattClient.h - OK: desctructor added
  • pal/AttClient.h - OK: changes for comply with renaming in ArrayView modle.
  • ble/GattCallbackParamTypes.h - OK: GattWriteCallbackParams structure turned len field to back compatible union, Documented. GattWriteCallbackParams structure turned len & offset fields to back compatible unions, Documented.
  • ble/pal/AttClientToGattClientAdapter.h - OK: changes for comply with renaming in ArrayView module, made API puiblic.
  • ble/pal/AttServerMessage.h - OK: extended AttReadResponse & AttReadBlobResponse structures by get-data-pointer method.
  • ble/pal/GattClient.h - OK: changes for comply with renaming in ArrayView modle. Could you change the name file to different? (in ble directory exist file of the same name)
  • ble/pal/SimpleAttServerMessage.h - OK: changes for comply with renaming in ArrayView module.

update for the rest soon

@pan-
Copy link
Member Author

pan- commented Aug 11, 2017

@nvlsianpu Thanks for your comments.

ble/Gap.h OK: Handle_t turned from uint16_t to uintptr_t (in result).
ble/GatAttribite.h OK: Handle_t turned from uint16_t to uintptr_t (in result).

A connection handle, in HCI term, is a 16 bit integer (ranging from 0x0000 to 0x0EFF). Unfortunately, this might not be the same thing for some stack (it might refer to an opaque pointer for instance). That's the reason behind the change.

ble/GattCallbackParamTypes.h - OK: GattWriteCallbackParams structure turned len field to back compatible union, Documented. GattWriteCallbackParams structure turned len & offset fields to back compatible unions, Documented.

At some points, we will have to split out event associated with an ATT request from event associated to an ATT response. Historically, they have been the same and it felt just wrong once we add error handling in the equation. Some fields, like data in GattWriteCallbackParams also doesn't make sense in the response.

ble/pal/GattClient.h - OK: changes for comply with renaming in ArrayView modle. Could you change the name file to different? (in ble directory exist file of the same name)

Yes I will change the name of the file.

@nvlsianpu
Copy link
Contributor

I reviewed (almost) GenericGattClient.cpp - I have some remarks:
some procedures are not implemented e.g read multiple characteristic values method, reliable writes procedure, secondary service discovery - Is it possible to add check list in PR description.

I think It would be nice if callback chains of procedures were documented (especially for discovery process ) - this is minor wish only - but I think It would simplify maintenance further as well.

@pan-
Copy link
Member Author

pan- commented Aug 15, 2017

I reviewed (almost) GenericGattClient.cpp - I have some remarks:
some procedures are not implemented e.g read multiple characteristic values method, reliable writes procedure, secondary service discovery - Is it possible to add check list in PR description.

These procedures are not yet defined in the GattClient abstraction however they are not forgotten. That's the reason why all the primitives necessary to realize them are in the adaptation layer. They will be added once partners provide the adaptation layer. I also think the horrendous function launchServiceDiscovery will be deprecated and replaced with proper alternatives which does a single thing instead of handling (poorly) all at once. Namely four procedures:

  • Discover all primary services.
  • Discover all primary services by service UUID.
  • Discover all characteristics of a service.
  • Discover characteristics by UUID.

The procedures to be added are:

  • Find included service
  • Read using characteristic UUID
  • Read multiple characteristic values
  • Reliable writes (I would prefer another denomination, it really is useful for writing atomically a set of characteristic values, it is not really about reliability which is already there for regular write and long write).

I think It would be nice if callback chains of procedures were documented (especially for discovery process ) - this is minor wish only - but I think It would simplify maintenance further as well.

I agree, could you list what interaction diagram you would like to have in the documentation ?

@nvlsianpu
Copy link
Contributor

@pan Thanks for answer. I'm done with review this PR. Great job - I really like how GenaricGattClientit is written and organized.

I agree, could you list what interaction diagram you would like to have in the documentation ?

message or state diagram for launchServiceDiscovery implementation would be OK.

I also think the horrendous function launchServiceDiscovery will be deprecated

Unless it works properly it is OK to have it as is. I agree - fragmented discovery will be more useful for real application. My opinion is that the Discovery of whole device should be moved to an example or a library.

@pan-
Copy link
Member Author

pan- commented Aug 16, 2017

message or state diagram for launchServiceDiscovery implementation would be OK.

I can do that, basically it will model behavior described in the porting guide.

Unless it works properly it is OK to have it as is. I agree - fragmented discovery will be more useful for real application. My opinion is that the Discovery of whole device should be moved to an example or a library.

I was thinking of deprecating it, not removing it. My main issue with that function is its complexity. It also hides to the user which procedure is really used and it is a bad thing if you want to tailored your application to consume less energy. Direct access to the standard procedure is, I believe, the way to go. I'd like to see examples demonstrating the different kind of discovery available while explaining clearly the use case for each and the impact on power when one or the other is used.

@nvlsianpu
Copy link
Contributor

Prose is OK as well (even without diagrams). What I had as idea is to have states, messages, request, and respond names used in documentation - which makes geting into the code more harmless.

namespace ble {
namespace generic {

// forward declaration
Copy link
Contributor

Choose a reason for hiding this comment

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

prular, declarations

uint16_t GenericGattClient::get_mtu(Gap::Handle_t connection) const {
uint16_t result = 23;
if(_pal_client->get_mtu_size((connection_handle_t) connection, result) != BLE_ERROR_NONE) {
result = 23;
Copy link
Contributor

Choose a reason for hiding this comment

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

I prefer assertion which hang process upon error. In case you want to have default value for mtu size I prefer to have virtual method with default implementation which return 23 instead of abstract one already implemented.

Copy link
Contributor

Choose a reason for hiding this comment

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

Comment it is related to every get_mtu in this file.


memcpy(data + (current_offset - offset), read_response.data(), read_response.size());
current_offset = current_offset + read_response.size();
client->_pal_client->read_attribute_blob(
Copy link
Contributor

Choose a reason for hiding this comment

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

I recommend error handling as for initial read request (+ resource free)

break;

default:
// error
Copy link
Contributor

Choose a reason for hiding this comment

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

message assertion

break;

default:
// error
Copy link
Contributor

Choose a reason for hiding this comment

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

message assertion

static DiscoveredCharacteristic::Properties_t get_properties(const ArrayView<const uint8_t>& value) {
uint8_t raw_properties = value[0];
DiscoveredCharacteristic::Properties_t result;
result._broadcast = raw_properties && (1 << 0);
Copy link
Contributor

Choose a reason for hiding this comment

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

here and next few lines & instead of &&

if (last_characteristic.getValueHandle() == services_discovered->end) {
handle_all_characteristics_discovered(client);
} else {
client->_pal_client->discover_characteristics_of_a_service(
Copy link
Contributor

Choose a reason for hiding this comment

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

need error service here and around


virtual ~descriptor_discovery_control_block_t() { }

ble_error_t start(GenericGattClient* client) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice - what about a start method for other xxx_control_block_t - a see at last pros of coherence

@theotherjimmy
Copy link
Contributor

@pan- any news?

@0xc0170
Copy link
Contributor

0xc0170 commented Sep 4, 2017

@pan- Bump

@pan-
Copy link
Member Author

pan- commented Sep 28, 2017

I close this, comments have been addressed in #5060.

@pan- pan- closed this Sep 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants