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

[documentation] How to use this Lib #59

Open
16L-YT opened this issue May 22, 2021 · 8 comments
Open

[documentation] How to use this Lib #59

16L-YT opened this issue May 22, 2021 · 8 comments

Comments

@16L-YT
Copy link

16L-YT commented May 22, 2021

Is your feature request related to a problem? Please describe.
It is not straight forward how to use this Lib. I need to check if the following steps I followed (I managed to include in my project correctly) are correct. Also I was wondering why there is no CMakeLists.txt in the parent directory of this Lib and for services library.

Describe the solution you'd like

  1. Add mbed-os-experimental-ble-services.lib to project directory, with the following as content: https://github.com/ARMmbed/mbed-os-experimental-ble-services
  2. run mbed deploy in order to download the library.
  3. Add to the following CMakeLists.txt to mbed-os-experimental-ble-services directory:
add_library(mbed-os-experimental-ble-services INTERFACE)

target_include_directories(mbed-os-experimental-ble-services
    INTERFACE
        .
)

add_subdirectory(services)
  1. Add to the following CMakeLists.txt to mbed-os-experimental-ble-services\services:
add_subdirectory(DeviceInformation)
add_subdirectory(CurrentTime)
add_subdirectory(LinkLoss)
  1. Example Usage in main.cpp:
//...
#include "ble-service-device-information/DeviceInformationService.h"
//...

       DeviceInformationService::system_id_t system_id;
        system_id.manufacturer_defined_identifier =    0x00EEFFC0;
        system_id.organizationally_unique_identifier = 0x0000000000000000;

        DeviceInformationService::add_service(ble,
            "CompanyName", 
            MBED_CONF_APP_MODEL_NAME, 
            serial_nr, 
            MBED_CONF_APP_HW_REV, 
            GIT_COMMIT_TAG "(" __DATE__ " " __TIME__ ")",  
            GIT_COMMIT_HASH,
            &system_id,
            nullptr,
            nullptr
        );

  1. Add to the main project CMakeLists.txt the following:
add_subdirectory(mbed-os-experimental-ble-services)


target_link_libraries(${APP_TARGET}
    PRIVATE
        mbed-os
        mbed-events
        mbed-ble
        mbed-ble-utils
        ble-service-device-information
)

Describe alternatives you've considered
N/A

Additional context
N/A

@pan-
Copy link
Member

pan- commented May 24, 2021

Thanks for asking this question @16L-YT .

Today we have no global library that includes all services, you have to pick and choose which one you want to use in your CmakeLists.txt file. For example if you want the link loss service and the current time service:

add_subdirectory(mbed-os-experimental-ble-services/services/CurrentTime)
add_subdirectory(mbed-os-experimental-ble-services/services/LinkLoss)

Then in the target_link_libraries of your application, you have to link the libraries:

target_link_libraries(${APP_TARGET}
    PRIVATE
        mbed-os
        mbed-events
        mbed-ble
        ble-service-link-loss
        ble-service-current-time
)

If I understand correctly your issue, there is two enhancement that can be made:

  • Add documentation that explain how to integrates libraries in a project.
  • Add a library that contains all other libraries. It could be useful for users that don't care about build time.

Is that correct ?

@16L-YT
Copy link
Author

16L-YT commented May 25, 2021

Yes that is correct.

The steps you mentioned are good to be included in the README.

Feel free to close this issue anytime.

@idea--list
Copy link

Does one absolutely need Mbed OS CLI to try this lib or even Mbed Studio can handle that if i put the CMakeLists.txt files into the directories mentioned by @16L-YT ? I ask because CLI freaks me out all the time and prefer not using that.

@noonfom
Copy link

noonfom commented Jun 1, 2021

@idea--list In Mbed Studio, you can use this library just like any other library:

  1. Go to the Libraries view by selecting View -> Libraries in the navigation bar
  2. Click the '+' icon to add a new library
  3. In the popup window, enter the URL of the library followed by its name:

