This project adds Bluetooth central connectivity to Azure Sphere in a extendable fashion allowing multiple peripherals to be connected to Azure and hence to the Cloud. The reuse of different projects and specific additional code allow it to be adapted quickly by the community opening the possibility for new IOT devices.
Hardware.The BLE connectivity is provided by Nordic nRF52832. The nordic MCU is controlled by Azure Sphere through the serial port, hardware control flow is used, so there is needed a serial port with CTS and RTS lines. The Azure Sphere device also controls the Nordic MCU reset line.
Connections to the nRF52 Development Kit are shown below.
Azure Sphere uses the PMOD connector, the reason is because uart port on click board connectors don't provide the control lines. You can solder a right angle header onto the pmod or even just a straight header as shown below.
The PMOD connector is clearly identified on Top silkscreen, well at least the side where the UART connection pins are, just remember to connect Tx <-> Rx and CTS <-> RTS. The reset line is placed on GPIO1. The pinout is shown below.
Additional hardware is needed to test the solution, as the Azure Sphere + nRF52 DK would act as the central device. Possibilities are endless but for development and testing purposes we are using another DK from Nordic (either nRF52833 or Thingy) that will be programmed as a BLE peripheral.
The software is based on the Wifi Setup and device control over BLE example located on the azure-sphere-samples github repository. The example allows to configure a Wifi connection among other things via Bluetooth, but the Nordic device acts as a peripheral, configuration is done via a central device such as smartphone or computer.
In order to keep the peripheral connectivity, a multi role device has to be implemented, which is possible to do for Nordic SDK 15.2.0. In fact, there is a multi role implementation in the Nordic Playground called nrf52-ble-multi-link-multi-role which I have used for this purpose.
Porting from one application to another is not just a copy and paste, there are a few things to be aware of if you don't want to spend hours looking at compiler errors.
I have used Segger Embedded Studio for the code modifications as it was already used on the projects and it's free for non-commercial use, you can download your copy here.
The aggregator example implements a simple command protocol to exchange data between the central device (only one such a smartphone) and the peripheral devices. But more importantly is the internal management that allow to address up to 19 peripheral devices In this case we are trying to control those devices but from our Azure Sphere.
The NUS (Nordic UART Service) is used to send and get the commands from Central device on the aggregator, i.e.
static volatile uint32_t agg_cmd_received = 0;
static uint8_t agg_cmd[32];
static void agg_cfg_service_data_handler(ble_agg_cfg_service_evt_t * p_evt)
{
if (p_evt->type == BLE_AGG_CFG_SERVICE_EVT_RX_DATA)
{
//while(agg_cmd_received != 0);
if(agg_cmd_received == 0)
{
agg_cmd_received = p_evt->params.rx_data.p_data[0];
memcpy(agg_cmd, &p_evt->params.rx_data.p_data[1], p_evt->params.rx_data.le ngth);
}
else NRF_LOG_WARNING("AGG CMD OVERFLOW!!\r\n");
}
}
This need to change to the UART direct physical connection to Azure Sphere. I have used the existing BLE control message Category Id on the existing device control via BLE project, that is,
A new Control Request Id can be created to process new commands in blecontrol_message_protocol_defs.h
/// <summary>
/// Request ID for Set LED ON/OFF ALL on BLE Bonds Request message.
/// </summary>
static const MessageProtocol_RequestId BleControlMessageProtocol_ProcessAzureCmdsRequestId =
0x0005;
A new handler is created and assigned in function ble_control_message_protocol_init
m_process_azure_cmd_handler = process_azure_cmd_handler;
...
message_protocol_register_request_handler(MessageProtocol_BleControlCategoryId,
BleControlMessageProtocol_ProcessAzureCmdsRequestId,
ble_control_process_app_commands_request_handler);
The new handler is registered in main by doing
ble_control_message_protocol_init(init_ble_stack, \
set_ble_passkey, \
ble_start_advertising_handler, \
delete_bonds, \
process_app_commands);
process_app_commands function does a few commands and it can be extended as well as the application requires.
The underlying protocol is not strictly defined as the Wifi BLE example, so in this case we cannot have any length in message as it has to be a multiple of 4 bytes, i.e.
if we have less data we need to pad with zeros.
There are commands directly issue by the Azure "Central" application such as to change led color of a peripheral, but whenever there is some notification from the peripherals or a change in the Bluetooth central connection state, the Nordic MCU has to generate an event, this way we keep the same scheme of the original protocol.
In order to reuse the aggregator code to achieve the above, a few things were done. The aggregator data might be any stack state such as a new connection or disconnection, this will include information of the device such as the name, services, etc. Fortunately, the aggregator data is written to a circular buffer so it's possible to change how the data it's transferred. In this case we need to change from using NUS to our physical UART port, but also encapsulate the data into our protocol.
The event is generated by calling
ble_control_message_protocol_send_ble_client_event();
This is mostly done after some call to any function that add data to the buffer, for example when a connection or disconnection happens, the functions
// Notify the aggregator service
app_aggregator_on_central_connect(p_gap_evt, &m_device_being_connected_info);
or
// Notify aggregator service
app_aggregator_on_central_disconnect(p_gap_evt);
are called respectively. After those calls, data will be available in the buffer and the event can be generated, afterwards the MT3620 upon processing the event will generate a Request to get the data.
On the Azure Sphere side, we need to attach the event, the event will be used to send the request and receive the response. I could not get access to any source for the client device of the aggregator example such as the android application, which only an apk is available. Nonetheless there are only four commands implemented and it can be inferred from reading the Nordic application.
Here is how it looks the response handler on the azure sphere device.
static void GetAggregatorDataResponseHandler(MessageProtocol_CategoryId categoryId,
MessageProtocol_RequestId requestId,
const uint8_t* data, size_t dataSize,
MessageProtocol_ResponseResult result, bool timedOut)
{
if (timedOut) {
Log_Debug("ERROR: Timed out waiting for \"Initialize BLE Device\" response.\n");
ChangeBleProtocolState(BleControlMessageProtocolState_Error);
return;
}
if (result != 0) {
Log_Debug("ERROR: \"Initialize BLE Device\" failed with error code: %u.\n", re sult);
ChangeBleProtocolState(BleControlMessageProtocolState_Error);
return;
}
// Handle data depending on message
switch (data[0]) {
case AGG_BLE_LINK_CONNECTED:
handleAggregatorConnection();
break;
case AGG_BLE_LINK_DISCONNECTED:
handleAggregatorDisconnect();
break;
case AGG_BLE_LINK_DATA_UPDATE:
//Not implemented
break;
case AGG_BLE_LED_BUTTON_PRESSED:
//
break;
default:
break;
}
}
The details of the implementations can be found in github for both azure and nordic devices.
Conclusion.This is just a starting point for a big project with azure Sphere as a Bluetooth Hub. It's a good place to start as the project is simple but not simpler, it requires a lot of trimming to handle the devices. We haven't exposed the data collected from BLE peripherals to the Azure cloud, in first place because there is a lot of work to do to organize the data effectively and be able to instruct the Azure Sphere what data to upload to cloud.
An example would be a heart rate monitor for an elderly person at home. The heart rate measurements or any other health indicative collected by the BLE device will be transmitted to the Azure sphere, some data might or not be uploaded to the cloud. For instance, a healthy individual might have an abnormal heart rate at given times, those times and rates will be upload more frequently. This kind of decisions has to be implemented either from the high level application on the cloud and downloaded to azure sphere by internet connectivity.
Comments