This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unique Characteristics for each peripheral using Multiperipheral SD

I am developing an application in which my device will have multiple android phones connected to it. Currently I have it working with one peripheral and after having upgraded to SDK13, I am looking at adding more peripherals.

My device has a service which contains 6 characteristics, 3 of these I would like the value to be shared between all devices, and 3 need to have unique values for each connection.

Having the shared characteristics is no problem, and it works just as shown in the multiperipheral example but, how can I get the values of the other 3 to be unique to each connection?

EDIT 29/06/17

image description

Above is an image to try and show what I'd like to achieve. The two peripheral devices are connected to my relay device. The 2 smart phones are connected to my relay device as centrals and they discover the relay device has an active_device characteristic and an active_device_data characteristic.

Each smart phone is able to set and read their own unique value of active_device, which tells the Relay device which peripheral that smart phone wants the data for. So, Smart phone one has set active_device to 1, to get the device_data from Peripheral devce 1 forwarded to it via the active_device_data characteristic, and the same for Smart phone 2 and peripheral device 2.

Currently I have not figured out how to allow smart phone one and two to choose different active devices. If I write a one to active_device using smart phone 1, then do a read with smart phone 2, it reads active_device as 1. Is there a way I can have different values of active_device for each connection?

Parents
  • I've had some time to revisit this issue and have since solved it. The key is to use the BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event.

    Enable read/write authorisation by setting

    attr_md.rd_auth    = 1;
    attr_md.wr_auth    = 1;
    

    in your ble_gatts_attr_md_t structure that is used when adding a characteristic. This will create a BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST when you read/write to that characteristic so, you can then edit the data that is returned. This is shown below

    static void on_rw_auth_request(my_service_t * p_my_service, ble_evt_t * p_ble_evt)
    {
        if (p_ble_evt->evt.gatts_evt.conn_handle == p_my_service->conn_handle)
        {
            // get the data from the actual event as the data is stored in a variable length array and accessing it via another ptr doesn't work
            ble_gatts_evt_rw_authorize_request_t * req = &p_ble_evt->evt.gatts_evt.params.authorize_request;
            
            if(req->type == BLE_GATTS_AUTHORIZE_TYPE_READ && 
              ( req->request.read.handle == p_my_service->active_device_handles.value_handle))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                auth_reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
                auth_reply.params.read.update = 1;
                auth_reply.params.read.offset = 0;
                auth_reply.params.read.len = sizeof(p_my_service->active_device);
                auth_reply.params.read.p_data = (uint8_t*)&p_my_service->active_device;
                sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
            }
            else if(req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE && 
              ( req->request.write.handle == p_my_service->active_device_handles.value_handle))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                memset(&auth_reply, 0, sizeof(auth_reply));
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                auth_reply.params.write.update = 1;
                
                if(req->request.write.len == sizeof(p_my_service->active_device))
                {
                    p_my_service->active_device = *(uint32_t*)req->request.write.data; 
                    auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                    auth_reply.params.write.offset = req->request.write.offset;
                    auth_reply.params.write.len = req->request.write.len;
                    auth_reply.params.write.p_data = (uint8_t *)&p_my_service->active_device;
                }
                else 
                {
                   auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
                }
                uint32_t err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
                if (p_my_service->evt_handler != NULL && auth_reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS)
                {
                    my_service_evt_t evt;
                    evt.evt_type = MY_SERVICE_EVT_ACTIVE_DEVICE_NEW_VALUE;
                    evt.data.active_device = p_my_service->active_device;
                    p_my_service->evt_handler(p_my_service, &evt);
                }
            }
            else if(req->type == BLE_GATTS_AUTHORIZE_TYPE_READ && 
              ( req->request.read.handle == p_my_service->battery_level_handles.value_handle))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                auth_reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
                auth_reply.params.read.update = 1;
                auth_reply.params.read.offset = 0;
                auth_reply.params.read.len = sizeof(p_my_service->last_battery_level);
                auth_reply.params.read.p_data = (uint8_t*)&p_my_service->last_battery_level;
                sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
            }
        }
    }
    
    
    void my_service_on_ble_evt(my_service_t * p_my_service, ble_evt_t * p_ble_evt)
    {
        if (p_my_service == NULL || p_ble_evt == NULL)
        {
            return;
        }
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                on_connect(p_my_service, p_ble_evt);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                on_disconnect(p_my_service, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_WRITE:
                on_write(p_my_service, p_ble_evt);
                break;
            case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
                on_rw_auth_request(p_my_service, p_ble_evt);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
Reply
  • I've had some time to revisit this issue and have since solved it. The key is to use the BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event.

    Enable read/write authorisation by setting

    attr_md.rd_auth    = 1;
    attr_md.wr_auth    = 1;
    

    in your ble_gatts_attr_md_t structure that is used when adding a characteristic. This will create a BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST when you read/write to that characteristic so, you can then edit the data that is returned. This is shown below

    static void on_rw_auth_request(my_service_t * p_my_service, ble_evt_t * p_ble_evt)
    {
        if (p_ble_evt->evt.gatts_evt.conn_handle == p_my_service->conn_handle)
        {
            // get the data from the actual event as the data is stored in a variable length array and accessing it via another ptr doesn't work
            ble_gatts_evt_rw_authorize_request_t * req = &p_ble_evt->evt.gatts_evt.params.authorize_request;
            
            if(req->type == BLE_GATTS_AUTHORIZE_TYPE_READ && 
              ( req->request.read.handle == p_my_service->active_device_handles.value_handle))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                auth_reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
                auth_reply.params.read.update = 1;
                auth_reply.params.read.offset = 0;
                auth_reply.params.read.len = sizeof(p_my_service->active_device);
                auth_reply.params.read.p_data = (uint8_t*)&p_my_service->active_device;
                sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
            }
            else if(req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE && 
              ( req->request.write.handle == p_my_service->active_device_handles.value_handle))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                memset(&auth_reply, 0, sizeof(auth_reply));
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                auth_reply.params.write.update = 1;
                
                if(req->request.write.len == sizeof(p_my_service->active_device))
                {
                    p_my_service->active_device = *(uint32_t*)req->request.write.data; 
                    auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                    auth_reply.params.write.offset = req->request.write.offset;
                    auth_reply.params.write.len = req->request.write.len;
                    auth_reply.params.write.p_data = (uint8_t *)&p_my_service->active_device;
                }
                else 
                {
                   auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH;
                }
                uint32_t err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
                if (p_my_service->evt_handler != NULL && auth_reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS)
                {
                    my_service_evt_t evt;
                    evt.evt_type = MY_SERVICE_EVT_ACTIVE_DEVICE_NEW_VALUE;
                    evt.data.active_device = p_my_service->active_device;
                    p_my_service->evt_handler(p_my_service, &evt);
                }
            }
            else if(req->type == BLE_GATTS_AUTHORIZE_TYPE_READ && 
              ( req->request.read.handle == p_my_service->battery_level_handles.value_handle))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                auth_reply.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
                auth_reply.params.read.update = 1;
                auth_reply.params.read.offset = 0;
                auth_reply.params.read.len = sizeof(p_my_service->last_battery_level);
                auth_reply.params.read.p_data = (uint8_t*)&p_my_service->last_battery_level;
                sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
            }
        }
    }
    
    
    void my_service_on_ble_evt(my_service_t * p_my_service, ble_evt_t * p_ble_evt)
    {
        if (p_my_service == NULL || p_ble_evt == NULL)
        {
            return;
        }
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                on_connect(p_my_service, p_ble_evt);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                on_disconnect(p_my_service, p_ble_evt);
                break;
    
            case BLE_GATTS_EVT_WRITE:
                on_write(p_my_service, p_ble_evt);
                break;
            case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
                on_rw_auth_request(p_my_service, p_ble_evt);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
Children
No Data
Related