BLE to Ethernet Thin Gateway

details

BLE to Ethernet Thin Gateway is the data collecor to transmit the BLE(Bluetooth Low Eneregy) data to a cloud server through Ethernet.

System Configuration

The whole system is composed of Data Sender, Data Collector and Cloud Server. Data Sender measures the heart rate and transmits to Data Collector. For software of Data Sender, we use the ble_app_hrs_s110 example code provided by Nordic. We will use virtual data for heart rate and battery level.

Data Collector collects the data transmitted by Data Sender, and tranmits the collected data to the cloud service. (In this posting, we will use the “dweet.io” service). For the software of Data Collector, we combines Nordic’s ble_app_hrs_c_s120 examples and W5500 io libraries.

ble_gateway-1

Hardware

In order to check the debugging log and Ethernet function, connect the UART to USB module and WIZ550io as below.

ble_gateway-2

ble_gateway-3

Software

Download nRF51 SDK by clicking below link

https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v10.x.x/

You can get the Eclipse Project and source code from Github Repository. After downloading the fiels from Github, save them in the below path.

ble_app_hrs : <SDK>/examples/ble_peripheral
ble_app_hrs_c_with_W5500 : <SDK>/examples/ble_central

Data Sender

(1) Development Enviroment

Import Existing Project

  • [import]-[Existing Projects into Workspace]
  • Select root directory
<SDK>/examples/ble_peripheral/ble_app_hrs/pca10028/s110/armgcc

 

(2)Upload SoftDevice

ble_gateway-4

(3)Upload Application

ble_gateway-5

 

Data Collector

(1) Development Enviroment

Import Existing Project

  • [import]-[Existing Projects into Workspace]
  • Select root directory
<SDK>/examples/ble_central/ble_app_hrs_c_with_W5500/pca10028/s120/armgcc

(2) Upload Software

ble_gateway-6

(3) Upload Application

ble_gateway_7

APP_TIMER_DEF(m_publish_data_timer_id);
 
int main(void)
{
    bool erase_bonds;
    uint32_t err_code;
 
    // Initialize.
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
 
    buttons_leds_init(&erase_bonds);
    uart_init();
    printf("Heart rate collector example\r\n");
 
    spi0_master_init();
    user_ethernet_init();
 
    app_mailbox_create(&hr_data_mailbox);
    app_mailbox_create(&bas_data_mailbox);
 
    ble_stack_init();
    device_manager_init(erase_bonds);
    db_discovery_init();
 
    hrs_c_init();
    bas_c_init();
 
 
    // Start scanning for peripherals and initiate connection
    // with devices that advertise Heart Rate UUID.
    scan_start();
 
    err_code = app_timer_create(&m_publish_data_timer_id, APP_TIMER_MODE_REPEATED, publish_data_handler);
    APP_ERROR_CHECK(err_code);
    err_code = app_timer_start(m_publish_data_timer_id,PUBLISH_INTERVAL,NULL);
    APP_ERROR_CHECK(err_code);
 
 
    for (;; )
    {
    	power_manage();
    }
}
  • 1~2 : Set Timer Interval (300ms) to publish to cloud service & Initialize
  • 16 : Initialize the SPI Interface to control WIZ550io
  • 17 : Initialize the Ethernet (IP address and network configuration)
  • 19 ~ 20 : Initialize the mail box (If the HR event and BAS event occurs, the values are saved into a mailbox)
  • 22 ~ 24 : Initialize BLE Central Stack.
  • 26 ~ 27 : Initialize HR(Heart Rate) and BAS(Battery) collector
  • 32 : BLE Peripheral Scan and Connection Scan
  • 34 ~ 37 : Create Publish Timer and Start
#define HR_EVT_MAILBOX_QUEUE_SIZE     10
#define BAS_EVT_MAILBOX_QUEUE_SIZE    10
 
typedef struct
{
    uint16_t evt_data;
    uint16_t dummy_data;
}hrs_c_evt_data;
 
typedef struct
{
    uint16_t battery_level;
    uint16_t dummy_data;
}bas_c_evt_data;
 