add_mbed_library

Now, you can include any of the services in you main application as follows:

// Include Current Time service
#include "ble-service-current-time/CurrentTimeService.h"
// Include Device Information service
#include "ble-service-device-information/DeviceInformationService.h"
// Include Link Loss service
#include "ble-service-link-loss/LinkLossService.h"

However, you may have found that Mbed Studio will produce an error if you include a .lib with the following contents:

https://github.com/ARMmbed/mbed-os-experimental-ble-services/

The reason seems to be due to the IDE's desire to look for the master as opposed to the main branch. As a workaround, you can add a commit SHA to the URL, e.g.,

https://github.com/ARMmbed/mbed-os-experimental-ble-services/#76dc518594e37c9e4ee3445d22eee3ba6b046efc

@pan- Perhaps we should add this fix to the BLE_GattServer_ExperimentalServices example.

@16L-YT @idea--list Thanks for your questions and feedback.

@idea--list
Copy link

idea--list commented Jun 8, 2021

@noonfom
Made a new project in Mbed Studio imported this git and also fetched mbed-os-ble-utils.
Then copy pasted the example code found in BLE_GattServer_ExperimentalServices example you mentioned.

It compiles&runs on my Artemis Thing Plus. Using nRF Connect on my phone i can connect to the board and see those characteristics... but here stops all the goodness.

I can update manually the value of "Alert Level" characteristic but it never gets updated automatically as i get farther from the board and the RSSI changes. This makes no sense at all. Digging into the implementation i find this in LinkLossService.cpp :

void LinkLossService::onConnectionComplete(const ble::ConnectionCompleteEvent &event)
{
    if (event.getStatus() == BLE_ERROR_NONE) {
        stop_alert();
    }
}

Maybe i get it wrong but i guess this event should do the opposite and start monitoring RSSI and update the value of "Alert Level" on each timeout and i should be able to read that value by tapping the downward arrow inside nRF Connect.

While i also find this:

void LinkLossService::onDisconnectionComplete(const ble::DisconnectionCompleteEvent &event)
{
    AlertLevel level  = get_alert_level();
    if (_alert_handler != nullptr && event.getReason() == ble::disconnection_reason_t::CONNECTION_TIMEOUT &&
        level != AlertLevel::NO_ALERT && !_in_alert) {
        _in_alert = true;
        _alert_handler->on_alert_requested(level);
        if (_alert_timeout > std::chrono::milliseconds(0)) {
            _event_queue_handle = _event_queue.call_in(_alert_timeout, [this] { stop_alert(); });
        }
    }
}

I get a feeling the logic is messed up quite a bit as stop_alert() should be called when the peers disconnect and all the other stuff makes sense to be called when the connection is established.

As for "Current Time" characteristic: i can read the value hardcoded within source code via nRF connect, however i can not write a new value to this characteristic thus can not change the timestamp on the board despite the characteristic should be writeable. Again this makes me wonder as most embedded devices do not even have an RTC hardware, if they have, that tends to drift much more than time on a mobile phone (GSM-network keeps the local time accurate on phones). Mbed's software based RTC gets cleared when power is lost. So again would make sense if the phone could inject time into the embedded device via "Current Time" service, but the current implementation does not do that. At least i tried to write the current UNIX timestamp in any possible data type nRF Connect offers but none of them seem to work.
😵

@noonfom
Copy link

noonfom commented Jun 8, 2021

@idea--list The Link Loss Service (LLS) is a standard Bluetooth service defined in LLS_v1.0.1. It was implemented in #14 entirely in accordance with its specification, which does not specify how the Alert Level should be updated. The only requirement is that the Alert Level Characteristic have read/write properties. Admittedly, the BLE_GattServer_ExperimentalServices example only scratches the surface of what is possible with the service. The idea of updating the Alert Level in relation to changes in the RSSI is interesting and could be implemented at the application level.

The specification states that the alert should continue until one of the following events occur:

  • An implementation-specific timeout
  • User interaction on the device
  • Reconnection on the physical link

