Skip to content

Commit 697bbca

Browse files
committed
added central_custom_hrm
add BLECLientCharacteristic isValid() and read 8,16, 32 bit
1 parent 2ca6a28 commit 697bbca

File tree

5 files changed

+239
-10
lines changed

5 files changed

+239
-10
lines changed

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
- Added experimental (work in progress) BLE Homekit
3232
- Enhanced bleuart to work with larger MTU
3333
- Partially support data length extension
34+
- Added BLECLientCharacteristic isValid() and read 8,16, 32 bit
35+
- Added cental_custom_hrm example for how to use client service and characteristic
3436

3537
## Bug Fixs
3638

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*********************************************************************
2+
This is an example for our nRF52 based Bluefruit LE modules
3+
4+
Pick one up today in the adafruit shop!
5+
6+
Adafruit invests time and resources providing this open source code,
7+
please support Adafruit and open-source hardware by purchasing
8+
products from Adafruit!
9+
10+
MIT license, check LICENSE for more information
11+
All text above, and the splash screen below must be included in
12+
any redistribution
13+
*********************************************************************/
14+
15+
/* This sketch show how to use BLEClientService and BLEClientCharacteristic
16+
* to implement a custom client that is used to talk with Gatt server on
17+
* peripheral.
18+
*
19+
* Note: you will need another feather52 running peripheral/custom_HRM sketch
20+
* to test with.
21+
*/
22+
23+
#include <bluefruit.h>
24+
25+
/* HRM Service Definitions
26+
* Heart Rate Monitor Service: 0x180D
27+
* Heart Rate Measurement Char: 0x2A37 (Mandatory)
28+
* Body Sensor Location Char: 0x2A38 (Optional)
29+
*/
30+
31+
BLEClientService clientHRM(UUID16_SVC_HEART_RATE);
32+
BLEClientCharacteristic clientMeasurement (UUID16_CHR_HEART_RATE_MEASUREMENT);
33+
BLEClientCharacteristic clientSensorLocation(UUID16_CHR_BODY_SENSOR_LOCATION);
34+
35+
void setup()
36+
{
37+
Serial.begin(115200);
38+
39+
Serial.println("Bluefruit52 Central Custom HRM Example");
40+
Serial.println("--------------------------------------\n");
41+
42+
// Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
43+
// SRAM usage required by SoftDevice will increase dramatically with number of connections
44+
Bluefruit.begin(0, 1);
45+
46+
Bluefruit.setName("Bluefruit52 Central");
47+
48+
// Initialize HRM client
49+
clientHRM.begin();
50+
51+
// Initialize client characteristics of HRM.
52+
// Note: Client Char will be added to the most recent Service that is initialized.
53+
clientSensorLocation.begin();
54+
55+
clientMeasurement.begin();
56+
clientMeasurement.setNotifyCallback(hrm_notify_callback); // set up callback for receiving measurement
57+
58+
// Increase Blink rate to different from PrPh advertising mode
59+
Bluefruit.setConnLedInterval(250);
60+
61+
// Callbacks for Central
62+
Bluefruit.Central.setConnectCallback(connect_callback);
63+
Bluefruit.Central.setDisconnectCallback(disconnect_callback);
64+
65+
/* Start Central Scanning
66+
* - Enable auto scan if disconnected
67+
* - Interval = 100 ms, window = 80 ms
68+
* - Don't use active scan
69+
* - Filter only accept HRM service
70+
* - Start(timeout) with timeout = 0 will scan forever (until connected)
71+
*/
72+
Bluefruit.Scanner.setRxCallback(scan_callback);
73+
Bluefruit.Scanner.restartOnDisconnect(true);
74+
Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
75+
Bluefruit.Scanner.filterUuid(clientHRM.uuid);
76+
Bluefruit.Scanner.useActiveScan(false);
77+
Bluefruit.Scanner.start(0); // // 0 = Don't stop scanning after n seconds
78+
}
79+
80+
void loop()
81+
{
82+
// do nothing
83+
}
84+
85+
/**
86+
* Callback invoked when scanner pick up an advertising data
87+
* @param report Structural advertising data
88+
*/
89+
void scan_callback(ble_gap_evt_adv_report_t* report)
90+
{
91+
// Connect to device with HRM service in advertising
92+
Bluefruit.Central.connect(report);
93+
}
94+
95+
/**
96+
* Callback invoked when an connection is established
97+
* @param conn_handle
98+
*/
99+
void connect_callback(uint16_t conn_handle)
100+
{
101+
Serial.println("Connected");
102+
Serial.print("Discovering HRM Service ... ");
103+
104+
// If HRM is not found, disconnect and return
105+
if ( !clientHRM.discover(conn_handle) )
106+
{
107+
Serial.println("Found NONE");
108+
109+
// disconect since we couldn't find HRM service
110+
Bluefruit.Central.disconnect(conn_handle);
111+
112+
return;
113+
}
114+
115+
// HRM is found
116+
Serial.println("Found it");
117+
Serial.println("Discovering Measurement and Body location characteristic ... ");
118+
119+
uint8_t num_found_chr = Bluefruit.Discovery.discoverCharacteristic(conn_handle, clientMeasurement, clientSensorLocation);
120+
121+
Serial.print("Found ");
122+
Serial.print(num_found_chr);
123+
Serial.println("Characteristics");
124+
125+
// Measurement chr is mandatory, if it is not found (valid), then disconnect
126+
if ( !clientMeasurement.isValid() )
127+
{
128+
Serial.println("Measurement characteristic not found");
129+
Bluefruit.Central.disconnect(conn_handle);
130+
131+
return;
132+
}
133+
134+
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml
135+
// Body Sensor Location is optional, print its location (in text) if present
136+
if ( clientSensorLocation.isValid() )
137+
{
138+
// Body sensor location value is 8 bit
139+
const char* body_str[] = { "Other", "Chest", "Wrist", "Finger", "Hand", "Ear Lobe", "Foot" };
140+
141+
uint8_t loc_value = 0;
142+
if ( clientSensorLocation.read(&loc_value) )
143+
{
144+
Serial.print("Body Location Sensor: ");
145+
Serial.println(body_str[loc_value]);
146+
}
147+
}
148+
149+
// Reaching here means we are ready to go, let's enable notification on measurement chr
150+
if ( clientMeasurement.enableNotify() )
151+
{
152+
Serial.println("Ready to receive HRM Measurement value");
153+
}else
154+
{
155+
Serial.println("Couldn't enable notify for HRM Measurement. Increase DEBUG LEVEL for troubleshooting");
156+
}
157+
}
158+
159+
/**
160+
* Callback invoked when a connection is dropped
161+
* @param conn_handle
162+
* @param reason
163+
*/
164+
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
165+
{
166+
(void) conn_handle;
167+
(void) reason;
168+
169+
Serial.println("Disconnected");
170+
}
171+
172+
173+
/**
174+
* Hooked callback that triggered when a measurement value is sent from peripheral
175+
* @param chr Reference to client characteristic that even occurred,
176+
* in this example it should be clientMeasurement
177+
* @param data Pointer to received data
178+
* @param len Length of received data
179+
*/
180+
void hrm_notify_callback(BLEClientCharacteristic& chr, uint8_t* data, uint16_t len)
181+
{
182+
// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml
183+
// Measurement contains of control byte0 and measurement (8 or 16 bit) + optional field
184+
// if byte0's bit0 is 0 --> measurement is 8 bit, otherwise 16 bit.
185+
186+
Serial.print("HRM Measurement: ");
187+
188+
189+
if ( data[0] & bit(0) )
190+
{
191+
uint16_t value;
192+
memcpy(&value, data+1, 2);
193+
194+
Serial.println(value);
195+
}
196+
else
197+
{
198+
Serial.println(data[1]);
199+
}
200+
}