APP_MAILBOX_DEF(hr_data_mailbox, HR_EVT_MAILBOX_QUEUE_SIZE, sizeof(hrs_c_evt_data));
APP_MAILBOX_DEF(bas_data_mailbox, BAS_EVT_MAILBOX_QUEUE_SIZE, sizeof(bas_c_evt_data));
 
static any_port = 50000;
uint8_t dweet_io_ip[4] = {54,172,56,193};
uint16_t dest_port = 80;
#define THING         "Ble2Eth"
#define HEART_RATE     "heart_rate"
#define BATTERY     "battery"
  • 1 ~ 2 : Set Mailbox QUEUE SIZE
  • 4 ~ 14 : Initialize Hear rate and Batter level data format
  • 16 ~ 17 : Initialize Mailbox
  • 19 ~ 24 : Information to send the Data to dweet.io
static void publish_data_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    uint8_t sn = 0;
    uint32_t ret;
    uint8_t eth_data[512];
    hrs_c_evt_data hr_data;
    bas_c_evt_data batt_data;
 
    // Connect to server
    if(app_mailbox_length_get(&hr_data_mailbox) || app_mailbox_length_get(&bas_data_mailbox))
    {
        if(getSn_SR(sn) != SOCK_CLOSED)
        {
            close(sn);
            disconnect(sn);
        }
        while(getSn_SR(sn) != SOCK_CLOSED);
 
        if( ret = socket(sn, Sn_MR_TCP, any_port++, 0x00) != sn )
        {
            APPL_LOG("[PUBLISH]: Socket open failed, reason %d\r\n", ret);
            return;
        }
 
        if( ret = connect(sn, dweet_io_ip, dest_port) != SOCK_OK )
        {
            APPL_LOG("[PUBLISH]: Socket Connection failed, reason %d\r\n", ret);
            return;
        }
    }
    else    return;
 
    // Publish collected data
    while( app_mailbox_length_get(&hr_data_mailbox) != 0)
    {
        app_mailbox_get(&hr_data_mailbox,&hr_data);
        sprintf(eth_data,"GET /dweet/for/%s?%s=%d HTTP/1.1\r\nHost: dweet. io\r\n\r\n",THING,HEART_RATE,hr_data.evt_data);
        send(sn,eth_data,strlen((uint8_t*)eth_data));
    }
 
    while( app_mailbox_length_get(&bas_data_mailbox) != 0)
    {
        app_mailbox_get(&bas_data_mailbox,&batt_data);
        sprintf(eth_data,"GET /dweet/for/%s?%s=%d HTTP/1.1\r\nHost: dweet. io\r\n\r\n",THING,BATTERY,batt_data.battery_level);
        send(sn,eth_data,strlen((uint8_t*)eth_data));
    }
 
    close(sn);
    disconnect(sn);
}
  • publish_data_handler’ is performed every 300ms to establish TCP connection with dweet.io and transmits the batter data and heart rate data.
  • When ‘publish_data_hander’ is performed, mailbox data is transmited via Ethernet
/**@brief Heart Rate Collector Handler.
 */
static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt)
{
    uint32_t err_code;
    uint32_t test;
    hrs_c_evt_data hrs_c_data;
 
    switch (p_hrs_c_evt->evt_type)
    {
        case BLE_HRS_C_EVT_DISCOVERY_COMPLETE:
 
            // Heart rate service discovered. Enable notification of Heart Rate Measurement.
            err_code = ble_hrs_c_hrm_notif_enable(p_hrs_c);
            APP_ERROR_CHECK(err_code);
 
            printf("Heart rate service discovered \r\n");
            break;
 
        case BLE_HRS_C_EVT_HRM_NOTIFICATION:
        {
            APPL_LOG("[APPL]: HR Measurement received %d \r\n", p_hrs_c_evt->params.hrm.hr_value);
            hrs_c_data.evt_data = p_hrs_c_evt->params.hrm.hr_value;
            app_mailbox_put(&hr_data_mailbox,&hrs_c_data);
            break;
        }
 
        default:
            break;
    }
}
 
 
/**@brief Battery levelCollector Handler.
 */
