xref: /btstack/src/ble/gatt-service/cycling_power_service_server.h (revision ced70f9bfeafe291ec597a3a9cc862e39e0da3ce)
1 /*
2  * Copyright (C) 2018 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 /**
39  * @title Cycling Power Service Server
40  *
41  */
42 
43 #ifndef CYCLING_POWER_SERVICE_SERVER_H
44 #define CYCLING_POWER_SERVICE_SERVER_H
45 
46 #include <stdint.h>
47 
48 #if defined __cplusplus
49 extern "C" {
50 #endif
51 
52 /**
53  * @text The Cycling Power Service allows to query device's power- and
54  * force-related data and optionally speed- and cadence-related data for
55  * use in sports and fitness applications.
56  *
57  * To use with your application, add `#import <cycling_power_service.gatt>`
58  * to your .gatt file.
59  */
60 
61 /* API_START */
62 #define CYCLING_POWER_MANUFACTURER_SPECIFIC_DATA_MAX_SIZE   16
63 
64 typedef enum {
65     CP_PEDAL_POWER_BALANCE_REFERENCE_UNKNOWN = 0,
66     CP_PEDAL_POWER_BALANCE_REFERENCE_LEFT,
67     CP_PEDAL_POWER_BALANCE_REFERENCE_NOT_SUPPORTED
68 } cycling_power_pedal_power_balance_reference_t;
69 
70 typedef enum {
71     CP_TORQUE_SOURCE_WHEEL = 0,
72     CP_TORQUE_SOURCE_CRANK,
73     CP_TORQUE_SOURCE_NOT_SUPPORTED
74 } cycling_power_torque_source_t;
75 
76 typedef enum {
77     CP_SENSOR_MEASUREMENT_CONTEXT_FORCE = 0,
78     CP_SENSOR_MEASUREMENT_CONTEXT_TORQUE
79 } cycling_power_sensor_measurement_context_t;
80 
81 typedef enum {
82     CP_DISTRIBUTED_SYSTEM_UNSPECIFIED = 0,
83     CP_DISTRIBUTED_SYSTEM_NOT_SUPPORTED,
84     CP_DISTRIBUTED_SYSTEM_SUPPORTED
85 } cycling_power_distributed_system_t;
86 
87 typedef enum {
88     CP_MEASUREMENT_FLAG_PEDAL_POWER_BALANCE_PRESENT = 0,
89     CP_MEASUREMENT_FLAG_PEDAL_POWER_BALANCE_REFERENCE, // 0 - unknown, 1 - left
90     CP_MEASUREMENT_FLAG_ACCUMULATED_TORQUE_PRESENT,
91     CP_MEASUREMENT_FLAG_ACCUMULATED_TORQUE_SOURCE, // 0 - wheel based, 1 - crank based
92     CP_MEASUREMENT_FLAG_WHEEL_REVOLUTION_DATA_PRESENT,
93     CP_MEASUREMENT_FLAG_CRANK_REVOLUTION_DATA_PRESENT,
94     CP_MEASUREMENT_FLAG_EXTREME_FORCE_MAGNITUDES_PRESENT,
95     CP_MEASUREMENT_FLAG_EXTREME_TORQUE_MAGNITUDES_PRESENT,
96     CP_MEASUREMENT_FLAG_EXTREME_ANGLES_PRESENT,
97     CP_MEASUREMENT_FLAG_TOP_DEAD_SPOT_ANGLE_PRESENT,
98     CP_MEASUREMENT_FLAG_BOTTOM_DEAD_SPOT_ANGLE_PRESENT,
99     CP_MEASUREMENT_FLAG_ACCUMULATED_ENERGY_PRESENT,
100     CP_MEASUREMENT_FLAG_OFFSET_COMPENSATION_INDICATOR,
101     CP_MEASUREMENT_FLAG_RESERVED
102 } cycling_power_measurement_flag_t;
103 
104 typedef enum {
105     CP_INSTANTANEOUS_MEASUREMENT_DIRECTION_UNKNOWN = 0,
106     CP_INSTANTANEOUS_MEASUREMENT_DIRECTION_TANGENTIAL_COMPONENT,
107     CP_INSTANTANEOUS_MEASUREMENT_DIRECTION_RADIAL_COMPONENT,
108     CP_INSTANTANEOUS_MEASUREMENT_DIRECTION_LATERAL_COMPONENT
109 } cycling_power_instantaneous_measurement_direction_t;
110 
111 typedef enum {
112     CP_VECTOR_FLAG_CRANK_REVOLUTION_DATA_PRESENT = 0,
113     CP_VECTOR_FLAG_FIRST_CRANK_MEASUREMENT_ANGLE_PRESENT,
114     CP_VECTOR_FLAG_INSTANTANEOUS_FORCE_MAGNITUDE_ARRAY_PRESENT,
115     CP_VECTOR_FLAG_INSTANTANEOUS_TORQUE_MAGNITUDE_ARRAY_PRESENT,
116     CP_VECTOR_FLAG_INSTANTANEOUS_MEASUREMENT_DIRECTION = 4, // 2 bit
117     CP_VECTOR_FLAG_RESERVED = 6
118 } cycling_power_vector_flag_t;
119 
120 typedef enum {
121     CP_SENSOR_LOCATION_OTHER,
122     CP_SENSOR_LOCATION_TOP_OF_SHOE,
123     CP_SENSOR_LOCATION_IN_SHOE,
124     CP_SENSOR_LOCATION_HIP,
125     CP_SENSOR_LOCATION_FRONT_WHEEL,
126     CP_SENSOR_LOCATION_LEFT_CRANK,
127     CP_SENSOR_LOCATION_RIGHT_CRANK,
128     CP_SENSOR_LOCATION_LEFT_PEDAL,
129     CP_SENSOR_LOCATION_RIGHT_PEDAL,
130     CP_SENSOR_LOCATION_FRONT_HUB,
131     CP_SENSOR_LOCATION_REAR_DROPOUT,
132     CP_SENSOR_LOCATION_CHAINSTAY,
133     CP_SENSOR_LOCATION_REAR_WHEEL,
134     CP_SENSOR_LOCATION_REAR_HUB,
135     CP_SENSOR_LOCATION_CHEST,
136     CP_SENSOR_LOCATION_SPIDER,
137     CP_SENSOR_LOCATION_CHAIN_RING,
138     CP_SENSOR_LOCATION_RESERVED
139 } cycling_power_sensor_location_t;
140 
141 typedef enum {
142     CP_FEATURE_FLAG_PEDAL_POWER_BALANCE_SUPPORTED = 0,
143     CP_FEATURE_FLAG_ACCUMULATED_TORQUE_SUPPORTED,
144     CP_FEATURE_FLAG_WHEEL_REVOLUTION_DATA_SUPPORTED,
145     CP_FEATURE_FLAG_CRANK_REVOLUTION_DATA_SUPPORTED,
146     CP_FEATURE_FLAG_EXTREME_MAGNITUDES_SUPPORTED,
147     CP_FEATURE_FLAG_EXTREME_ANGLES_SUPPORTED,
148     CP_FEATURE_FLAG_TOP_AND_BOTTOM_DEAD_SPOT_ANGLE_SUPPORTED,
149     CP_FEATURE_FLAG_ACCUMULATED_ENERGY_SUPPORTED,
150     CP_FEATURE_FLAG_OFFSET_COMPENSATION_INDICATOR_SUPPORTED,
151     CP_FEATURE_FLAG_OFFSET_COMPENSATION_SUPPORTED,
152     CP_FEATURE_FLAG_CYCLING_POWER_MEASUREMENT_CHARACTERISTIC_CONTENT_MASKING_SUPPORTED,
153     CP_FEATURE_FLAG_MULTIPLE_SENSOR_LOCATIONS_SUPPORTED,
154     CP_FEATURE_FLAG_CRANK_LENGTH_ADJUSTMENT_SUPPORTED,
155     CP_FEATURE_FLAG_CHAIN_LENGTH_ADJUSTMENT_SUPPORTED,
156     CP_FEATURE_FLAG_CHAIN_WEIGHT_ADJUSTMENT_SUPPORTED,
157     CP_FEATURE_FLAG_SPAN_LENGTH_ADJUSTMENT_SUPPORTED,
158     CP_FEATURE_FLAG_SENSOR_MEASUREMENT_CONTEXT, // 0-force based, 1-torque based
159     CP_FEATURE_FLAG_INSTANTANEOUS_MEASUREMENT_DIRECTION_SUPPORTED,
160     CP_FEATURE_FLAG_FACTORY_CALIBRATION_DATE_SUPPORTED,
161     CP_FEATURE_FLAG_ENHANCED_OFFSET_COMPENSATION_SUPPORTED,
162     CP_FEATURE_FLAG_DISTRIBUTED_SYSTEM_SUPPORT = 20,  // 0-unspecified, 1-not for use in distr. system, 2-used in distr. system, 3-reserved
163     CP_FEATURE_FLAG_RESERVED = 22
164 } cycling_power_feature_flag_t;
165 
166 typedef enum {
167     CP_CALIBRATION_STATUS_INCORRECT_CALIBRATION_POSITION = 0x01,
168     CP_CALIBRATION_STATUS_MANUFACTURER_SPECIFIC_ERROR_FOLLOWS = 0xFF
169 } cycling_power_calibration_status_t;
170 
171 
172 /**
173  * @brief Init Server with ATT DB
174  *
175  * @param feature_flags
176  * @param pedal_power_balance_reference
177  * @param torque_source
178  * @param supported_sensor_locations
179  * @param num_supported_sensor_locations
180  * @param current_sensor_location
181  */
182 void cycling_power_service_server_init(uint32_t feature_flags,
183                                        cycling_power_pedal_power_balance_reference_t pedal_power_balance_reference, cycling_power_torque_source_t torque_source,
184                                        cycling_power_sensor_location_t * supported_sensor_locations, uint16_t num_supported_sensor_locations,
185                                        cycling_power_sensor_location_t current_sensor_location);
186 
187 /**
188  * @brief Setup measurement as advertisement data
189  * @param adv_interval
190  * @param adv_buffer
191  * @param adv_size
192  * @return
193  */
194 int cycling_power_get_measurement_adv(uint16_t adv_interval, uint8_t * adv_buffer, uint16_t adv_size);
195 
196 /**
197  * @brief Register callback for the calibration and broadcast updates.
198  *
199  * @param callback
200  */
201 void cycling_power_service_server_packet_handler(btstack_packet_handler_t callback);
202 
203 /**
204  * @brief Report calibration done.
205  * @param measurement_type
206  * @param calibrated_value
207  */
208 void  cycling_power_server_calibration_done(cycling_power_sensor_measurement_context_t measurement_type, uint16_t calibrated_value);
209 
210 /**
211  * @brief Report enhanced calibration done.
212  *
213  * @param measurement_type
214  * @param calibrated_value
215  * @param manufacturer_company_id
216  * @param num_manufacturer_specific_data
217  * @param manufacturer_specific_data
218  */
219 void cycling_power_server_enhanced_calibration_done(cycling_power_sensor_measurement_context_t measurement_type,
220                                                     uint16_t calibrated_value, uint16_t manufacturer_company_id,
221                                                     uint8_t num_manufacturer_specific_data, uint8_t * manufacturer_specific_data);
222 
223 /**
224  * @brief Set factory calibration date.
225  * @param date
226  * @return 1 if successful
227  */
228 int  cycling_power_service_server_set_factory_calibration_date(gatt_date_time_t date);
229 
230 /**
231  * @brief Set sampling rate.
232  * @param sampling_rate_Hz
233  */
234 void cycling_power_service_server_set_sampling_rate(uint8_t sampling_rate_Hz);
235 
236 /**
237  * @brief Accumulate torque value.
238  * @param torque_Nm
239  */
240 void cycling_power_service_server_add_torque(int16_t torque_Nm);
241 
242 /**
243  * @brief Accumulate wheel revolution value and set the time of the last measurement.
244  * @param wheel_revolution
245  * @param wheel_event_time_s  unit: seconds
246  */
247 void cycling_power_service_server_add_wheel_revolution(int32_t wheel_revolution, uint16_t wheel_event_time_s);
248 
249 /**
250  * @brief Accumulate crank revolution value and set the time of the last measurement.
251  * @param crank_revolution
252  * @param crank_event_time_s  unit: seconds
253  */
254 void cycling_power_service_server_add_crank_revolution(uint16_t crank_revolution, uint16_t crank_event_time_s);
255 
256 /**
257  * @brief Accumulate energy.
258  * @param energy_kJ  unit: kilo Joule
259  */
260 void cycling_power_service_add_energy(uint16_t energy_kJ);
261 
262 /**
263  * @brief Set the value of the power. The Instantaneous Power field represents either
264  * the total power the user is producing or a part of the total power depending on the
265  * type of sensor (e.g., single sensor or distributed power sensor system).
266  *
267  * @param instantaneous_power_W  unit: watt
268  */
269 void cycling_power_service_server_set_instantaneous_power(int16_t instantaneous_power_W);
270 
271 /**
272  * @brief Set the pedal power balance value. The Pedal Power Balance field represents the ratio between
273  * the total amount of power measured by the sensor and a reference (either unknown or left).
274  *
275  * @param pedal_power_balance_percentage
276  */
277 void cycling_power_service_server_set_pedal_power_balance(uint8_t pedal_power_balance_percentage);
278 
279 /**
280  * @brief Set the minimum and maximum force value measured in a single crank revolution.
281  *
282  * This, so called, Extreme Force Magnitude field pair will be included in the Cycling Power Measurement
283  * characteristic only if the device supports the Extreme Magnitudes feature and
284  * the Sensor Measurement Context of the Cycling Power Feature characteristic is set to 0 (Force-based).
285  *
286  * @param min_force_magnitude_N  unit: newton
287  * @param max_force_magnitude_N  unit: newton
288  */
289 void cycling_power_service_server_set_force_magnitude(int16_t min_force_magnitude_N, int16_t max_force_magnitude_N);
290 
291 /**
292  * @brief Set the minimum and maximum torque value measured in a single crank revolution.
293  *
294  * This, so called, Extreme Torque Magnitude field pair will be included in the Cycling Power Measurement
295  * characteristic only if the device supports the Extreme Magnitudes feature and
296  * the Sensor Measurement Context of the Cycling Power Feature characteristic is set to 1 (Torque-based).
297  *
298  * @param min_torque_magnitude_Nm  unit: newton meter
299  * @param max_torque_magnitude_Nm  unit: newton meter
300  */
301 void cycling_power_service_server_set_torque_magnitude(int16_t min_torque_magnitude_Nm, int16_t max_torque_magnitude_Nm);
302 
303 /**
304  * @brief Set the minimum and maximum angle of the crank measured in a single crank revolution (unit: degree).
305  *
306  * This, so called, Extreme Angles Magnitude field pair will be included in the Cycling Power Measurement
307  * characteristic only if the device supports the Extreme Angles feature.
308  *
309  * @param min_angle_degree
310  * @param max_angle_degree
311  */
312 void cycling_power_service_server_set_angle(uint16_t min_angle_degree, uint16_t max_angle_degree);
313 
314 /**
315  * @brief Set the value of the crank angle measured when the value of the Instantaneous Power value becomes positive.
316  *
317  * This field will be included in the Cycling Power Measurement characteristic
318  * only if the device supports the Top and Bottom Dead Spot Angles feature.
319  *
320  * @param top_dead_spot_angle_degree
321  */
322 void cycling_power_service_server_set_top_dead_spot_angle(uint16_t top_dead_spot_angle_degree);
323 
324 /**
325  * @brief Set the value of the crank angle measured when the value of the Instantaneous Power value becomes negative.
326  *
327  * This field will be included in the Cycling Power Measurement characteristic
328  * only if the device supports the Top and Bottom Dead Spot Angles feature.
329  *
330  * @param bottom_dead_spot_angle_degree
331  */
332 void cycling_power_service_server_set_bottom_dead_spot_angle(uint16_t bottom_dead_spot_angle_degree);
333 
334 /**
335  * @brief Set the raw sensor force magnitude measurements.
336  *
337  * @param force_magnitude_count
338  * @param force_magnitude_N_array  unit: newton
339  */
340 void cycling_power_service_server_set_force_magnitude_values(int force_magnitude_count, int16_t * force_magnitude_N_array);
341 
342 /**
343  * @brief Set the raw sensor torque magnitude measurements.
344  *
345  * @param force_magnitude_count
346  * @param force_magnitude_N_array  unit: newton meter
347  */
348 void cycling_power_service_server_set_torque_magnitude_values(int torque_magnitude_count, int16_t * torque_magnitude_Nm_array);
349 
350 /**
351  * @brief Set the instantaneous measurement direction. The field describes
352  * the direction of the Instantaneous Magnitude values the Server measures
353  * (e.g., Unknown, Tangential Component, Radial Component, or Lateral Component).
354  *
355  * @param direction
356  */
357 void cycling_power_service_server_set_instantaneous_measurement_direction(cycling_power_instantaneous_measurement_direction_t direction);
358 
359 /**
360  * Set first crank measurement angle. The value will be present only in the first packet of
361  * the Cycling Power Vector notification.
362  *
363  * @param first_crank_measurement_angle_degree
364  */
365 void cycling_power_service_server_set_first_crank_measurement_angle(uint16_t first_crank_measurement_angle_degree);
366 
367 /**
368  * Get measurement flags bitmask.
369  * @return measurement_flags_bitmask, see cycling_power_measurement_flag_t
370  */
371 uint16_t cycling_power_service_measurement_flags(void);
372 
373 /**
374  * Get vector flags bitmask.
375  * @return vector_flags_bitmask, see cycling_power_vector_flag_t
376  */
377 uint8_t  cycling_power_service_vector_flags(void);
378 
379 /**
380  * @brief Trigger notification if subscribed
381  */
382 void cycling_power_service_server_update_values(void);
383 
384 /* API_END */
385 
386 #if defined __cplusplus
387 }
388 #endif
389 
390 #endif
391 
392