libraries/Bluefruit52Lib/keywords.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ parentService KEYWORD2
171171
assign KEYWORD2
172172
discoverDescriptor KEYWORD2
173173
valueHandle KEYWORD2
174+
isValid KEYWORD2
174175

175176
read KEYWORD2
176177
write KEYWORD2

libraries/Bluefruit52Lib/src/BLEClientCharacteristic.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ uint16_t BLEClientCharacteristic::valueHandle(void)
106106
return _chr.handle_value;
107107
}
108108

109+
bool BLEClientCharacteristic::isValid(void)
110+
{
111+
return _chr.handle_value != BLE_GATT_HANDLE_INVALID;
112+
}
113+
109114
uint8_t BLEClientCharacteristic::properties(void)
110115
{
111116
uint8_t u8;
@@ -159,6 +164,21 @@ uint16_t BLEClientCharacteristic::read(void* buffer, uint16_t bufsize)
159164
return (rxlen < 0) ? 0 : rxlen;
160165
}
161166

167+
uint16_t BLEClientCharacteristic::read(uint32_t* num)
168+
{
169+
return read(num, 4);
170+
}
171+
172+
uint16_t BLEClientCharacteristic::read(uint16_t* num)
173+
{
174+
return read(num, 2);
175+
}
176+
177+
uint16_t BLEClientCharacteristic::read(uint8_t* num)
178+
{
179+
return read(num, 1);
180+
}
181+
162182
/*------------------------------------------------------------------*/
163183
/* WRITE
164184
*------------------------------------------------------------------*/