static void bas_c_evt_handler(ble_bas_c_t * p_bas_c, ble_bas_c_evt_t * p_bas_c_evt)
{
    uint32_t err_code;
    bas_c_evt_data bas_data;
 
    switch (p_bas_c_evt->evt_type)
    {
        case BLE_BAS_C_EVT_DISCOVERY_COMPLETE:
            // Batttery service discovered. Enable notification of Battery Level.
            APPL_LOG("[APPL]: Battery Service discovered. \r\n");
 
            APPL_LOG("[APPL]: Reading battery level. \r\n");
 
            err_code = ble_bas_c_bl_read(p_bas_c);
            APP_ERROR_CHECK(err_code);
 
 
            APPL_LOG("[APPL]: Enabling Battery Level Notification. \r\n");
            err_code = ble_bas_c_bl_notif_enable(p_bas_c);
            APP_ERROR_CHECK(err_code);
 
            break;
 
        case BLE_BAS_C_EVT_BATT_NOTIFICATION:
        {
            APPL_LOG("[APPL]: Battery Level received %d %%\r\n", p_bas_c_evt->params.battery_level);
            bas_data.battery_level = p_bas_c_evt->params.battery_level;
            app_mailbox_put(&bas_data_mailbox,&bas_data);
            break;
        }
 
        case BLE_BAS_C_EVT_BATT_READ_RESP:
        {
            APPL_LOG("[APPL]: Battery Level Read as %d %%\r\n", p_bas_c_evt->params.battery_level);
            break;
        }
 
        default:
            break;
    }
}
  • 20 ~ 26 : When the heart rate notification event occurs, data is saved in the mailbox
  • 59 ~ 65 : When the battery notification event occurs, data is saved in the mailbox
  • The data in the mailbox is transmited viz Ethernet when ‘publish_data_handler’ is performed

 

To Check the Data at the Cloud Service (dweet.io)

In the free version service of dweet.io, the data is not saved in the database. Therfore, you can check the data on the web browser without specific configuration or key. Just input the URL as like ‘https://dweet.io/follow/Ble2Eth’. Just add the name of THING that defined above code at the end of ‘https://dweet.io/follow/”

ble_gateway-8

In regard to use of dweet.io, you can learn it from the site ‘https://dweet.io/

BLE to Ethernet Thin Gateway is the data collecor to transmit the BLE(Bluetooth Low Eneregy) data to a cloud server through Ethernet.

System Configuration

The whole system is composed of Data Sender, Data Collector and Cloud Server. Data Sender measures the heart rate and transmits to Data Collector. For software of Data Sender, we use the ble_app_hrs_s110 example code provided by Nordic. We will use virtual data for heart rate and battery level.

Data Collector collects the data transmitted by Data Sender, and tranmits the collected data to the cloud service. (In this posting, we will use the “dweet.io” service). For the software of Data Collector, we combines Nordic’s ble_app_hrs_c_s120 examples and W5500 io libraries.

ble_gateway-1

Hardware

In order to check the debugging log and Ethernet function, connect the UART to USB module and WIZ550io as below.

ble_gateway-2

ble_gateway-3

Software

Download nRF51 SDK by clicking below link

https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v10.x.x/

You can get the Eclipse Project and source code from Github Repository. After downloading the fiels from Github, save them in the below path.

ble_app_hrs : <SDK>/examples/ble_peripheral
ble_app_hrs_c_with_W5500 : <SDK>/examples/ble_central

Data Sender

(1) Development Enviroment

Import Existing Project

  • [import]-[Existing Projects into Workspace]
  • Select root directory
<SDK>/examples/ble_peripheral/ble_app_hrs/pca10028/s110/armgcc

 

(2)Upload SoftDevice

ble_gateway-4

(3)Upload Application

ble_gateway-5

 

Data Collector

(1) Development Enviroment

Import Existing Project

  • [import]-[Existing Projects into Workspace]
  • Select root directory
<SDK>/examples/ble_central/ble_app_hrs_c_with_W5500/pca10028/s120/armgcc

(2) Upload Software

ble_gateway-6

(3) Upload Application

ble_gateway_7

APP_TIMER_DEF(m_publish_data_timer_id);
 
