Project Description
BLE to Ethernet Thin Gateway is the data collector to transmit the BLE(Bluetooth Low Energy) 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 transmits 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.
Hardware
- Data Sender : nRF51 DKx 1
- Data Collector : nRF51 DKx 1 / WIZ550io x 1 / xbee USB adapter
In order to check the debugging log and Ethernet function, connect the UART to USB module and WIZ550io as below.
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 files from Github, save them in the below path.
ble_app_hrs : /examples/ble_peripheral
ble_app_hrs_c_with_W5500 : /examples/ble_central
Data Sender
(1) Development Environment
Import Existing Project
- [import]-[Existing Projects into Workspace]
- Select root directory
/examples/ble_peripheral/ble_app_hrs/pca10028/s110/armgcc
(2)Upload SoftDevice
(3)Upload Application
Data Collector
(1) Development Environment
Import Existing Project
- [import]-[Existing Projects into Workspace]
- Select root directory
/examples/ble_central/ble_app_hrs_c_with_W5500/pca10028/s120/armgcc
(2) Upload Software
(3) Upload Application
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 transmitted 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 transmitted 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. Therefore, 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/”
In regard to use of dweet.io, you can learn it from the site ‘https://dweet.io/”
Comments