libraries/Bluefruit52Lib/src/BLEClientCharacteristic.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,35 +59,41 @@ class BLEClientCharacteristic
5959
// Destructor
6060
virtual ~BLEClientCharacteristic();
6161

62-
void assign(ble_gattc_char_t* gattc_chr);
63-
bool discoverDescriptor(uint16_t conn_handle, ble_gattc_handle_range_t hdl_range);
62+
void assign(ble_gattc_char_t* gattc_chr);
63+
bool discoverDescriptor(uint16_t conn_handle, ble_gattc_handle_range_t hdl_range);
6464

65-
void begin(BLEClientService* parent_svc = NULL);
65+
void begin(BLEClientService* parent_svc = NULL);
6666

6767
uint16_t connHandle(void);
6868
uint16_t valueHandle(void);
69+
bool isValid(void);
6970
uint8_t properties(void);
71+
72+
7073
BLEClientService& parentService(void);
7174

7275
/*------------- Read -------------*/
7376
uint16_t read(void* buffer, uint16_t bufsize);
77+
uint16_t read(uint32_t* num);
78+
uint16_t read(uint16_t* num);
79+
uint16_t read(uint8_t* num);
7480

7581
/*------------- Write -------------*/
7682
uint16_t write (const void* data, uint16_t len);
7783
uint16_t write_resp(const void* data, uint16_t len);
7884

7985
/*------------- Notify -------------*/
80-
bool writeCCCD (uint16_t value);
86+
bool writeCCCD (uint16_t value);
8187

82-
bool enableNotify (void);
83-
bool disableNotify (void);
88+
bool enableNotify (void);
89+
bool disableNotify (void);
8490

85-
bool enableIndicate (void);
86-
bool disableIndicate (void);
91+
bool enableIndicate (void);
92+
bool disableIndicate (void);
8793

8894
/*------------- Callbacks -------------*/
89-
void setNotifyCallback(notify_cb_t fp);
90-
void useAdaCallback(bool enabled);
95+
void setNotifyCallback(notify_cb_t fp);
96+
void useAdaCallback(bool enabled);
9197

9298
private:
9399
ble_gattc_char_t _chr;

0 commit comments

Comments
 (0)