int main(void)
{
    bool erase_bonds;
    uint32_t err_code;
 
    // Initialize.
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
 
    buttons_leds_init(&erase_bonds);
    uart_init();
    printf("Heart rate collector example\r\n");
 
    spi0_master_init();
    user_ethernet_init();
 
    app_mailbox_create(&hr_data_mailbox);
    app_mailbox_create(&bas_data_mailbox);
 
    ble_stack_init();
    device_manager_init(erase_bonds);
    db_discovery_init();
 
    hrs_c_init();
    bas_c_init();
 
 
    // Start scanning for peripherals and initiate connection
    // with devices that advertise Heart Rate UUID.
    scan_start();
 
    err_code = app_timer_create(&m_publish_data_timer_id, APP_TIMER_MODE_REPEATED, publish_data_handler);
    APP_ERROR_CHECK(err_code);
    err_code = app_timer_start(m_publish_data_timer_id,PUBLISH_INTERVAL,NULL);
    APP_ERROR_CHECK(err_code);
 
 
    for (;; )
    {
    	power_manage();
    }
}
  • 1~2 : Set Timer Interval (300ms) to publish to cloud service & Initialize
  • 16 : Initialize the SPI Interface to control WIZ550io
  • 17 : Initialize the Ethernet (IP address and network configuration)
  • 19 ~ 20 : Initialize the mail box (If the HR event and BAS event occurs, the values are saved into a mailbox)
  • 22 ~ 24 : Initialize BLE Central Stack.
  • 26 ~ 27 : Initialize HR(Heart Rate) and BAS(Battery) collector
  • 32 : BLE Peripheral Scan and Connection Scan
  • 34 ~ 37 : Create Publish Timer and Start
#define HR_EVT_MAILBOX_QUEUE_SIZE     10
#define BAS_EVT_MAILBOX_QUEUE_SIZE    10
 
typedef struct
{
    uint16_t evt_data;
    uint16_t dummy_data;
}hrs_c_evt_data;
 
typedef struct
{
    uint16_t battery_level;
    uint16_t dummy_data;
}bas_c_evt_data;
 
APP_MAILBOX_DEF(hr_data_mailbox, HR_EVT_MAILBOX_QUEUE_SIZE, sizeof(hrs_c_evt_data));
APP_MAILBOX_DEF(bas_data_mailbox, BAS_EVT_MAILBOX_QUEUE_SIZE, sizeof(bas_c_evt_data));
 
static any_port = 50000;
uint8_t dweet_io_ip[4] = {54,172,56,193};
uint16_t dest_port = 80;
#define THING         "Ble2Eth"
#define HEART_RATE     "heart_rate"
#define BATTERY     "battery"
  • 1 ~ 2 : Set Mailbox QUEUE SIZE
  • 4 ~ 14 : Initialize Hear rate and Batter level data format
  • 16 ~ 17 : Initialize Mailbox
  • 19 ~ 24 : Information to send the Data to dweet.io
static void publish_data_handler(void * p_context)
{
    UNUSED_PARAMETER(p_context);
    uint8_t sn = 0;
    uint32_t ret;
    uint8_t eth_data[512];
    hrs_c_evt_data hr_data;
    bas_c_evt_data batt_data;
 
    // Connect to server
    if(app_mailbox_length_get(&hr_data_mailbox) || app_mailbox_length_get(&bas_data_mailbox))
    {
        if(getSn_SR(sn) != SOCK_CLOSED)
        {
            close(sn);
            disconnect(sn);
        }
        while(getSn_SR(sn) != SOCK_CLOSED);
 
        if( ret = socket(sn, Sn_MR_TCP, any_port++, 0x00) != sn )
        {
            APPL_LOG("[PUBLISH]: Socket open failed, reason %d\r\n", ret);
            return;
        }
 
        if( ret = connect(sn, dweet_io_ip, dest_port) != SOCK_OK )
        {
            APPL_LOG("[PUBLISH]: Socket Connection failed, reason %d\r\n", ret);
            return;
        }
    }
    else    return;
 
    // Publish collected data
    while( app_mailbox_length_get(&hr_data_mailbox) != 0)
    {
        app_mailbox_get(&hr_data_mailbox,&hr_data);
        sprintf(eth_data,"GET /dweet/for/%s?%s=%d HTTP/1.1\r\nHost: dweet. io\r\n\r\n",THING,HEART_RATE,hr_data.evt_data);
        send(sn,eth_data,strlen((uint8_t*)eth_data));
    }
 
    while( app_mailbox_length_get(&bas_data_mailbox) != 0)
    {
        app_mailbox_get(&bas_data_mailbox,&batt_data);
        sprintf(eth_data,"GET /dweet/for/%s?%s=%d HTTP/1.1\r\nHost: dweet. io\r\n\r\n",THING,BATTERY,batt_data.battery_level);
        send(sn,eth_data,strlen((uint8_t*)eth_data));
    }
 
    close(sn);
    disconnect(sn);
}
  • publish_data_handler’ is performed every 300ms to establish TCP connection with dweet.io and transmits the batter data and heart rate data.
  • When ‘publish_data_hander’ is performed, mailbox data is transmited via Ethernet
