SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
SensorBHI260AP_Klio.cpp
Go to the documentation of this file.
1
31#include "../../../SensorBuildOpt.h"
32#if !SENSORLIB_EXCLUDE_BHI260_KLIO
33
35
36const char *SensorBHI260AP_Klio::errorMessages[9] = {
37 "",
38 "Invalid parameter",
39 "Parameter out of range",
40 "Invalid pattern operation",
41 "Not implemented",
42 "Buffer size",
43 "Internal",
44 "Undefined",
45 "Operation pending"
46};
47
49 sensor(&sensor),
50 max_patterns(0),
51 max_pattern_size(0),
52 similarity_result_buf(nullptr),
53 similarity_idx_buf(nullptr),
54 learning_callback(nullptr),
55 learning_callback_user_data(nullptr),
56 recognition_callback(nullptr),
57 recognition_callback_user_data(nullptr),
58 errorCode(KLIO_DRIVER_ERROR_NONE),
59 k_state({0, 0, 0, 0}) {}
60
65
67{
68 if (sensor) {
69 sensor->configure(BoschSensorID::KLIO, 0, 0);
70 sensor->removeResultEvent(BoschSensorID::KLIO, static_klio_callback);
71 sensor->configure(BoschSensorID::KLIO_LOG, 0, 0);
72 sensor->removeResultEvent(BoschSensorID::KLIO_LOG, static_klio_log_callback);
73 }
74
75 if (similarity_result_buf ) {
76 free(similarity_result_buf);
77 similarity_result_buf = nullptr;
78 }
79 if (similarity_idx_buf ) {
80 free(similarity_idx_buf);
81 similarity_idx_buf = nullptr;
82 }
83}
84
85
87{
88 if (similarity_result_buf && similarity_idx_buf && sensor) {
89 return true;
90 }
91 if (!sensor) {
92 SENSORLIB_LOG_E("The sensor handle is null");
93 return false;
94 }
95 const uint8_t PARAM_BUF_LEN = 252;
96 uint8_t param_buf[PARAM_BUF_LEN];
97 uint16_t size = sizeof(param_buf);
98 int major = -1;
99 int minor = -1;
100 int version = -1;
101 int count = 0;
102
103 if (!getParameter(KLIO_PARAM_ALGORITHM_VERSION, param_buf, &size)) {
104 SENSORLIB_LOG_E("Unable to get Klio firmware version.");
105 return false;
106 }
107
108 if (size > 0) {
109 count = sscanf((char *)param_buf, "%d.%d.%d", &major, &minor, &version);
110 }
111
112 if (major < 0 || minor < 0 || version < 0 || count != 3) {
113 SENSORLIB_LOG_E("Unable to get Klio firmware version.");
114 return false;
115 }
116
117 SENSORLIB_LOG_D("Klio version %d.%d.%d - buf:%s", major, minor, version, param_buf);
118
119 /* Get number of supported patterns */
120 uint16_t length = sizeof(param_buf);
121 if (!getParameter(KLIO_PARAM_RECOGNITION_MAX_PATTERNS, param_buf, &length)) {
122 return false;
123 }
124 max_patterns = *((uint16_t *) param_buf);
125 similarity_result_buf = (float *)malloc(sizeof(float) * max_patterns);
126 if (!similarity_result_buf) {
127 SENSORLIB_LOG_E("Klio result buffer allocate failed!");
128 return false;
129 }
130 similarity_idx_buf = (uint8_t *)malloc(sizeof(uint8_t) * max_patterns);
131 if (!similarity_idx_buf) {
132 SENSORLIB_LOG_E("Klio index buffer allocate failed!");
133 free(similarity_result_buf);
134 return false;
135 }
136 SENSORLIB_LOG_D("Klio process allocate successfully!");
137
138 /* Get maximum supported pattern size */
139 length = sizeof(param_buf);
140 if (!getParameter(KLIO_PARAM_PATTERN_BLOB_SIZE, param_buf, &length)) {
141 free(similarity_idx_buf);
142 free(similarity_result_buf);
143 return false;
144 }
145 max_pattern_size = *((uint16_t *) param_buf);
146 SENSORLIB_LOG_D("Klio Max patterns :%u", max_patterns);
147 SENSORLIB_LOG_D("Klio Max pattern len:%u", max_pattern_size);
148
149 uint8_t ignore_insignificant_movement = 1;
150 /* Prevent learning with small movements, parameter writes should be done after reset and before sensor enable */
151 setParameter(KLIO_PARAM_LEARNING_IGNORE_INSIG_MOVEMENT, &ignore_insignificant_movement,
152 sizeof(ignore_insignificant_movement));
153
154
155 sensor->onResultEvent(BoschSensorID::KLIO_LOG, static_klio_log_callback, this);
156
157 return sensor->onResultEvent(BoschSensorID::KLIO, static_klio_callback, this);
158}
159
160bool SensorBHI260AP_Klio::setState(bool learning_enable, bool learning_reset, bool recognition_enable, bool recognition_reset)
161{
162 bhy2_klio_sensor_state_t sensor_state = {
163 .learning_enabled = learning_enable,
164 .learning_reset = learning_reset,
165 .recognition_enabled = recognition_enable,
166 .recognition_reset = recognition_reset
167 };
168 return KlioTemplate(bhy2_klio_set_state, &sensor_state);
169
170}
171
173{
174 bhy2_klio_sensor_state_t sensor_state;
175 if (!sensor) {
176 SENSORLIB_LOG_E("The sensor handle is null");
177 return {};
178 }
179 bhy2_klio_get_state(&sensor_state, sensor->getDev());
180 return sensor_state;
181}
182
184{
185 if (!sensor) {
186 SENSORLIB_LOG_E("The sensor handle is null");
187 return false;
188 }
189 return bhy2_klio_set_state(&sensor_state, sensor->getDev()) == BHY2_OK;
190}
191
193{
194 k_state = getState();
195 k_state.learning_enabled = true;
196 return setState(k_state);
197}
198
199bool SensorBHI260AP_Klio::recognition(const uint8_t *pattern_ids, size_t size)
200{
201 if (!KlioTemplate(bhy2_klio_set_pattern_states, KLIO_PATTERN_STATE_ENABLE, pattern_ids, size)) {
202 SENSORLIB_LOG_E("Klio set pattern idx failed!");
203 return false;
204 }
205 k_state = getState();
206 k_state.learning_enabled = false;
207 k_state.recognition_enabled = true;
208 return setState(k_state);
209}
210
211bool SensorBHI260AP_Klio::getLearnPattern(uint8_t *pattern, uint16_t *size)
212{
213 return KlioTemplate(bhy2_klio_read_pattern, 0, pattern, size);
214}
215
217{
218 return max_patterns;
219}
220
221void SensorBHI260AP_Klio::static_klio_callback(uint8_t sensor_id, const uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data)
222{
223 SensorBHI260AP_Klio *self = static_cast<SensorBHI260AP_Klio *>(user_data);
224 self->klio_call_local(sensor_id, data, size, timestamp, self);
225}
226
227void SensorBHI260AP_Klio::klio_call_local(uint8_t sensor_id, const uint8_t *data_ptr, uint32_t size, uint64_t *timestamp, void *user_data)
228{
229 bhy2_klio_sensor_frame_t data;
230 if (size != 11) {
231 return;
232 }
233 memcpy(&data, data_ptr, sizeof(data));
234 if (learning_callback) {
235 if (k_state.learning_enabled) {
236 learning_callback(static_cast<LearningChangeReason>(data.learn.change_reason),
237 data.learn.progress, data.learn.index, learning_callback_user_data);
238 }
239 }
240 if (recognition_callback && data.recognize.index != 0xFF) {
241 if (k_state.recognition_enabled) {
242 recognition_callback(data.recognize.index, data.recognize.count, recognition_callback_user_data);
243 }
244 }
245}
246
247void SensorBHI260AP_Klio::static_klio_log_callback(uint8_t sensor_id, const uint8_t *data, uint32_t size, uint64_t *timestamp, void *user_data)
248{
249 SensorBHI260AP_Klio *self = static_cast<SensorBHI260AP_Klio *>(user_data);
250 self->klio_log_call_local(sensor_id, data, size, timestamp, self);
251}
252
253void SensorBHI260AP_Klio::klio_log_call_local(uint8_t sensor_id, const uint8_t *data_ptr, uint32_t size, uint64_t *timestamp, void *user_data)
254{
255 bhy2_klio_log_frame_t data;
256 memcpy(&data, data_ptr, sizeof(data));
257 SENSORLIB_LOG_D("ax: %.9g, ay: %.9g, az: %.9g, gx: %.9g, gy: %.9g, gz: %.9g\n",
258 data.accel[0],
259 data.accel[1],
260 data.accel[2],
261 data.gyro[0],
262 data.gyro[1],
263 data.gyro[2]);
264}
265
266bool SensorBHI260AP_Klio::getParameter(KlioParameter id, uint8_t *parameter_data, uint16_t *size)
267{
268 return KlioTemplate(bhy2_klio_get_parameter, id, parameter_data, size);
269}
270
271bool SensorBHI260AP_Klio::setParameter(KlioParameter id, const void *parameter_data, uint16_t size)
272{
273 return KlioTemplate(bhy2_klio_set_parameter, id, parameter_data, size);
274}
275
276bool SensorBHI260AP_Klio::writePattern(uint8_t idx, const uint8_t *parameter_data, uint16_t size)
277{
278 return KlioTemplate(bhy2_klio_write_pattern, idx, parameter_data, size);
279}
280
281bool SensorBHI260AP_Klio::writeMultiplePatterns(const uint8_t *ids, const uint8_t **parameter_data_array, const uint16_t *sizes, uint8_t count)
282{
283 for (uint8_t i = 0; i < count; ++i) {
284 if (!KlioTemplate(bhy2_klio_write_pattern, ids[i], parameter_data_array[i], sizes[i])) {
285 SENSORLIB_LOG_D("Write pattern with ID :%u failed", ids[i]);
286 return false;
287 }
288 }
289 return true;
290}
291
292bool SensorBHI260AP_Klio::setPattern(KlioPatternState operation, const uint8_t *pattern_ids, uint16_t size)
293{
294 return KlioTemplate(bhy2_klio_set_pattern_states, static_cast<bhy2_klio_pattern_state_t>(operation), pattern_ids, size);
295}
296
297bool SensorBHI260AP_Klio::enablePattern(const uint8_t *pattern_ids, uint16_t size)
298{
299 return KlioTemplate(bhy2_klio_set_pattern_states, KLIO_PATTERN_STATE_ENABLE, pattern_ids, size);
300}
301
302bool SensorBHI260AP_Klio::readPattern(uint8_t idx, uint8_t *buffer, uint16_t *length)
303{
304 return KlioTemplate(bhy2_klio_read_pattern, idx, buffer, length);
305}
306
307bool SensorBHI260AP_Klio::enable(float sample_rate, uint32_t report_latency_ms)
308{
309 if (!sensor) {
310 SENSORLIB_LOG_E("The sensor handle is null");
311 return false;
312 }
313 return sensor->configure(BoschSensorID::KLIO, sample_rate, report_latency_ms);
314}
315
317{
318 if (!sensor) {
319 SENSORLIB_LOG_E("The sensor handle is null");
320 return;
321 }
322 sensor->configure(BoschSensorID::KLIO, 0, 0);
323}
324
325bool SensorBHI260AP_Klio::logout(float sample_rate, uint32_t report_latency_ms)
326{
327 if (!sensor) {
328 SENSORLIB_LOG_E("The sensor handle is null");
329 return false;
330 }
331 return sensor->configure(BoschSensorID::KLIO_LOG, sample_rate, report_latency_ms);
332}
333
335{
336 learning_callback = cb;
337 learning_callback_user_data = user_data;
338}
339
341{
342 recognition_callback = cb;
343 recognition_callback_user_data = user_data;
344}
345
347{
348 if (!sensor) {
349 SENSORLIB_LOG_E("The sensor handle is null");
350 return false;
351 }
352 uint32_t klio_status;
353 int8_t rslt = bhy2_klio_read_reset_driver_status(&klio_status, sensor->getDev());
354 if (rslt != BHY2_OK) {
355 errorCode = static_cast<KlioError>(klio_status);
356 return true;
357 }
358 errorCode = static_cast<KlioError>(klio_status);
359 return errorCode != KLIO_DRIVER_ERROR_NONE;
360}
361
363{
364 return errorCode;
365}
366
368{
369 if (errorCode <= 8) {
370 return errorMessages[errorCode];
371 }
372 return "Unknown error code";
373}
374
375
376template<typename Func, typename... Args>
377bool SensorBHI260AP_Klio::KlioTemplate(Func func, Args &&... args)
378{
379 if (!sensor) {
380 SENSORLIB_LOG_E("The sensor handle is null");
381 return false;
382 }
383 int8_t rslt = func(std::forward<Args>(args)..., sensor->getDev());
384 if (rslt != BHY2_OK) {
385 SENSORLIB_LOG_E("Interface access error, %s", BoschSensorUtils::get_api_error(rslt));
386 return false;
387 }
388 if (checkError()) {
390 return false;
391 }
392 return true;
393}
394
395
396#endif
#define SENSORLIB_LOG_E(...)
#define SENSORLIB_LOG_D(...)
SensorBMA4XX * sensor
bhy2_klio_driver_error_state_t KlioError
void(*)(LearningChangeReason reason, uint32_t progress, int learn_index, void *user_data) LearningCallback
void end()
End the interaction with the KLIO functionality of the BHI260AP sensor and release related resources.
bool getLearnPattern(uint8_t *pattern, uint16_t *size)
Retrieve the learned pattern from the sensor.
bool writeMultiplePatterns(const uint8_t *ids, const uint8_t **parameter_data_array, const uint16_t *sizes, uint8_t count)
Write multiple patterns to the KLIO sensor.
bool readPattern(uint8_t idx, uint8_t *buffer, uint16_t *length)
Read a pattern from the KLIO sensor.
void setLearningCallback(LearningCallback cb, void *user_data)
Set the callback function for the learning event.
void disable()
Disable the KLIO sensor.
bool setPattern(KlioPatternState operation, const uint8_t *pattern_ids, uint16_t size)
Set the state of patterns in the KLIO sensor.
KlioError getError() const
Get the error information of the KLIO sensor.
bool writePattern(uint8_t idx, const uint8_t *parameter_data, uint16_t size)
Write a pattern to the KLIO sensor.
void(*)(uint8_t pattern_id, float count, void *user_data) RecognitionCallback
KlioState getState()
Get the current state of the KLIO sensor.
bool logout(float sample_rate, uint32_t report_latency_ms)
Log out the KLIO sensor with specified sample rate and report latency.
bool begin()
Initialize the interaction with the KLIO functionality of the BHI260AP sensor.
bool enablePattern(const uint8_t *pattern_ids, uint16_t size)
Enable specified patterns in the KLIO sensor.
bool enable(float sample_rate, uint32_t report_latency_ms)
Enable the KLIO sensor with specified sample rate and report latency.
bool learning()
Start the learning function of the KLIO sensor.
bool setState(bool learning_enable, bool learning_reset, bool recognition_enable, bool recognition_reset)
Set the learning and recognition states of the KLIO sensor.
uint8_t getMaxPatterns()
Retrieve the maximum number of recognition patterns allowed.
const char * errorToString() const
Convert the error information to a string.
bool checkError()
Check if there is an error in the KLIO sensor.
bool recognition(const uint8_t *pattern_ids, size_t size)
Start the recognition function of the KLIO sensor for the specified pattern IDs.
bool getParameter(KlioParameter id, uint8_t *parameter_data, uint16_t *size)
Get a parameter from the KLIO sensor.
void setRecognitionCallback(RecognitionCallback cb, void *user_data)
Set the callback function for the recognition event.
bool setParameter(KlioParameter id, const void *parameter_data, uint16_t size)
Set a parameter of the KLIO sensor.
SensorBHI260AP_Klio(SensorBHI260AP &sensor)
Constructor to initialize the SensorBHI260AP_Klio object.
~SensorBHI260AP_Klio()
Destructor to release resources occupied by the SensorBHI260AP_Klio object.
uint8_t i