The first and third requirements are satisfied in onDisconnectionComplete and onConnectionComplete, respectively. The second requirement is not implemented and is perhaps open to interpretation.

On the Current Time Service, you should be able to write a new value to the Current Time Characteristic. Here's an example:

Example: Sat, 17 July 2021 12:34:56.

  1. Use the CurrentTime struct to determine the order of the data
  2. The first two bytes represent the year: 2021 = 0x07E5 (B0 = E5; B1 = 07). Think little endian
  3. Continue to create the following table:
B0 B1 B2 B3 B4 B5 B6 B7 B8 B9
0xE5 0x07 0x07 0x11 0x0C 0x22 0x38 0x06 0x00 0x00
  1. Using nRF Connect, write this data to the Current Time Characteristic as a series of individual bytes
  2. Observe the updated time: 17 July 2021, 12:34:56, Day of Week: Saturday

@idea--list
Copy link

@noonfom
Now i see: Bluetooth SIG has specified a ton of different blueprints for services and currently there are only a few of them implemented in the mbed-os-example-ble repo.
If i get it right, LinkLossService has been merged into Mbed OS core 2 months ago. If that is true, i would consider deleting that service from this experimental repo as that might lead to confusion.

Thanks for clarifying the data format of the CurrentTime characteristic, i could not have guessed that. Was not expecting this format as inside CurrentTimeService.h i found:

/**     * Set the time offset, i.e. the time in seconds beyond Epoch time.
*
* @param host_time Time in seconds according to your host.
* @param adjust_reason Bitmask using a combination of MANUAL_TIME_UPDATE, EXTERNAL_REFERENCE_TIME_UPDATE,
* CHANGE_OF_TIME_ZONE and CHANGE_OF_DST representing the reason for setting the time or zero if reason is unknown.
**/
void set_time(time_t host_time, uint8_t adjust_reason);

Thus i was expecting i shall input UNIXTIMESTAMP format into nRF Connect to update the current time on the board.

IMHO that would make more sense than the format used now as most webservices expose UNIXTIMESTAMP for machines.
I imagine concentrator devices with internet connection to grab time from such services and thus it would be easier to work with UNIXTIMESTAMPs. However the function could automatically detect if the current format or UNIXTIMESTAMP has been received and do some conversion if needed. Luckily these 2 formats differ quite much and are easily distinguishable, that way the function could consume 2 different formats thus not breaking anything on previous implementation while could make our lifes easier by accepting also UNIXTIMESTAMP.

@idea--list
Copy link

idea--list commented Jun 20, 2021

By the way recently i read the spec of the LinkLossService, but that really does not make much sense for me.
I mean BLE is a radio connection and thus it will just break sooner or later per se.
If i get it right the device running the GattServer (and thus LinkLossService) is the peripheral device and the client reading the characteristic values is the central device (in my case the phone running nRF Connect).

As i tried the implementation and went out of reach the characteristic value on my central device (phone with nRF Connect) did not change. Not even if i got back into range. I guess the value of Alert Level changes on the peripheral device then... which would allow us to blink some LEDs/ beep a speaker only on the peripheral device AFTER the connection has been lost (in which case i do not understand what is the difference between mild and high alert if the connection is already lost anyway...)

...but how could we send an alert to a remote system if the value does not change on the central device, which may provide the connection to a remote surveillance system?

IMHO also the name Alert Level is misleading as it does not allow for any preventive action (does anything only AFTER we have trouble). Something like Connection Lost would have been more intuitive and also a counter called Lost Times would have some sense, but it is already specified...

I think Mbed's implementation could extend the original spec sheet (or implement a more useful non-standard service) by adding 2 different RSSI threshold characteristics (both sides should be able to change those) and then the peripheral device running the GattServer should set mild alert or high alert level if those thresholds are surpassed and no alert otherwise. This would also allow PREVENTIVE action as well as remote monitoring.

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

No branches or pull requests

4 participants