/**@brief Heart Rate Collector Handler.
 */
static void hrs_c_evt_handler(ble_hrs_c_t * p_hrs_c, ble_hrs_c_evt_t * p_hrs_c_evt)
{
    uint32_t err_code;
    uint32_t test;
    hrs_c_evt_data hrs_c_data;
 
    switch (p_hrs_c_evt->evt_type)
    {
        case BLE_HRS_C_EVT_DISCOVERY_COMPLETE:
 
            // Heart rate service discovered. Enable notification of Heart Rate Measurement.
            err_code = ble_hrs_c_hrm_notif_enable(p_hrs_c);
            APP_ERROR_CHECK(err_code);
 
            printf("Heart rate service discovered \r\n");
            break;
 
        case BLE_HRS_C_EVT_HRM_NOTIFICATION:
        {
            APPL_LOG("[APPL]: HR Measurement received %d \r\n", p_hrs_c_evt->params.hrm.hr_value);
            hrs_c_data.evt_data = p_hrs_c_evt->params.hrm.hr_value;
            app_mailbox_put(&hr_data_mailbox,&hrs_c_data);
            break;
        }
 
        default:
            break;
    }
}
 
 
/**@brief Battery levelCollector Handler.
 */
static void bas_c_evt_handler(ble_bas_c_t * p_bas_c, ble_bas_c_evt_t * p_bas_c_evt)
{
    uint32_t err_code;
    bas_c_evt_data bas_data;
 
    switch (p_bas_c_evt->evt_type)
    {
        case BLE_BAS_C_EVT_DISCOVERY_COMPLETE:
            // Batttery service discovered. Enable notification of Battery Level.
            APPL_LOG("[APPL]: Battery Service discovered. \r\n");
 
            APPL_LOG("[APPL]: Reading battery level. \r\n");
 
            err_code = ble_bas_c_bl_read(p_bas_c);
            APP_ERROR_CHECK(err_code);
 
 
            APPL_LOG("[APPL]: Enabling Battery Level Notification. \r\n");
            err_code = ble_bas_c_bl_notif_enable(p_bas_c);
            APP_ERROR_CHECK(err_code);
 
            break;
 
        case BLE_BAS_C_EVT_BATT_NOTIFICATION:
        {
            APPL_LOG("[APPL]: Battery Level received %d %%\r\n", p_bas_c_evt->params.battery_level);
            bas_data.battery_level = p_bas_c_evt->params.battery_level;
            app_mailbox_put(&bas_data_mailbox,&bas_data);
            break;
        }
 
        case BLE_BAS_C_EVT_BATT_READ_RESP:
        {
            APPL_LOG("[APPL]: Battery Level Read as %d %%\r\n", p_bas_c_evt->params.battery_level);
            break;
        }
 
        default:
            break;
    }
}
  • 20 ~ 26 : When the heart rate notification event occurs, data is saved in the mailbox
  • 59 ~ 65 : When the battery notification event occurs, data is saved in the mailbox
  • The data in the mailbox is transmited viz Ethernet when ‘publish_data_handler’ is performed

 

To Check the Data at the Cloud Service (dweet.io)

In the free version service of dweet.io, the data is not saved in the database. Therfore, you can check the data on the web browser without specific configuration or key. Just input the URL as like ‘https://dweet.io/follow/Ble2Eth’. Just add the name of THING that defined above code at the end of ‘https://dweet.io/follow/”

ble_gateway-8

In regard to use of dweet.io, you can learn it from the site ‘https://dweet.io/

COMMENTS

Please Login to comment
  Subscribe  
Notify of