Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Fork of Bluetooth_Heart_Rate_Monitor_dummy by
CycleSpeedCadenceService.h
- Committer:
- smigielski
- Date:
- 2015-05-25
- Revision:
- 71:832536f63f0b
- Parent:
- 64:43e7ddf9dba5
File content as of revision 71:832536f63f0b:
/* mbed Microcontroller Library
* Copyright (c) 2006-2013 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __BLE_CYCLE_SPEED_CADENCE_SERVICE_H__
#define __BLE_CYCLE_SPEED_CADENCE_SERVICE_H__
#include "BLEDevice.h"
/**
* @class CycleSpeedCadenceService
* @brief BLE Service for HeartRate. This BLE Service contains the location of the sensor, the heartrate in beats per minute. <br>
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml <br>
* HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml <br>
* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml
*/
class CycleSpeedCadenceService {
public:
/**
* @enum SensorLocation
* @brief Location of HeartRate sensor on body.
*/
enum {
LOCATION_OTHER = 0,
LOCATION_TOP_OF_SHOE,
LOCATION_IN_SHOE,
LOCATION_HIP,
LOCATION_FRONT_WHEEL,
LOCATION_LEFT_CRANK,
LOCATION_RIGHT_CRANK,
LOCATION_LEFT_PEDAL,
LOCATION_RIGHT_PEDAL,
LOCATION_FRONT_HUB,
LOCATION_REAR_DROPOUT,
LOCATION_CHAINSTAY,
LOCATION_REAR_WHEEL,
LOCATION_REAR_HUB,
LOCATION_CHEST
};
enum {
UUID_SENSOR_LOCATION_CHAR = 0x2A5D,
UUID_CSC_MEASUREMENT_CHAR = 0x2A5B,
UUID_CSC_FEATURE_CHAR = 0x2A5C,
UUID_CSC_CONTROL_POINT_CHAR = 0x2A55
};
public:
/**
* @brief Constructor with 8bit HRM Counter value.
*
* @param[ref] _ble
* Reference to the underlying BLEDevice.
* @param[in] hrmCounter (8-bit)
* initial value for the hrm counter.
* @param[in] location
* Sensor's location.
*/
CycleSpeedCadenceService(BLEDevice &_ble, uint32_t wheelRevolutions ,uint16_t wheelEvent, uint8_t location) :
ble(_ble),
feautureBytes(true,false),
valueBytes(wheelRevolutions,wheelEvent),
cscMesurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
valueBytes.getNumValueBytes(), CSCValueBytes::MAX_VALUE_BYTES,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
cscFeatures(CycleSpeedCadenceService::UUID_CSC_FEATURE_CHAR, feautureBytes.getPointer()),
sensorLocation(CycleSpeedCadenceService::UUID_SENSOR_LOCATION_CHAR, &location),
controlPoint(CycleSpeedCadenceService::UUID_CSC_CONTROL_POINT_CHAR, &controlPointValue) {
setupService();
}
CycleSpeedCadenceService(BLEDevice &_ble, uint16_t crankRevolutions, uint16_t crankEvent, uint8_t location ) :
ble(_ble),
feautureBytes(false,true),
valueBytes(crankRevolutions,crankEvent),
cscMesurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
valueBytes.getNumValueBytes(), CSCValueBytes::MAX_VALUE_BYTES,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
cscFeatures(CycleSpeedCadenceService::UUID_CSC_FEATURE_CHAR, feautureBytes.getPointer()),
sensorLocation(CycleSpeedCadenceService::UUID_SENSOR_LOCATION_CHAR, &location),
controlPoint(CycleSpeedCadenceService::UUID_CSC_CONTROL_POINT_CHAR, &controlPointValue) {
setupService();
}
CycleSpeedCadenceService(BLEDevice &_ble, uint32_t wheelRevolutions ,uint16_t wheelEvent,uint16_t crankRevolutions, uint16_t crankEvent, uint8_t location ) :
ble(_ble),
feautureBytes(true,true),
valueBytes(wheelRevolutions,wheelEvent,crankRevolutions,crankEvent),
cscMesurement(GattCharacteristic::UUID_CSC_MEASUREMENT_CHAR, valueBytes.getPointer(),
valueBytes.getNumValueBytes(), CSCValueBytes::MAX_VALUE_BYTES,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
cscFeatures(CycleSpeedCadenceService::UUID_CSC_FEATURE_CHAR, feautureBytes.getPointer()),
sensorLocation(CycleSpeedCadenceService::UUID_SENSOR_LOCATION_CHAR, &location),
controlPoint(CycleSpeedCadenceService::UUID_CSC_CONTROL_POINT_CHAR, &controlPointValue) {
setupService();
}
/**
* @brief Set a new 8-bit value for heart rate.
*
* @param[in] hrmCounter
* HeartRate in bpm.
*/
void updateWheel(uint32_t wheelRevolutions ,uint16_t wheelEvent) {
valueBytes.updateWheel(wheelRevolutions,wheelEvent);
ble.updateCharacteristicValue(cscMesurement.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
}
/**
* Set a new 16-bit value for heart rate.
*
* @param[in] hrmCounter
* HeartRate in bpm.
*/
void updateCrank(uint16_t crankRevolutions, uint16_t crankEvent) {
valueBytes.updateCrank(crankRevolutions,crankEvent);
ble.updateCharacteristicValue(cscMesurement.getValueAttribute().getHandle(), valueBytes.getPointer(), valueBytes.getNumValueBytes());
}
/**
* This callback allows the CycleSpeedCadenceService to receive updates to the
* controlPoint Characteristic.
*
* @param[in] params
* Information about the characterisitc being updated.
*/
virtual void onDataWritten(const GattCharacteristicWriteCBParams *params) {
if (params->charHandle == controlPoint.getValueHandle()) {
/* Do something here if the new value is 1; else you can override this method by
* extending this class.
* @NOTE: if you are extending this class, be sure to also call
* ble.onDataWritten(this, &ExtendedHRService::onDataWritten); in
* your constructor.
*/
}
}
private:
void setupService(void) {
static bool serviceAdded = false; /* We should only ever need to add the heart rate service once. */
if (serviceAdded) {
return;
}
GattCharacteristic *charTable[] = {&cscMesurement, &cscFeatures, &sensorLocation, &controlPoint};
GattService cscsService(GattService::UUID_CYCLING_SPEED_AND_CADENCE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
ble.addService(cscsService);
serviceAdded = true;
ble.onDataWritten(this, &CycleSpeedCadenceService::onDataWritten);
}
private:
struct CSCFeatureBytes {
uint16_t cscFeaturesValue;
//location change is not supported right now
CSCFeatureBytes(bool wheelSupport, bool crankSupport){
cscFeaturesValue= wheelSupport | crankSupport << 1;
}
uint16_t *getPointer(void) {
return &cscFeaturesValue;
}
const uint16_t *getPointer(void) const {
return &cscFeaturesValue;
}
};
/* Private internal representation for the bytes used to work with the vaulue of the heart-rate characteristic. */
struct CSCValueBytes {
static const unsigned MAX_VALUE_BYTES = 11; /* FLAGS + up to two bytes for heart-rate */
static const unsigned FLAGS_BYTE_INDEX = 0;
static const unsigned WHEEL_REVOLUTIONS_INDEX = 1;
static const unsigned WHEEL_EVENT_INDEX = 5;
static const unsigned CRANK_REVOLUTIONS_INDEX = 1;
static const unsigned CRANK_EVENT_INDEX = 3;
static const unsigned WHEEL_PRESENCE_BITNUM = 0;
static const uint8_t WHEEL_FLAG = (1 << WHEEL_PRESENCE_BITNUM);
static const unsigned CADENCE_PRESENCE_BITNUM = 1;
static const uint8_t CADENCE_FLAG = (1 << CADENCE_PRESENCE_BITNUM);
//speed
CSCValueBytes(uint32_t wheelRevolutions ,uint16_t wheelEvent) : valueBytes() {
valueBytes[FLAGS_BYTE_INDEX] = WHEEL_FLAG;
updateWheel(wheelRevolutions,wheelEvent);
}
//cadence
CSCValueBytes(uint16_t crankRevolutions, uint16_t crankEvent ) : valueBytes() {
valueBytes[FLAGS_BYTE_INDEX] = CADENCE_FLAG;
updateCrank(crankRevolutions,crankEvent);
}
//speed + cadence
CSCValueBytes(uint32_t wheelRevolutions ,uint16_t wheelEvent,uint16_t crankRevolutions, uint16_t crankEvent) : valueBytes() {
valueBytes[FLAGS_BYTE_INDEX] = (WHEEL_FLAG |CADENCE_FLAG);
updateWheel(wheelRevolutions,wheelEvent);
updateCrank(crankRevolutions,crankEvent);
}
void updateWheel(uint32_t wheelRevolutions ,uint16_t wheelEvent) {
valueBytes[WHEEL_REVOLUTIONS_INDEX] = (uint8_t)(wheelRevolutions & 0xFF);
valueBytes[WHEEL_REVOLUTIONS_INDEX + 1] = (uint8_t)((wheelRevolutions >> 8) & 0xFF);
valueBytes[WHEEL_REVOLUTIONS_INDEX + 2] = (uint8_t)((wheelRevolutions >> 16) & 0xFF);
valueBytes[WHEEL_REVOLUTIONS_INDEX + 3] = (uint8_t)((wheelRevolutions >> 24) & 0xFF);
valueBytes[WHEEL_EVENT_INDEX] = (uint8_t)(wheelEvent & 0xFF);
valueBytes[WHEEL_EVENT_INDEX + 1] = (uint8_t)((wheelEvent >> 8) & 0xFF);
}
void updateCrank(uint16_t crankRevolutions, uint16_t crankEvent) {
int offset = (valueBytes[FLAGS_BYTE_INDEX] & WHEEL_FLAG) ? sizeof(uint32_t)+ sizeof(uint16_t):0;
valueBytes[offset + CRANK_REVOLUTIONS_INDEX] = (uint8_t)(crankRevolutions & 0xFF);
valueBytes[offset + CRANK_REVOLUTIONS_INDEX + 1] = (uint8_t)((crankRevolutions >> 8) & 0xFF);
valueBytes[offset + CRANK_EVENT_INDEX] = (uint8_t)(crankEvent & 0xFF);
valueBytes[offset + CRANK_EVENT_INDEX + 1] = (uint8_t)((crankEvent >> 8) & 0xFF);
}
uint8_t *getPointer(void) {
return valueBytes;
}
const uint8_t *getPointer(void) const {
return valueBytes;
}
unsigned getNumValueBytes(void) const {
return 1 + ((valueBytes[FLAGS_BYTE_INDEX] & WHEEL_FLAG) ? sizeof(uint32_t)+ sizeof(uint16_t):0)
+ ((valueBytes[FLAGS_BYTE_INDEX] & CADENCE_FLAG) ? sizeof(uint16_t) + sizeof(uint16_t):0);
}
private:
/* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */
/* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
uint8_t valueBytes[MAX_VALUE_BYTES];
};
private:
BLEDevice &ble;
CSCFeatureBytes feautureBytes;
CSCValueBytes valueBytes;
uint8_t controlPointValue;
GattCharacteristic cscMesurement;
ReadOnlyGattCharacteristic<uint16_t> cscFeatures;
ReadOnlyGattCharacteristic<uint8_t> sensorLocation;
WriteOnlyGattCharacteristic<uint8_t> controlPoint;
};
#endif /* #ifndef __BLE_CYCLE_SPEED_CADENCE_SERVICE_H__*/
