From 01e3b4baaf5a9a11bea7ae2f71b369f4b6d76484 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Tue, 18 Jul 2017 19:01:18 +0900 Subject: [PATCH 01/16] sensord: remove unused debugging function Change-Id: I9486d4b7db1cf42eddd26d36c447108eff893a24 Signed-off-by: kibak.yoon --- src/shared/sensor_utils.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/shared/sensor_utils.cpp b/src/shared/sensor_utils.cpp index 16341cc..9cd8141 100644 --- a/src/shared/sensor_utils.cpp +++ b/src/shared/sensor_utils.cpp @@ -211,31 +211,6 @@ unsigned long long sensor::utils::get_timestamp(timeval *t) return ((unsigned long long)(t->tv_sec)*1000000LL +t->tv_usec); } -#ifdef _DEBUG -bool sensor::utils::get_proc_name(pid_t pid, char *process_name) -{ - FILE *fp; - char buf[NAME_MAX]; - char filename[PATH_MAX]; - - sprintf(filename, "/proc/%d/stat", pid); - fp = fopen(filename, "r"); - - if (fp == NULL) - return false; - - if (fscanf(fp, "%*s (%[^)]", buf) < 1) { - fclose(fp); - return false; - } - - strncpy(process_name, buf, NAME_MAX-1); - process_name[NAME_MAX-1] = '\0'; - fclose(fp); - - return true; -} -#else bool sensor::utils::get_proc_name(pid_t pid, char *process_name) { char buf[NAME_MAX]; @@ -249,7 +224,6 @@ bool sensor::utils::get_proc_name(pid_t pid, char *process_name) return true; } -#endif const char* sensor::utils::get_client_name(void) { -- 2.7.4 From d096d640331205a41eda989f5edbb3252d157410 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Fri, 21 Jul 2017 11:57:11 +0900 Subject: [PATCH 02/16] sensord: increase timeout time a specific command takes more than a second sometimes (e.g., permission checking with cynara initialization). so timeout time should be increased. (3sec) Change-Id: Ib886303eb4c847568f2ebbc9db797873b0779329 Signed-off-by: kibak.yoon --- src/shared/socket.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/shared/socket.cpp b/src/shared/socket.cpp index aed28df..8849181 100644 --- a/src/shared/socket.cpp +++ b/src/shared/socket.cpp @@ -29,6 +29,8 @@ #include "sensor_log.h" +#define SOCK_TIMEOUT 3 + using namespace ipc; static bool set_close_on_exec(int fd) @@ -136,7 +138,6 @@ socket::~socket() bool socket::connect(void) { - const int TIMEOUT = 3; sockaddr_un addr; fd_set write_fds; FD_ZERO(&write_fds); @@ -157,7 +158,7 @@ bool socket::connect(void) return false; } - if (!select_fds(m_sock_fd, NULL, &write_fds, TIMEOUT)) { + if (!select_fds(m_sock_fd, NULL, &write_fds, SOCK_TIMEOUT)) { _E("Failed to select for socket[%d]", m_sock_fd); close(); return false; @@ -294,12 +295,11 @@ bool socket::create(const std::string &path) ssize_t socket::send(const void *buffer, size_t size, bool select) const { if (select) { - const int TIMEOUT = 1; fd_set write_fds; FD_ZERO(&write_fds); FD_SET(m_sock_fd, &write_fds); - if (!select_fds(m_sock_fd, NULL, &write_fds, TIMEOUT)) { + if (!select_fds(m_sock_fd, NULL, &write_fds, SOCK_TIMEOUT)) { _E("Failed to send message(timeout)"); return 0; } @@ -311,12 +311,11 @@ ssize_t socket::send(const void *buffer, size_t size, bool select) const ssize_t socket::recv(void* buffer, size_t size, bool select) const { if (select) { - const int TIMEOUT = 1; fd_set read_fds; FD_ZERO(&read_fds); FD_SET(m_sock_fd, &read_fds); - if (!select_fds(m_sock_fd, &read_fds, NULL, TIMEOUT)) { + if (!select_fds(m_sock_fd, &read_fds, NULL, SOCK_TIMEOUT)) { _E("Failed to receive message(timeout)"); return 0; } -- 2.7.4 From 17238ab0c43b389fb66869f938e61d071e791d37 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 17 May 2017 13:48:38 +0900 Subject: [PATCH 03/16] sensord: enable samsung pedometer sensor for fused location - URI = http://samsung.com/sensor/healthinfo/pedometer/samsung_pedometer - Model = samsung_pedometer - Vendor = samsung.com Change-Id: Ic6220e0001bc5923e392a7a0dec99860ba47227d Signed-off-by: kibak.yoon --- src/sensor/CMakeLists.txt | 6 + src/sensor/create.cpp | 7 + src/sensor/pedometer/average_filter.cpp | 64 +++++ src/sensor/pedometer/average_filter.h | 48 ++++ src/sensor/pedometer/common.h | 25 ++ src/sensor/pedometer/pedometer.cpp | 84 +++++++ src/sensor/pedometer/pedometer.h | 75 ++++++ src/sensor/pedometer/pedometer_info.h | 46 ++++ src/sensor/pedometer/pedometer_sensor.cpp | 134 ++++++++++ src/sensor/pedometer/pedometer_sensor.h | 50 ++++ src/sensor/pedometer/pedometer_speed_filter.cpp | 161 ++++++++++++ src/sensor/pedometer/pedometer_speed_filter.h | 116 +++++++++ src/sensor/pedometer/savitzky_golay_filter15.cpp | 71 ++++++ src/sensor/pedometer/savitzky_golay_filter15.h | 50 ++++ src/sensor/pedometer/step_detection.cpp | 271 +++++++++++++++++++++ src/sensor/pedometer/step_detection.h | 82 +++++++ src/sensor/pedometer/step_event.h | 33 +++ .../pedometer/zero_crossing_step_detection.cpp | 65 +++++ .../pedometer/zero_crossing_step_detection.h | 56 +++++ 19 files changed, 1444 insertions(+) create mode 100644 src/sensor/pedometer/average_filter.cpp create mode 100644 src/sensor/pedometer/average_filter.h create mode 100644 src/sensor/pedometer/common.h create mode 100644 src/sensor/pedometer/pedometer.cpp create mode 100644 src/sensor/pedometer/pedometer.h create mode 100644 src/sensor/pedometer/pedometer_info.h create mode 100644 src/sensor/pedometer/pedometer_sensor.cpp create mode 100644 src/sensor/pedometer/pedometer_sensor.h create mode 100644 src/sensor/pedometer/pedometer_speed_filter.cpp create mode 100644 src/sensor/pedometer/pedometer_speed_filter.h create mode 100644 src/sensor/pedometer/savitzky_golay_filter15.cpp create mode 100644 src/sensor/pedometer/savitzky_golay_filter15.h create mode 100644 src/sensor/pedometer/step_detection.cpp create mode 100644 src/sensor/pedometer/step_detection.h create mode 100644 src/sensor/pedometer/step_event.h create mode 100644 src/sensor/pedometer/zero_crossing_step_detection.cpp create mode 100644 src/sensor/pedometer/zero_crossing_step_detection.h diff --git a/src/sensor/CMakeLists.txt b/src/sensor/CMakeLists.txt index 9735d8d..388cb3a 100644 --- a/src/sensor/CMakeLists.txt +++ b/src/sensor/CMakeLists.txt @@ -7,6 +7,7 @@ SET(GRAVITY "ON") SET(LINEAR_ACCEL "ON") SET(RV "ON") SET(ORIENTATION "ON") +SET(PEDOMETER "ON") INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/src/shared @@ -59,6 +60,11 @@ FILE(GLOB_RECURSE SRCS ${SRCS} orientation/*.cpp) ADD_DEFINITIONS(-DENABLE_ORIENTATION) ENDIF() +IF("${PEDOMETER}" STREQUAL "ON") +FILE(GLOB_RECURSE SRCS ${SRCS} pedometer/*.cpp) +ADD_DEFINITIONS(-DENABLE_PEDOMETER) +ENDIF() + MESSAGE("Sources: ${SRCS}") ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${PLUGINS_PKGS_LDFLAGS}) diff --git a/src/sensor/create.cpp b/src/sensor/create.cpp index 0dd39b5..3c9b372 100644 --- a/src/sensor/create.cpp +++ b/src/sensor/create.cpp @@ -37,6 +37,9 @@ #ifdef ENABLE_ORIENTATION #include "orientation/orientation_sensor.h" #endif +#ifdef ENABLE_PEDOMETER +#include "pedometer/pedometer_sensor.h" +#endif static std::vector sensors; @@ -82,6 +85,10 @@ extern "C" int create(fusion_sensor_t **fsensors) create_sensor("Orientation Sensor"); #endif +#ifdef ENABLE_PEDOMETER + create_sensor("Pedometer"); +#endif + *fsensors = &sensors[0]; return sensors.size(); } diff --git a/src/sensor/pedometer/average_filter.cpp b/src/sensor/pedometer/average_filter.cpp new file mode 100644 index 0000000..81ca075 --- /dev/null +++ b/src/sensor/pedometer/average_filter.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "average_filter.h" + +#include + +static double mean(double *array, int size) +{ + double avrg = 0; + + for (int i = 0; i < size; ++i) + avrg = avrg + array[i]; + + return avrg / size; +} + +average_filter::average_filter(int sz) +: m_size(sz) +, m_index(0) +, m_ready(false) +{ + m_array = (double *)calloc(sz, sizeof(double)); +} + +average_filter::~average_filter() +{ + if (m_array == NULL) + return; + + free(m_array); + m_array = NULL; + m_size = 0; +} + +double average_filter::filter(double value) +{ + m_array[m_index++] = value; + + if (m_index >= m_size) { + m_ready = true; + m_index = 0; + } + return mean(m_array, (m_ready ? m_size : m_index)); +} + +void average_filter::reset(void) +{ + m_index = 0; + m_ready = false; +} diff --git a/src/sensor/pedometer/average_filter.h b/src/sensor/pedometer/average_filter.h new file mode 100644 index 0000000..e083ce0 --- /dev/null +++ b/src/sensor/pedometer/average_filter.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __AVERAGE_FILTER_H__ +#define __AVERAGE_FILTER_H__ + +#include +#include "common.h" + +class average_filter { +public: + average_filter(int size); + ~average_filter(); + + /************************************************************************ + * Filters input data. + */ + double filter(double value); + + /************************************************************************ + * Resets average filter to initial state. + */ + void reset(void); + +private: + /************************************************************************ + * Average filter state. + */ + double *m_array; + int m_size; + int m_index; + bool m_ready; +}; + +#endif /* __AVERAGE_FILTER_H__ */ diff --git a/src/sensor/pedometer/common.h b/src/sensor/pedometer/common.h new file mode 100644 index 0000000..b1a0fef --- /dev/null +++ b/src/sensor/pedometer/common.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __PEDOMETER_COMMON_H__ +#define __PEDOMETER_COMMON_H__ + +#include + +typedef long long timestamp_t; +#define UNKNOWN_TIMESTAMP ((long long)0x8000000000000000) + +#endif /* __PEDOMETER_COMMON_H__ */ diff --git a/src/sensor/pedometer/pedometer.cpp b/src/sensor/pedometer/pedometer.cpp new file mode 100644 index 0000000..b642746 --- /dev/null +++ b/src/sensor/pedometer/pedometer.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "pedometer.h" +#include "step_event.h" + +#include + +pedometer::pedometer() +: m_step_detection() +, m_total_length(0) +, m_step_count(0) +, m_pedometer_filter() +, m_some_speed(false) +{ +} + +pedometer::~pedometer() +{ +} + +void pedometer::set_savitzky_filter(bool enable) +{ + m_step_detection.set_use_savitzky(enable); +} + +void pedometer::reset(void) +{ + m_total_length = 0; + m_step_count = 0; + m_step_detection.reset(); + m_pedometer_filter.reset(); + m_some_speed = false; +} + +bool pedometer::get_pedometer(timestamp_t timestamp, double acc, pedometer_info *info) +{ + bool result = false; + step_event event; + + if (m_step_detection.get_step(timestamp, acc, &event)) { + if (event.m_timestamp != UNKNOWN_TIMESTAMP) { + m_step_count++; + m_total_length += event.m_step_length; + m_pedometer_filter.get_step(timestamp, event.m_step_length); + double speed = m_pedometer_filter.get_speed(timestamp); + info->timestamp = timestamp; + info->is_step_detected = true; + info->step_count = m_step_count; + info->step_length = event.m_step_length; + info->total_step_length = m_total_length; + info->step_speed = speed; + result = true; + m_some_speed = speed != 0; + } + } + if (m_some_speed) { + double speed = m_pedometer_filter.get_speed(timestamp); + if (speed == 0) { + m_some_speed = false; + info->timestamp = timestamp; + info->is_step_detected = true; + info->step_count = m_step_count; + info->step_length = 0; + info->total_step_length = m_total_length; + info->step_speed = 0; + result = true; + } + } + return result; +} diff --git a/src/sensor/pedometer/pedometer.h b/src/sensor/pedometer/pedometer.h new file mode 100644 index 0000000..3f904d7 --- /dev/null +++ b/src/sensor/pedometer/pedometer.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __PEDOMETER_H__ +#define __PEDOMETER_H__ + +#include "common.h" +#include "step_detection.h" +#include "pedometer_info.h" +#include "pedometer_speed_filter.h" + +/************************************************************************ + * stores pedometer engine state. + */ +class pedometer { +public: + pedometer(); + ~pedometer(); + + /************************************************************************ + * enables/disables savitzky filter. + */ + void set_savitzky_filter(bool enable); + + /************************************************************************ + * resets {@link pedometer} object to initial state. + */ + void reset(void); + + /************************************************************************ + * called on new acceleration event. + * + * @param info + * result of pedometer algorithm. valid only it method returns true. + * @param timestamp + * timestamp of acceleration event in ns. + * @param acc + * vertical component of global acceleration. + * + * @result + * true if new step event was detected. + */ + bool get_pedometer(timestamp_t timestamp, double acc, pedometer_info *info); + +private: + /** detects step and estimates step length. */ + step_detection m_step_detection; + + /** sum of lengths all steps from start. */ + double m_total_length; + + /** number of steps from start. */ + long long m_step_count; + + /** estimates current speed from step length. */ + pedometer_speed_filter m_pedometer_filter; + + /** some non zero speed was detected. */ + bool m_some_speed; +}; + +#endif /* __PEDOMETER_H__ */ diff --git a/src/sensor/pedometer/pedometer_info.h b/src/sensor/pedometer/pedometer_info.h new file mode 100644 index 0000000..ac521db --- /dev/null +++ b/src/sensor/pedometer/pedometer_info.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __PEDOMETER_INFO_H__ +#define __PEDOMETER_INFO_H__ + +#include "common.h" + +/************************************************************************ + * stores information about pedometer event detected. + */ +class pedometer_info { +public: + /** timestamp this event was detected in ns. */ + timestamp_t timestamp; + + /** is step detected. */ + bool is_step_detected; + + /** step count from scanner start. */ + long long step_count; + + /** step length in meters. */ + double step_length; + + /** total length of all steps detected from scanner start in meters. */ + double total_step_length; + + /** current mean speed in m/s. */ + double step_speed; +}; + +#endif /* __PEDOMETER_INFO_H__ */ diff --git a/src/sensor/pedometer/pedometer_sensor.cpp b/src/sensor/pedometer/pedometer_sensor.cpp new file mode 100644 index 0000000..bbd9b67 --- /dev/null +++ b/src/sensor/pedometer/pedometer_sensor.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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. + * + */ + +#include "pedometer_sensor.h" + +#include +#include +#include +#include + +#define NAME_SENSOR "http://samsung.com/sensor/healthinfo/pedometer/samsung_pedometer" +#define NAME_VENDOR "samsung.com" + +#define SRC_ID_ACC 0x1 +#define SRC_STR_ACC "http://tizen.org/sensor/general/accelerometer" + +#define NORM(x, y, z) sqrt((x)*(x) + (y)*(y) + (z)*(z)) + +#define US_TO_NS(x) (x * 1000) + +/* Sensor information */ +static sensor_info2_t sensor_info = { + id: 0x1, + type: HUMAN_PEDOMETER_SENSOR, + uri: NAME_SENSOR, + vendor: NAME_VENDOR, + min_range: 0, + max_range: 1, + resolution: 1, + min_interval: 0, + max_batch_count: 0, + wakeup_supported: false, + privilege: "http://tizen.org/privilege/healthinfo", +}; + +/* Required sensor list */ +static required_sensor_s required_sensors[] = { + {SRC_ID_ACC, SRC_STR_ACC} +}; + +pedometer_sensor::pedometer_sensor() +: m_step_count(-1) +, m_step_length(-1) +, m_step_total_length(-1) +, m_step_speed(-1) +, m_time(0) +{ +} + +pedometer_sensor::~pedometer_sensor() +{ +} + +int pedometer_sensor::get_sensor_info(const sensor_info2_t **info) +{ + *info = &sensor_info; + return OP_SUCCESS; +} + +int pedometer_sensor::get_required_sensors(const required_sensor_s **sensors) +{ + *sensors = required_sensors; + + /* You should return the number of required sensor */ + return 1; +} + +int pedometer_sensor::update(uint32_t id, sensor_data_t *data, int len) +{ + pedometer_info info; + double acc = NORM(data->values[0], data->values[1], data->values[2]); + + if (!m_pedometer.get_pedometer(US_TO_NS(data->timestamp), acc, &info)) + return OP_ERROR; + + m_step_count = info.step_count; + m_step_length = info.step_length; + m_step_total_length = info.total_step_length; + m_step_speed = info.step_speed; + m_time = data->timestamp; + + _D("[%lld] %lld %f %f %f", data->timestamp, + info.step_count, info.step_length, info.total_step_length, info.step_speed); + + return OP_SUCCESS; +} + +int pedometer_sensor::get_data(sensor_data_t **data, int *len) +{ + sensor_data_t *sensor_data; + sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t)); + + sensor_data->accuracy = SENSOR_ACCURACY_GOOD; + sensor_data->timestamp = m_time; + sensor_data->value_count = 8; + sensor_data->values[0] = (float)m_step_count; + sensor_data->values[1] = (float)m_step_count; + sensor_data->values[2] = 0; + sensor_data->values[3] = m_step_total_length; + sensor_data->values[4] = 0; + sensor_data->values[5] = m_step_speed; + sensor_data->values[6] = 0; + sensor_data->values[7] = 0; + + *data = sensor_data; + *len = sizeof(sensor_data_t); + + return 0; +} + +int pedometer_sensor::start(observer_h ob) +{ + m_pedometer.reset(); + return OP_DEFAULT; +} + +int pedometer_sensor::stop(observer_h ob) +{ + return OP_DEFAULT; +} diff --git a/src/sensor/pedometer/pedometer_sensor.h b/src/sensor/pedometer/pedometer_sensor.h new file mode 100644 index 0000000..32153b3 --- /dev/null +++ b/src/sensor/pedometer/pedometer_sensor.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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 __PEDOMETER_SENSOR_H__ +#define __PEDOMETER_SENSOR_H__ + +#include +#include + +#include "pedometer.h" + +class pedometer_sensor : public fusion_sensor { +public: + pedometer_sensor(); + virtual ~pedometer_sensor(); + + int get_sensor_info(const sensor_info2_t **info); + int get_required_sensors(const required_sensor_s **sensors); + + int update(uint32_t id, sensor_data_t *data, int len); + int get_data(sensor_data_t **data, int *len); + + int start(observer_h ob); + int stop(observer_h ob); + +private: + long long m_step_count; + float m_step_length; + float m_step_total_length; + float m_step_speed; + unsigned long long m_time; + + pedometer m_pedometer; +}; + +#endif /* __PEDOMETER_SENSOR_H__ */ diff --git a/src/sensor/pedometer/pedometer_speed_filter.cpp b/src/sensor/pedometer/pedometer_speed_filter.cpp new file mode 100644 index 0000000..d6ac774 --- /dev/null +++ b/src/sensor/pedometer/pedometer_speed_filter.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "pedometer_speed_filter.h" + +/** default for maximum step duration in ns. currently 2s. */ +#define STEP_MAX_DURATION 2000000000L + +pedometer_speed_filter::pedometer_speed_filter() +: m_last_timestamp(UNKNOWN_TIMESTAMP) +, m_current_speed(0) +, m_last_step_length(0) +, m_last_step_duration(0) +, m_step_max_duration(STEP_MAX_DURATION) +{ +} + +pedometer_speed_filter::~pedometer_speed_filter() +{ +} + +/************************************************************************ + * clears current speed, last step length and last step duration. + */ +void pedometer_speed_filter::clear_speed(void) +{ + m_current_speed = 0; + m_last_step_length = 0; + m_last_step_duration = 0; +} + +/************************************************************************ + * sets new maximum step duration in ns. + * if there is no new speed during this time current speed is cleared. + * 0 disables this feature. + * + * @param step_max_duration + * maximum step duration in ns. + * 0 to disable step duration checking. + */ +void pedometer_speed_filter::set_step_max_duration(long long step_max_duration) +{ + m_step_max_duration = step_max_duration; +} + +/************************************************************************ + * called when new step detection event occurs. + * + * @param timestamp + * timestamp of step detection event in ns. + * @param steplength + * length of detected step in m. + */ +void pedometer_speed_filter::get_step(timestamp_t timestamp, double step_length) +{ + if (m_last_timestamp == UNKNOWN_TIMESTAMP || timestamp == UNKNOWN_TIMESTAMP) { + clear_speed(); + } else if (m_step_max_duration != 0 && timestamp - m_last_timestamp > m_step_max_duration) { + clear_speed(); + } else if (m_last_timestamp < timestamp) { + double step_duration = (timestamp - m_last_timestamp) / 1e9; + m_current_speed = + (step_length + m_last_step_length) / (step_duration + m_last_step_duration); + m_last_step_length = step_length; + m_last_step_duration = step_duration; + } else { + return; + } + m_last_timestamp = timestamp; +} + +/************************************************************************ + * reports new speed. + * + * @param timestamp + * timestamp of speed event. + * @param speed + * current speed in m/s. + */ +void pedometer_speed_filter::new_speed(timestamp_t timestamp, double speed) +{ + if (m_last_timestamp == UNKNOWN_TIMESTAMP || timestamp == UNKNOWN_TIMESTAMP + || timestamp > m_last_timestamp) { + m_last_timestamp = timestamp; + m_current_speed = speed; + m_last_step_length = 0; + m_last_step_duration = 0; + } +} + +/************************************************************************ + * returns current speed. + * + * @param timestamp + * timestamp for which speed should be calculated. + * @return speed for given timestamp in m/s. + */ +double pedometer_speed_filter::get_speed(timestamp_t timestamp) +{ + if (m_step_max_duration != 0 && (m_last_timestamp == UNKNOWN_TIMESTAMP || + timestamp == UNKNOWN_TIMESTAMP || + timestamp - m_last_timestamp > m_step_max_duration)) { + clear_speed(); + } + return m_current_speed; +} + +/************************************************************************ + * changes current speed. + * + * @param speed + * current speed in m/s. + */ +void pedometer_speed_filter::set_current_speed(double speed) +{ + m_current_speed = speed; +} + +/************************************************************************ + * @return estimated current speed in m/s. + */ +double pedometer_speed_filter::get_current_speed(void) +{ + return m_current_speed; +} + +/************************************************************************ + */ +bool pedometer_speed_filter::is_known_timestamp(void) +{ + return m_last_timestamp != UNKNOWN_TIMESTAMP; +} + +/************************************************************************ + */ +timestamp_t pedometer_speed_filter::get_timestamp(void) +{ + return m_last_timestamp; +} + +/************************************************************************ + * resets filter to initial state. + */ +void pedometer_speed_filter::reset(void) +{ + m_last_timestamp = UNKNOWN_TIMESTAMP; + clear_speed(); +} diff --git a/src/sensor/pedometer/pedometer_speed_filter.h b/src/sensor/pedometer/pedometer_speed_filter.h new file mode 100644 index 0000000..4c6fde1 --- /dev/null +++ b/src/sensor/pedometer/pedometer_speed_filter.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __PEDOMETER_SPEED_FILTER_H__ +#define __PEDOMETER_SPEED_FILTER_H__ + +#include "common.h" + +/************************************************************************ + * stores pedometer speed filter state. + */ +class pedometer_speed_filter { +public: + pedometer_speed_filter(); + ~pedometer_speed_filter(); + + void clear_speed(void); + + /************************************************************************ + * sets new maximum step duration in ns. + * if there is no new speed during this time current speed is cleared. + * 0 disables this feature. + * + * @param step_max_duration + * maximum step duration in ns. + * 0 to disable step duration checking. + */ + void set_step_max_duration(long long step_max_duration); + + /************************************************************************ + * called when new step detection event occurs. + * + * @param timestamp + * timestamp of step detection event in ns. + * @param steplength + * length of detected step in m. + */ + void get_step(timestamp_t timestamp, double step_length); + + /************************************************************************ + * reports new speed. + * + * @param timestamp + * timestamp of speed event. + * @param speed + * current speed in m/s. + */ + void new_speed(timestamp_t timestamp, double speed); + + /************************************************************************ + * returns current speed. + * + * @param timestamp + * timestamp for which speed should be calculated. + * @return speed for given timestamp in m/s. + */ + double get_speed(timestamp_t timestamp); + + /************************************************************************ + * changes current speed. + * + * @param speed + * current speed in m/s. + */ + void set_current_speed(double speed); + + /************************************************************************ + * @return estimated current speed in m/s. + */ + double get_current_speed(void); + + /************************************************************************ + */ + bool is_known_timestamp(void); + + /************************************************************************ + * @return timestamp of last step detection event in ns. + */ + timestamp_t get_timestamp(void); + + /************************************************************************ + * resets filter to initial state. + */ + void reset(void); + +private: + /** timestamp of last step detection event in ns. */ + timestamp_t m_last_timestamp; + + /** estimated current speed in m/s. */ + double m_current_speed; + + /** length of last step in m. */ + double m_last_step_length; + + /** duration of last step in s. */ + double m_last_step_duration; + + /** maximum step duration in ns. 0 to disable step duration checking. */ + long long m_step_max_duration; +}; + +#endif /* __PEDOMETER_SPEED_FILTER_H__ */ diff --git a/src/sensor/pedometer/savitzky_golay_filter15.cpp b/src/sensor/pedometer/savitzky_golay_filter15.cpp new file mode 100644 index 0000000..ced5d8f --- /dev/null +++ b/src/sensor/pedometer/savitzky_golay_filter15.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "savitzky_golay_filter15.h" + +#include + +/* length of filter. changing it requires changing coef_array! */ +#define ARRAY_SIZE 15 + +/* sum of numerators of elements in coef_array. */ +#define SUM_COEF 1105.0 + +/* array with coefficients for savitzky-golay filter. must be length of n! */ +static double coef_array[] = { + -78 / SUM_COEF, -13 / SUM_COEF, 42 / SUM_COEF, 87 / SUM_COEF, + 122 / SUM_COEF, 147 / SUM_COEF, 162 / SUM_COEF, 167 / SUM_COEF, + 162 / SUM_COEF, 147 / SUM_COEF, 122 / SUM_COEF, 87 / SUM_COEF, + 42 / SUM_COEF, -13 / SUM_COEF, -78 / SUM_COEF }; + +savitzky_golay_filter15::savitzky_golay_filter15() +: m_empty(true) +{ + m_array = (double *)calloc(ARRAY_SIZE, sizeof(double)); +} + +savitzky_golay_filter15::~savitzky_golay_filter15() +{ + if (m_array == NULL) + return; + + free(m_array); + m_array = NULL; +} + +double savitzky_golay_filter15::filter(double value) +{ + if (m_empty) { + for (int i = 0; i < ARRAY_SIZE; i++) + m_array[i] = value; + m_empty = false; + return value; + } + + for (int i = 1; i < ARRAY_SIZE; i++) + m_array[i - 1] = m_array[i]; + m_array[ARRAY_SIZE - 1] = value; + + double avrg = 0; + for (int i = 0; i < ARRAY_SIZE; i++) + avrg += m_array[i] * coef_array[i]; + return avrg; +} + +void savitzky_golay_filter15::reset(void) +{ + m_empty = true; +} diff --git a/src/sensor/pedometer/savitzky_golay_filter15.h b/src/sensor/pedometer/savitzky_golay_filter15.h new file mode 100644 index 0000000..a9a8899 --- /dev/null +++ b/src/sensor/pedometer/savitzky_golay_filter15.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __SAVITZKYGOLAYFILTER15_H__ +#define __SAVITZKYGOLAYFILTER15_H__ + +#include +#include "common.h" + +/************************************************************************ + * stores savitzky-golay filter state. + */ +class savitzky_golay_filter15 { +public: + savitzky_golay_filter15(); + ~savitzky_golay_filter15(); + + /************************************************************************ + * filters input data. + * + * @param value + * data to filter. + * @result filtered data. + */ + double filter(double value); + + /************************************************************************ + * resets savitzky-golay filter to initial state. + */ + void reset(void); + +private: + double *m_array; + bool m_empty; +}; + +#endif /* __SAVITZKYGOLAYFILTER15_H__ */ diff --git a/src/sensor/pedometer/step_detection.cpp b/src/sensor/pedometer/step_detection.cpp new file mode 100644 index 0000000..afabc84 --- /dev/null +++ b/src/sensor/pedometer/step_detection.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "step_detection.h" + +#include +#include + +/* Size of average filter. */ +#define AV_FILTER_SIZE 7 + +#define AV_GFILTER_SIZE 500 + +#define FAST_PEAK_THRESHOLD 0.77 + +#define SLOW_PEAK_THRESHOLD 0.3 + +#define PEAK_THRESHOLD_FOR_MEAN 2.0 + +#define B_COEF 1.08 + +#define SLOPE_PARAM -0.75 + +step_detection::step_detection() +: m_average_filter(AV_FILTER_SIZE) +, m_average_gfilter(AV_GFILTER_SIZE) +, m_zero_crossing_up(true) +, m_zero_crossing_down(false) +, m_zc_filter() +, m_peak_threshold(FAST_PEAK_THRESHOLD) +, m_use_savitzky(false) +, m_last_step_timestamp(UNKNOWN_TIMESTAMP) +, m_zero_crossing_up_detected(false) +, m_zero_crossing_down_detected(false) +, m_minimum_acceleration(0) +, m_maximum_acceleration(0) +, m_is_slow_step_detected(false) +{ +} + +step_detection::~step_detection() +{ +} + +/************************************************************************ + */ +void step_detection::reset(void) +{ + m_average_filter.reset(); + m_average_gfilter.reset(); + m_zero_crossing_up.reset(); + m_zero_crossing_down.reset(); + + m_average_gfilter.filter(9.81); + m_zc_filter.reset(); + + m_zero_crossing_up_detected = false; + m_zero_crossing_down_detected = false; + m_minimum_acceleration = 0; + m_maximum_acceleration = 0; + m_is_slow_step_detected = false; +} + +/************************************************************************ + */ +void step_detection::set_peak_threshold(double threshold) +{ + m_peak_threshold = threshold; +} + +/************************************************************************ + */ +void step_detection::set_use_savitzky(bool use_savitzky) +{ + m_use_savitzky = use_savitzky; +} + +/************************************************************************ + */ +bool step_detection::is_slow_step(void) +{ + return m_is_slow_step_detected; +} + +/************************************************************************ + */ +static double cal_step_length(double time, double sqrt4peak_valley_diff) +{ + double step_length = 0; + if (time <= 0 || time > 1.00) { + step_length = 0.50 * sqrt4peak_valley_diff; + } else if (time < 0.3) { + step_length = 0; + } else { + step_length = B_COEF + SLOPE_PARAM * time; + } + + if (step_length > 1.5) + step_length = 0; + + return step_length; +} + +/************************************************************************ + */ +bool step_detection::add_acc_sensor_values_average( + timestamp_t timestamp, double acc, step_event* step) +{ + double acceleration = m_average_filter.filter(acc - 9.8066f); + + bool n_zero_up = m_zero_crossing_up.detect_step(timestamp, acceleration); + bool n_zero_down = m_zero_crossing_down.detect_step(timestamp, acceleration); + + double sqrt4peak_valley_diff = 0; + bool is_step_detected = false; + + if (n_zero_up) { + m_zero_crossing_up_detected = true; + m_zero_crossing_down_detected = false; + } + if (n_zero_down) { + m_zero_crossing_up_detected = false; + m_zero_crossing_down_detected = true; + } + if (m_zero_crossing_up_detected) { + if (m_maximum_acceleration < acceleration) { + m_maximum_acceleration = acceleration; + } + } + if (m_zero_crossing_down_detected) { + if (m_minimum_acceleration > acceleration) { + m_minimum_acceleration = acceleration; + } + } + + double peak_threshold; + if (m_zero_crossing_up.m_time_sum / 1E9 < 1.2) { + peak_threshold = m_peak_threshold; + m_is_slow_step_detected = false; + } else { + peak_threshold = SLOW_PEAK_THRESHOLD; + m_is_slow_step_detected = true; + } + + if (n_zero_down) { + if (m_maximum_acceleration > peak_threshold + || (m_maximum_acceleration - m_minimum_acceleration > PEAK_THRESHOLD_FOR_MEAN)) { + sqrt4peak_valley_diff = pow(m_maximum_acceleration - m_minimum_acceleration, 0.25); + m_minimum_acceleration = 0; + m_maximum_acceleration = 0; + is_step_detected = true; + } + } + + if (m_zero_crossing_up.m_time_sum / 1E9 < 0.3) + is_step_detected = false; + + if (is_step_detected) { + if (m_last_step_timestamp == UNKNOWN_TIMESTAMP) + m_last_step_timestamp = timestamp; + + double time = (timestamp - m_last_step_timestamp) / 1E9; + m_last_step_timestamp = timestamp; + m_zero_crossing_up.m_time_sum = 0; + step->m_timestamp = timestamp; + step->m_step_length = cal_step_length(time, sqrt4peak_valley_diff); + + return true; + } + return false; +} + +/************************************************************************ + */ +bool step_detection::add_acc_sensor_values_savitzky( + timestamp_t timestamp, double acc, step_event* step) +{ + double acceleration = m_zc_filter.filter(acc - m_average_gfilter.filter(acc)); + bool n_zero_up = m_zero_crossing_up.detect_step(timestamp, acceleration); + bool n_zero_down = m_zero_crossing_down.detect_step(timestamp, acceleration); + + double sqrt4peak_valley_diff = 0; + bool is_step_detected = false; + + if (n_zero_up) { + m_zero_crossing_up_detected = true; + m_zero_crossing_down_detected = false; + } + if (n_zero_down) { + m_zero_crossing_up_detected = false; + m_zero_crossing_down_detected = true; + } + if (m_zero_crossing_up_detected) { + if (m_maximum_acceleration < acceleration) { + m_maximum_acceleration = acceleration; + } + } + if (m_zero_crossing_down_detected) { + if (m_minimum_acceleration > acceleration) { + m_minimum_acceleration = acceleration; + } + } + + bool zup = m_zero_crossing_up.m_time_sum / 1E9 > 1.2; + if (n_zero_down) { + is_step_detected = false; + + if ((m_maximum_acceleration > 0.6 && + m_minimum_acceleration < -0.852) + || (m_maximum_acceleration > 0.714 + && m_minimum_acceleration < -0.455)) { + is_step_detected = true; + m_is_slow_step_detected = false; + } + if (m_maximum_acceleration - m_minimum_acceleration > 3.32) { + is_step_detected = true; + m_is_slow_step_detected = false; + } + if (zup && m_maximum_acceleration > 0.764 && m_minimum_acceleration < -0.0235) {// slow steps + is_step_detected = true; + m_is_slow_step_detected = true; + } + + if (is_step_detected) { + sqrt4peak_valley_diff = pow(m_maximum_acceleration - m_minimum_acceleration, 0.25); + m_minimum_acceleration = 0.0; + m_maximum_acceleration = 0.0; + } + } + + if (m_zero_crossing_up.m_time_sum / 1E9 < 0.3) + is_step_detected = false; + + if (is_step_detected) { + if (m_last_step_timestamp == UNKNOWN_TIMESTAMP) + m_last_step_timestamp = timestamp; + + double time = (timestamp - m_last_step_timestamp) / 1E9; + + m_last_step_timestamp = timestamp; + m_zero_crossing_up.m_time_sum = 0; + step->m_timestamp = timestamp; + step->m_step_length = cal_step_length(time, sqrt4peak_valley_diff); + + return true; + } + + return false; +} + +/************************************************************************ + */ +bool step_detection::get_step(timestamp_t timestamp, double acc, step_event* step) +{ + return m_use_savitzky + ? add_acc_sensor_values_savitzky(timestamp, acc, step) + : add_acc_sensor_values_average(timestamp, acc, step); +} diff --git a/src/sensor/pedometer/step_detection.h b/src/sensor/pedometer/step_detection.h new file mode 100644 index 0000000..addd786 --- /dev/null +++ b/src/sensor/pedometer/step_detection.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __STEP_DETECTION_H__ +#define __STEP_DETECTION_H__ + +#include "average_filter.h" +#include "zero_crossing_step_detection.h" +#include "savitzky_golay_filter15.h" +#include "step_event.h" +#include "common.h" + +/************************************************************************ + * step detection engine state. + */ +class step_detection { +public: + step_detection(); + ~step_detection(); + + /************************************************************************ + */ + void set_peak_threshold(double threshold); + + /************************************************************************ + */ + void set_use_savitzky(bool use_savitzky); + + /************************************************************************ + */ + bool is_slow_step(void); + + /************************************************************************ + */ + bool add_acc_sensor_values_average( + timestamp_t timestamp, double acc, step_event* step); + + /************************************************************************ + */ + bool add_acc_sensor_values_savitzky( + timestamp_t timestamp, double acc, step_event* step); + + /************************************************************************ + */ + bool get_step(timestamp_t timestamp, double acc, step_event* step); + + /************************************************************************ + * resets step_detection object to initial state. + */ + void reset(void); + +private: + average_filter m_average_filter; + average_filter m_average_gfilter; + zero_crossing_step_detection m_zero_crossing_up; + zero_crossing_step_detection m_zero_crossing_down; + + savitzky_golay_filter15 m_zc_filter; + double m_peak_threshold; + bool m_use_savitzky; + timestamp_t m_last_step_timestamp; + bool m_zero_crossing_up_detected; + bool m_zero_crossing_down_detected; + double m_minimum_acceleration; + double m_maximum_acceleration; + bool m_is_slow_step_detected; +}; + +#endif /* __STEP_DETECTION_H__ */ diff --git a/src/sensor/pedometer/step_event.h b/src/sensor/pedometer/step_event.h new file mode 100644 index 0000000..724f262 --- /dev/null +++ b/src/sensor/pedometer/step_event.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __STEP_EVENT_H__ +#define __STEP_EVENT_H__ + +#include "common.h" + +class step_event { +public: + step_event() + : m_timestamp(UNKNOWN_TIMESTAMP) + , m_step_length(0) + {} + + timestamp_t m_timestamp; + double m_step_length; +}; + +#endif /* __STEP_EVENT_H__ */ diff --git a/src/sensor/pedometer/zero_crossing_step_detection.cpp b/src/sensor/pedometer/zero_crossing_step_detection.cpp new file mode 100644 index 0000000..aff2b3c --- /dev/null +++ b/src/sensor/pedometer/zero_crossing_step_detection.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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. + */ + +#include "zero_crossing_step_detection.h" + +static bool detect_zero_crossing(double last_accel, double new_accel, bool up) +{ + if (up) + return (last_accel < 0 && new_accel >= 0); + + return (last_accel > 0 && new_accel <= 0); +} + +zero_crossing_step_detection::zero_crossing_step_detection(bool up) +: m_time_sum(0) +, m_up(up) +, m_last_acceleration(0) +, m_last_timestamp(UNKNOWN_TIMESTAMP) +, m_last_zero_crossing_time(UNKNOWN_TIMESTAMP) +{ +} + +zero_crossing_step_detection::~zero_crossing_step_detection() +{ +} + +bool zero_crossing_step_detection::detect_step(timestamp_t timestamp, double acceleration) +{ + bool step_detected = false; + + if (m_last_timestamp != UNKNOWN_TIMESTAMP) { + // zero crossing detected + if (detect_zero_crossing(m_last_acceleration, acceleration, m_up)) { + m_time_sum += timestamp - m_last_timestamp; + m_last_timestamp = timestamp; + m_last_zero_crossing_time = timestamp; + step_detected = true; + } + } else { + m_last_timestamp = timestamp; + } + m_last_acceleration = acceleration; + return step_detected; +} + +void zero_crossing_step_detection::reset(void) +{ + m_last_acceleration = 0; + m_time_sum = 0; + m_last_timestamp = UNKNOWN_TIMESTAMP; + m_last_zero_crossing_time = UNKNOWN_TIMESTAMP; +} diff --git a/src/sensor/pedometer/zero_crossing_step_detection.h b/src/sensor/pedometer/zero_crossing_step_detection.h new file mode 100644 index 0000000..79ca518 --- /dev/null +++ b/src/sensor/pedometer/zero_crossing_step_detection.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd. + * + * 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 __ZERO_CROSSING_STEP_DETECTION_H__ +#define __ZERO_CROSSING_STEP_DETECTION_H__ + +#include "common.h" + +/************************************************************************ + * zero crossing detection engine state. + */ +class zero_crossing_step_detection { +public: + zero_crossing_step_detection(bool up); + ~zero_crossing_step_detection(); + + /************************************************************************ + */ + bool detect_step(timestamp_t timestamp, double acceleration); + + /************************************************************************ + */ + void reset(void); + + timestamp_t m_time_sum; + +private: + /** + * for true detects zero up crossing, for false detects zero down crossing. + */ + bool m_up; + + /** acceleration in previous detect step. */ + double m_last_acceleration; + + /** timestamp of last acc event. unknown time if no one. */ + timestamp_t m_last_timestamp; + + /** timestamp of last detected zero crossing. unknown time if not yet detected. */ + timestamp_t m_last_zero_crossing_time; +}; + +#endif /* __ZERO_CROSSING_STEP_DETECTION_H__ */ -- 2.7.4 From c9e0b6aa6d893a9e6fc26e25d8426feb59dcdf94 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 3 Aug 2017 21:05:11 +0900 Subject: [PATCH 04/16] sensord: remove excessive sensor log when socket buffer is full Change-Id: I70930ff13ac406a6c8a5418f3404cbfb83e3c32b Signed-off-by: kibak.yoon --- src/shared/channel.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shared/channel.cpp b/src/shared/channel.cpp index e407aee..446c881 100644 --- a/src/shared/channel.cpp +++ b/src/shared/channel.cpp @@ -155,9 +155,8 @@ bool channel::send(message *msg) { retv_if(!m_loop, false); - /* TODO: check buffer size(is there any linux api for this?) */ int cur_buffer_size = m_socket->get_current_buffer_size(); - retvm_if(cur_buffer_size > SYSTEMD_SOCK_BUF_SIZE, false, "Failed to send data"); + retv_if(cur_buffer_size > SYSTEMD_SOCK_BUF_SIZE, false); send_event_handler *handler = new(std::nothrow) send_event_handler(this, msg); retvm_if(!handler, false, "Failed to allocate memory"); -- 2.7.4 From c5aaf8cbb2b6bbbac2420636f41cba98d8ccc336 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Fri, 4 Aug 2017 00:37:13 +0900 Subject: [PATCH 05/16] sensord: ternimate sensord instantly when signal is received Change-Id: I1993404cf85cf92427ccaf69a28dbe88a461134d Signed-off-by: kibak.yoon --- src/server/server.cpp | 2 +- src/shared/event_loop.cpp | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/server/server.cpp b/src/server/server.cpp index 237f658..a411340 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -96,8 +96,8 @@ bool server::init(void) void server::deinit(void) { - m_manager->deinit(); m_server->close(); + m_manager->deinit(); delete m_server; m_server = NULL; diff --git a/src/shared/event_loop.cpp b/src/shared/event_loop.cpp index 1b569a1..c3a698b 100644 --- a/src/shared/event_loop.cpp +++ b/src/shared/event_loop.cpp @@ -238,12 +238,7 @@ void event_loop::stop(void) { ret_if(!is_running() || m_terminating.load()); - uint64_t term = 1; - ssize_t size; - m_terminating.store(true); - size = write(m_term_fd, &term, sizeof(uint64_t)); - - retm_if(size != sizeof(ssize_t), "Failed to write[%d]", m_term_fd); + terminate(); } void event_loop::terminate(void) -- 2.7.4 From b0d9ce9e1eabd744274000bdd2934a2d4f5fb04c Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Fri, 4 Aug 2017 00:38:29 +0900 Subject: [PATCH 06/16] sensord: fix bug with incorrect bit operation Change-Id: I29c35c9b923d572fbe0b39aa7fe5913386f77bb2 Signed-off-by: kibak.yoon --- src/shared/event_loop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/event_loop.cpp b/src/shared/event_loop.cpp index c3a698b..4f9e7ed 100644 --- a/src/shared/event_loop.cpp +++ b/src/shared/event_loop.cpp @@ -43,7 +43,7 @@ static gboolean g_io_handler(GIOChannel *ch, GIOCondition condition, gpointer da cond = (unsigned int)condition; if (cond & (G_IO_HUP)) - cond &= ~(G_IO_IN & G_IO_OUT); + cond &= ~(G_IO_IN | G_IO_OUT); handler_info *info = (handler_info *)data; id = info->id; -- 2.7.4 From 59055558123e4d54d1407c48fa11a80575121092 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Fri, 4 Aug 2017 10:34:49 +0900 Subject: [PATCH 07/16] sensord: add null check after malloc Change-Id: I6f01e8f46be1e08999bc0f35871fc675ba7ebeb8 Signed-off-by: kibak.yoon --- src/sensor/pedometer/pedometer_sensor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sensor/pedometer/pedometer_sensor.cpp b/src/sensor/pedometer/pedometer_sensor.cpp index bbd9b67..d16bdcc 100644 --- a/src/sensor/pedometer/pedometer_sensor.cpp +++ b/src/sensor/pedometer/pedometer_sensor.cpp @@ -103,6 +103,7 @@ int pedometer_sensor::get_data(sensor_data_t **data, int *len) { sensor_data_t *sensor_data; sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t)); + retvm_if(!sensor_data, -ENOMEM, "Failed to allocate memory"); sensor_data->accuracy = SENSOR_ACCURACY_GOOD; sensor_data->timestamp = m_time; -- 2.7.4 From 27411362d91803c8c0ab6e8d3688592b141e8037 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Fri, 4 Aug 2017 10:09:34 +0900 Subject: [PATCH 08/16] sensord: version 4.0.2 Change-Id: Id1c588dda1ae5d446f158afeea96b7d94bfff82e Signed-off-by: kibak.yoon --- packaging/sensord.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index d081956..b96b6fe 100644 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -1,6 +1,6 @@ Name: sensord Summary: Sensor daemon -Version: 4.0.1 +Version: 4.0.2 Release: 1 Group: System/Sensor Framework License: Apache-2.0 -- 2.7.4 From 7c9813c0be7c00cf1feaf1718f01ecfde399892a Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Wed, 9 Aug 2017 19:39:52 +0900 Subject: [PATCH 09/16] sensord: fix double-free issue - If the server is terminated unexpectedly, sensor library releases the memory of channel automatically. At that time, if client calls disconnect(), double-free problem is invoked. - Because it is right situation to call disconnect() explicitly, the auto-release code should be removed. Change-Id: I31894354eb2d11549dbe0382ce865de6beea89d4 Signed-off-by: kibak.yoon --- src/shared/channel_event_handler.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/shared/channel_event_handler.cpp b/src/shared/channel_event_handler.cpp index 6ca1e25..cc8a2bb 100644 --- a/src/shared/channel_event_handler.cpp +++ b/src/shared/channel_event_handler.cpp @@ -46,14 +46,12 @@ bool channel_event_handler::handle(int fd, event_condition condition) if (condition & (EVENT_HUP)) { m_ch->disconnect(); - delete m_ch; m_ch = NULL; return false; } if (!m_ch->read_sync(msg, false)) { m_ch->disconnect(); - delete m_ch; m_ch = NULL; return false; } -- 2.7.4 From ff891178a7a8147538ff5de57fb2987555440689 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 19:23:25 +0900 Subject: [PATCH 10/16] sensorctl: clean up log macros of sensorctl Change-Id: I7aff53066afae3659700f37ac32a536d39c53c62 Signed-off-by: kibak.yoon --- src/sensorctl/log.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/sensorctl/log.h b/src/sensorctl/log.h index 00cefbd..6bb1130 100644 --- a/src/sensorctl/log.h +++ b/src/sensorctl/log.h @@ -39,12 +39,17 @@ do { \ #define _E(fmt, args...) \ do { \ - g_print("\x1B[31m" fmt "\033[0m", ##args); \ + g_print(_RED fmt _RST, ##args); \ } while (0) #define _I(fmt, args...) \ do { \ - g_print("\x1B[32m" fmt "\033[0m", ##args); \ + g_print(_GRN fmt _RST, ##args); \ +} while (0) + +#define _W(fmt, args...) \ +do { \ + g_print(_YEL fmt _RST, ##args); \ } while (0) #define WARN_IF(expr, fmt, arg...) \ -- 2.7.4 From d42f20dc2e7180d49944d2dd4a894e7e35828881 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 19:26:11 +0900 Subject: [PATCH 11/16] sensorctl: remove unnecessary keyword/macro * change parameter name Change-Id: Iee63054bcf0b752fa0acf29ad087d210056ed606 Signed-off-by: kibak.yoon --- src/sensorctl/injector.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sensorctl/injector.h b/src/sensorctl/injector.h index ca942fc..b487c91 100644 --- a/src/sensorctl/injector.h +++ b/src/sensorctl/injector.h @@ -25,7 +25,6 @@ #include "sensor_manager.h" -#define NAME_MAX_TEST 32 #define INJECTOR_ARGC 4 /* e.g. {sensorctl, inject, wristup, conf} */ #define REGISTER_INJECTOR(sensor_type, event_name, injector_type) \ @@ -51,9 +50,8 @@ private: class injector_manager : public sensor_manager { public: - static void register_injector(injector *injector); + static void register_injector(injector *inject); -public: injector_manager(); virtual ~injector_manager(); -- 2.7.4 From 669c659b33ab8f417abdde207c1864d481c62d4a Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 19:33:32 +0900 Subject: [PATCH 12/16] sensorctl: remove assert macro - [TODO] replace "adapter" with "adaptor" Change-Id: I0f86d2de013616c598b296b014e7331254e6d5ec Signed-off-by: kibak.yoon --- src/sensorctl/sensor_adapter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sensorctl/sensor_adapter.cpp b/src/sensorctl/sensor_adapter.cpp index 82a54a2..13bc4e5 100644 --- a/src/sensorctl/sensor_adapter.cpp +++ b/src/sensorctl/sensor_adapter.cpp @@ -30,12 +30,12 @@ bool sensor_adapter::is_supported(sensor_type_t type) { sensor_t sensor; - int ret; - ret = sensord_get_default_sensor(type, &sensor); - ASSERT_TRUE(ret); + int ret = sensord_get_default_sensor(type, &sensor); + if (ret == 0) + return true; - return true; + return false; } int sensor_adapter::get_count(sensor_type_t type) -- 2.7.4 From e3eeb813d01784a008761e130cb82b400c99fbf0 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 19:44:11 +0900 Subject: [PATCH 13/16] sensorctl: add options/features for usability This patch supports the below options and features. [SYNOPSIS] - sensorctl test auto [--help] [--list] [--filter=] [--verbose] [--shuffle] [--repeat] [--output] - sensorctl test [--interval=NUMBER] [--batch_latency=NUMBER] [--powersave=TYPE] [--repeat=NUMBER] [--output=FILE_PATH] [--help] [--verbose] [Options] -f PATTERN, --filter= Run a subset of the tests for debugging or quickly verifying a change. Sensorctl will only run the tests whose full names match the filter. This can be used to specify multiple search patterns. -l, --list Prints the testcase list by following command. -h, --help Prints the synopsis and a list of the most commonly used commands. -v, --verbose Prints the log message fully while testcases are running. -s, --shuffle Run the testcase randomly. -r NUMBER, --repeat=NUMBER Run the testcase a given number of times. Change-Id: I30dec0ef2896e12c956be294c2677cb785335ec0 Signed-off-by: kibak.yoon --- src/sensorctl/test_bench.cpp | 232 +++++++++++++++++++++++++++++++------------ src/sensorctl/test_bench.h | 49 +++++---- 2 files changed, 200 insertions(+), 81 deletions(-) diff --git a/src/sensorctl/test_bench.cpp b/src/sensorctl/test_bench.cpp index 3b9cd51..db0b974 100644 --- a/src/sensorctl/test_bench.cpp +++ b/src/sensorctl/test_bench.cpp @@ -17,32 +17,108 @@ * */ -#include "log.h" #include "test_bench.h" +#include +#include + +#include "log.h" + /* * Implementation of test_option */ -bool test_option::full_log = false; -std::string test_option::group = ""; - -void test_option::show_full_log(bool show) +bool test_option::verbose = false; +bool test_option::shuffle = false; +bool test_option::show_list = false; +int test_option::repeat = 1; +std::string test_option::filter = ""; +std::string test_option::output = ""; +int test_option::interval = -1; +int test_option::latency = -1; +int test_option::powersave = -1; + +bool test_option::set_options(int argc, char *argv[]) { - full_log = show; -} - -void test_option::set_group(const char *gname) -{ - group = gname; -} + int c; + + while (1) { + static struct option options[] = { + {"list", no_argument, 0, 'l'}, + {"filter", required_argument, 0, 'f'}, + {"verbose", no_argument, 0, 'v'}, + {"shuffle", no_argument, 0, 's'}, + {"repeat", required_argument, 0, 'r'}, + {"output", required_argument, 0, 'o'}, + + /* For manual test*/ + {"interval", required_argument, 0, 'i'}, + {"batch_latency", required_argument, 0, 'b'}, + {"powersave", required_argument, 0, 'p'}, + + {"help", no_argument, 0, 'h'}, + {0, 0, 0, 0} + }; + + int option_index = 0; + c = getopt_long(argc, argv, "lfvsroibph:", options, &option_index); + if (c == -1) + return true; + + switch (c) { + case 0: + break; + case 'l': + _I("== Testcase List ==\n"); + test_bench::show_testcases(); + test_option::show_list = true; + break; + case 'f': + _I("Filter : %s\n", optarg); + if (!optarg) break; + test_option::filter = optarg; + break; + case 'v': + _I("Verbose is on\n"); + test_option::verbose = true; + break; + case 's': + _I("Shuffle is on(Default seed)\n"); + test_option::shuffle = true; + break; + case 'r': + _I("Repeat : %s\n", optarg); + if (!optarg) break; + test_option::repeat = atoi(optarg); + break; + case 'o': + /* [TODO] */ + _W("File output is not supported yet, use $sensorctl > out : %s\n", optarg); + if (!optarg) break; + test_option::output = optarg; + break; + case 'i': + _I("Interval : %s\n", optarg); + if (!optarg) break; + test_option::interval = atoi(optarg); + break; + case 'b': + _I("Batch latency : %s\n", optarg); + if (!optarg) break; + test_option::latency = atoi(optarg); + break; + case 'p': + _I("Power save : %s\n", optarg); + if (!optarg) break; + test_option::powersave = atoi(optarg); + break; + case 'h': + case '?': + default: + return false; + } + } -void test_option::set_options(int argc, char *argv[]) -{ - /* TODO: use getopt() */ - if (argc > 3) - set_group(argv[3]); - if (argc > 4) - show_full_log(atoi(argv[4])); + return true; } /* @@ -51,6 +127,7 @@ void test_option::set_options(int argc, char *argv[]) test_case::test_case(const std::string &group, const std::string &name) : m_group(group) , m_name(name) +, m_fullname(group + "." + m_name) , m_func(NULL) { test_bench::register_testcase(group, this); @@ -58,25 +135,17 @@ test_case::test_case(const std::string &group, const std::string &name) void test_case::started(void) { - _I("[----------]\n"); _I("[ RUN ] "); - _N("%s.%s\n", m_group.c_str(), m_name.c_str()); -} - -void test_case::stopped(void) -{ - _I("[ OK ] "); - _N("%s.%s\n", m_group.c_str(), m_name.c_str()); - _I("[----------]\n"); + _N("%s\n", m_fullname.c_str()); } -void test_case::show(bool result) +void test_case::stopped(bool result) { if (result) - _I("[ PASSED ] "); + _I("[ OK ] "); else _E("[ FAILED ] "); - _N("%s.%s\n", m_group.c_str(), m_name.c_str()); + _N("%s\n", m_fullname.c_str()); } void test_case::run_testcase(void) @@ -85,8 +154,7 @@ void test_case::run_testcase(void) started(); result = (this->*m_func)(); - stopped(); - show(result); + stopped(result); } void test_case::register_func(test_func func) @@ -103,6 +171,11 @@ test_bench& test_bench::instance() return bench; } +void test_bench::show_testcases(void) +{ + instance().show(); +} + void test_bench::register_testcase(const std::string &group, test_case *testcase) { instance().add_testcase(group, testcase); @@ -113,12 +186,15 @@ void test_bench::push_failure(const std::string &function, long line, const std: instance().add_failure(function, line, msg); } -void test_bench::run_all_testcase(void) +void test_bench::run_all_testcases(void) { + if (test_option::show_list) + return; + instance().run(); } -void test_bench::stop_all_testcase(void) +void test_bench::stop_all_testcases(void) { instance().stop(); } @@ -140,13 +216,36 @@ void test_bench::add_failure(const std::string &function, long line, const std:: void test_bench::started(void) { _I("[==========] "); - _N("Running %d testcases\n", count(test_option::group)); + _N("Running %d testcases\n", count()); } void test_bench::stopped(void) { _I("[==========] "); - _N("%d testcases ran\n", count(test_option::group)); + _N("%d testcases ran\n", count()); +} + +void test_bench::show(void) +{ + /* + * [group1] + * [tc name1] + * [tc name2] + * [group2] + * [tc name1] + */ + + for (auto it = testcases.begin(); it != testcases.end(); + it = testcases.upper_bound(it->first)) { + + auto range = testcases.equal_range(it->first); + _I("[%s]\n", it->first.c_str()); + + for (auto testcase = range.first; testcase != range.second; ++testcase) + _N(" * %s\n", testcase->second->name().c_str()); + } + + _I("Testcase Count : %u\n", count()); } void test_bench::show_failures(void) @@ -154,7 +253,8 @@ void test_bench::show_failures(void) _N("================================\n"); if (m_failure_count == 0) { - _N("there was no fail case\n"); + _I("[ PASSED ] "); + _N("%d tests\n", count() - m_failure_count); return; } @@ -166,28 +266,44 @@ void test_bench::show_failures(void) } } +bool test_bench::filter(const std::string &name) +{ + static std::regex filter(test_option::filter.c_str(), std::regex::optimize); + if (!std::regex_match(name, filter)) { + //_W("Not Matched : %s(%s)\n", name.c_str(), test_option::filter.c_str()); + return false; + } + + //_I("Matched : %s(%s)\n", name.c_str(), test_option::filter.c_str()); + return true; +} + void test_bench::run(void) { - std::size_t found; m_failure_count = 0; started(); - for (auto it = testcases.begin(); it != testcases.end(); ++it) { - if (m_stop) - break; + /* For group */ + for (auto it = testcases.begin(); it != testcases.end(); + it = testcases.upper_bound(it->first)) { + if (m_stop) break; + if (!filter(it->second->fullname())) continue; - found = it->first.find("skip"); + auto range = testcases.equal_range(it->first); - if (test_option::group.empty() && found != std::string::npos) - continue; + /* Time measurement for test group */ + clock_t start = clock(); - found = it->first.find(test_option::group); + _I("[----------] %d tests from %s\n", testcases.count(it->first), it->first.c_str()); + for (auto testcase = range.first; testcase != range.second; ++testcase) { + if (m_stop) break; + testcase->second->run_testcase(); + } - if (!test_option::group.empty() && found == std::string::npos) - continue; - - it->second->run_testcase(); + _I("[----------] %d tests from %s (%.4f sec)\n", + testcases.count(it->first), it->first.c_str(), + (double)(clock() - start)/ CLOCKS_PER_SEC); } stopped(); @@ -199,23 +315,15 @@ void test_bench::stop(void) m_stop = true; } -unsigned int test_bench::count(std::string &group) -{ - if (group.empty()) - return testcases.size() - count_by_key("skip"); - - return count_by_key(group.c_str()); -} - -unsigned int test_bench::count_by_key(const char *key) +unsigned int test_bench::count(void) { int count = 0; for (auto it = testcases.begin(); it != testcases.end(); ++it) { - std::size_t found = it->first.find(key); + if (!filter(it->second->fullname())) + continue; - if (found != std::string::npos) - count++; + count++; } return count; diff --git a/src/sensorctl/test_bench.h b/src/sensorctl/test_bench.h index 8525e39..f70fdeb 100644 --- a/src/sensorctl/test_bench.h +++ b/src/sensorctl/test_bench.h @@ -38,7 +38,7 @@ do { \ #define PASS(left, comp, right) \ do { \ - if (test_option::full_log) { \ + if (test_option::verbose) { \ _I("[ PASS ] "); \ std::ostringstream os; \ os << __FUNCTION__ << "(" << __LINE__ << ") : " \ @@ -96,32 +96,37 @@ do { \ } while (0) #define TESTCASE(group, name) \ -class test_case_##group_##name : public test_case { \ +class test_case_##group##_##name : public test_case { \ public: \ - test_case_##group_##name() \ + test_case_##group##_##name() \ : test_case(#group, #name) \ { \ - register_func(static_cast(&test_case_##group_##name::test)); \ + register_func(static_cast(&test_case_##group##_##name::test)); \ } \ bool test(void); \ -} test_case_##group_##name##_instance; \ -bool test_case_##group_##name::test(void) +} test_case_##group##_##name##_instance; \ +bool test_case_##group##_##name::test(void) /* * Declaration of test_option */ class test_option { public: - static bool full_log; - static std::string group; - - static void show_full_log(bool show); - static void set_group(const char *gname); - static void set_options(int argc, char *argv[]); + static bool verbose; + static bool shuffle; /* TODO */ + static bool show_list; + static int repeat; /* TODO */ + static std::string filter; + static std::string output; /* TODO */ + static int interval; + static int latency; + static int powersave; + + static bool set_options(int argc, char *argv[]); }; /* - * Decloaration of test_result + * Declaration of test_result */ class test_result { public: @@ -146,18 +151,19 @@ public: const std::string& group() const { return m_group; } const std::string& name() const { return m_name; } + const std::string& fullname() const { return m_fullname; } protected: typedef bool (test_case::*test_func)(); void started(void); - void stopped(void); - void show(bool result); + void stopped(bool result); void register_func(test_func func); private: const std::string m_group; const std::string m_name; + const std::string m_fullname; test_func m_func; }; @@ -171,10 +177,12 @@ public: , m_stop(false) {} + static void show_testcases(void); + static void register_testcase(const std::string &group, test_case *testcase); - static void run_all_testcase(void); - static void stop_all_testcase(void); + static void run_all_testcases(void); + static void stop_all_testcases(void); static void push_failure(const std::string &function, long line, const std::string &msg); @@ -188,11 +196,14 @@ private: void show_failures(void); void add_testcase(const std::string &group, test_case *testcase); + + bool filter(const std::string &name); void run(void); void stop(void); - unsigned int count(std::string &group); - unsigned int count_by_key(const char *key); + void show(void); + + unsigned int count(void); std::multimap testcases; std::vector results; -- 2.7.4 From 122cf1cbb2140acd69e25e9f8228112a1f87832d Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 20:18:08 +0900 Subject: [PATCH 14/16] sensorctl: seperate auto test and manual test - sensorctl test auto - sensorctl test Change-Id: Id30e09ff8380981699a9c7651af675fd7a370da5 Signed-off-by: kibak.yoon --- src/sensorctl/tester.cpp | 161 +++++++++++----------------------------- src/sensorctl/tester.h | 28 ++++++- src/sensorctl/tester_auto.cpp | 87 ++++++++++++++++++++++ src/sensorctl/tester_manual.cpp | 152 +++++++++++++++++++++++++++++++++++++ 4 files changed, 307 insertions(+), 121 deletions(-) create mode 100644 src/sensorctl/tester_auto.cpp create mode 100644 src/sensorctl/tester_manual.cpp diff --git a/src/sensorctl/tester.cpp b/src/sensorctl/tester.cpp index 4ac906f..e756337 100644 --- a/src/sensorctl/tester.cpp +++ b/src/sensorctl/tester.cpp @@ -27,23 +27,14 @@ #include "log.h" #include "macro.h" #include "mainloop.h" -#include "test_bench.h" -#include "sensor_adapter.h" -#define TESTER_ARGC 3 /* e.g. {sensorctl, test, accelerometer} */ +std::vector tester_manager::testers; -#define MAX_COUNT 999999 -#define TEST_DEFAULT_INTERVAL 100 -#define TEST_DEFAULT_LATENCY 0 -#define TEST_DEFAULT_POWERSAVE_OPTION SENSOR_OPTION_ALWAYS_ON - -static sensor_type_t type; -static int interval; -static int latency; -static int powersave; -static int repeat; - -static int event_count = 0; +tester::tester(const char *name) +: m_name(name) +{ + tester_manager::register_tester(this); +} tester_manager::tester_manager() { @@ -53,64 +44,53 @@ tester_manager::~tester_manager() { } +void tester_manager::register_tester(tester *test) +{ + testers.push_back(test); +} + bool tester_manager::run(int argc, char *argv[]) { - if (argc < TESTER_ARGC) { - usage(); - return false; - } + bool ret; + sensor_type_t type = ACCELEROMETER_SENSOR; - if (!setup(argc, argv)) { + if (argc < TESTER_ARGC) { usage(); return false; } - test_bench::run_all_testcase(); + if (strncmp(argv[2], "auto", 4) != 0) + type = get_sensor_type(argv[2]); - return true; -} + tester *_tester = get_tester(argv[2]); + RETVM_IF(!_tester, false, "Cannot find matched tester\n"); -bool tester_manager::setup(int argc, char *argv[]) -{ - if (strncmp(argv[2], "auto", 4) == 0) - return setup_auto(argc, argv); + ret = _tester->setup(type, argc, argv); + RETVM_IF(!ret, false, "Failed to setup injector\n"); - return setup_manual(argc, argv); -} + ret = _tester->run(argc, argv); + RETVM_IF(!ret, false, "Failed to run tester\n"); -bool tester_manager::setup_auto(int argc, char *argv[]) -{ - if (argc > 5) - repeat = atoi(argv[5]); - - test_option::show_full_log(true); - test_option::set_options(argc, argv); + ret = _tester->teardown(); + RETVM_IF(!ret, false, "Failed to tear down tester\n"); return true; } -bool tester_manager::setup_manual(int argc, char *argv[]) +tester *tester_manager::get_tester(const char *name) { - type = get_sensor_type(argv[2]); - RETVM_IF(type == UNKNOWN_SENSOR, false, "Invalid argument\n"); - - interval = TEST_DEFAULT_INTERVAL; - latency = TEST_DEFAULT_LATENCY; - powersave = TEST_DEFAULT_POWERSAVE_OPTION; - event_count = 0; - - if (argc >= TESTER_ARGC + 1) - interval = atoi(argv[TESTER_ARGC]); - if (argc >= TESTER_ARGC + 2) - latency = atoi(argv[TESTER_ARGC + 1]); - if (argc >= TESTER_ARGC + 3) - powersave = atoi(argv[TESTER_ARGC + 2]); - - test_option::show_full_log(true); - test_option::set_group("skip_manual"); - /* test_option::set_options(argc, argv); */ - - return true; + int count = testers.size(); + + for (int i = 0; i < count; ++i) { + if (strncmp(name, "auto", 4) == 0) { + if (testers[i]->name() == "auto") + return testers[i]; + } else { + if (testers[i]->name() == "manual") + return testers[i]; + } + } + return NULL; } void tester_manager::stop(void) @@ -121,69 +101,16 @@ void tester_manager::stop(void) void tester_manager::usage(void) { - _N("usage: sensorctl test auto [group] [log]\n"); - _N("usage: sensorctl test [interval] [batch_latency] [event_count] [test_count]\n"); + _N("usage: sensorctl test auto [options] [--help]\n"); + _N("usage: sensorctl test [--help]\n"); usage_sensors(); _N("auto:\n"); - _N(" test sensors automatically.\n"); - _N("group:\n"); - _N(" a group name(or a specific word contained in the group name).\n"); - _N("log:\n"); - _N(" enable(1) or disable(0). default value is 1.\n"); - _N("sensor_type: specific sensor\n"); - _N(" test specific sensor manually.\n"); - _N("interval_ms:\n"); - _N(" interval. default value is 100ms.\n"); - _N("batch_latency_ms:\n"); - _N(" batch_latency. default value is 1000ms.\n"); - _N("event count(n):\n"); - _N(" test sensor until it gets n event. default is 999999(infinitly).\n"); - _N("test count(n):\n"); - _N(" test sensor in n times repetitively, default is 1.\n\n"); -} - -/* manual test case */ -static void test_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) -{ - if (event_count >= MAX_COUNT) { - mainloop::stop(); - return; - } - - _N("%llu ", data->timestamp); - for (int i = 0; i < data->value_count; ++i) - _N(" %10f", data->values[i]); - _N("\n"); -} - -TESTCASE(skip_manual, sensor_test) -{ - int handle; - bool ret; - int index = 0; - sensor_data_t data; - - if (sensor_adapter::get_count(type) > 1) { - _N("There are more than 2 sensors. please enter the index : "); - if (scanf("%d", &index) != 1) - return false; - } - - sensor_info info(type, index, interval, latency, powersave, test_cb, NULL); - - ret = sensor_adapter::start(info, handle); - ASSERT_TRUE(ret); - - ret = sensor_adapter::get_data(handle, type, data); - EXPECT_TRUE(ret); - - mainloop::run(); - - ret = sensor_adapter::stop(info, handle); - ASSERT_TRUE(ret); - - return true; + _N(" Run all testcases automatically.\n"); + _N("sensor_type:\n"); + _N(" Run the specific sensor manually.\n"); + _N("help: \n"); + _N(" Prints the synopsis and a list of options.\n"); } diff --git a/src/sensorctl/tester.h b/src/sensorctl/tester.h index 148a402..b22b8ae 100644 --- a/src/sensorctl/tester.h +++ b/src/sensorctl/tester.h @@ -25,8 +25,30 @@ #include "sensor_manager.h" +#define TESTER_ARGC 3 /* e.g. {sensorctl, test, accelerometer} */ + +#define REGISTER_TESTER(name, tester_type) \ +static tester_type tester(name); + +class tester { +public: + tester(const char *name); + virtual ~tester() {} + + virtual bool setup(sensor_type_t type, int argc, char *argv[]) { return true; } + virtual bool teardown(void) { return true; } + virtual bool run(int argc, char *argv[]) = 0; + + const std::string& name() const { return m_name; } + +private: + std::string m_name; +}; + class tester_manager : public sensor_manager { public: + static void register_tester(tester *test); + tester_manager(); virtual ~tester_manager(); @@ -34,10 +56,8 @@ public: void stop(void); private: - bool setup(int argc, char *argv[]); - bool setup_auto(int argc, char *argv[]); - bool setup_manual(int argc, char *argv[]); + static std::vector testers; + tester *get_tester(const char *type); void usage(void); }; - diff --git a/src/sensorctl/tester_auto.cpp b/src/sensorctl/tester_auto.cpp new file mode 100644 index 0000000..2d4b534 --- /dev/null +++ b/src/sensorctl/tester_auto.cpp @@ -0,0 +1,87 @@ +/* + * sensorctl + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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. + * + */ + +#include "log.h" +#include "tester.h" +#include "test_bench.h" + +#define TEST_AUTO "auto" + +class tester_auto : public tester { +public: + tester_auto(const char *name); + virtual ~tester_auto(); + + bool setup(sensor_type_t type, int argc, char *argv[]); + bool teardown(void); + + bool run(int argc, char *argv[]); + void usage(void); +}; + +tester_auto::tester_auto(const char *name) +: tester(name) +{ +} + +tester_auto::~tester_auto() +{ +} + +bool tester_auto::setup(sensor_type_t type, int argc, char *argv[]) +{ + test_option::filter = "(?!manual|skip)[\\w\\.]+"; + + if (!test_option::set_options(argc, argv)) { + usage(); + return false; + } + + return true; +} + +bool tester_auto::teardown(void) +{ + return true; +} + +bool tester_auto::run(int argc, char *argv[]) +{ + test_bench::run_all_testcases(); + return true; +} + +void tester_auto::usage(void) +{ + _N("Usage : sensorctl test auto [--help] [--list] [--filter=]\n"); + _N(" [--verbose] [--shuffle] [--repeat]\n"); + _N(" [--output]\n"); + + _N("Examples:\n"); + _N(" sensorctl test auto --list\n"); + _N(" sensorctl test auto --filter=accelerometer.interval*\n"); + _N(" sensorctl test auto --filter=accelerometer.start\n"); + _N(" sensorctl test auto --filter=accelerometer.verify\n"); + _N(" sensorctl test auto --filter=ipc.socket*\n"); + _N(" sensorctl test auto --shuffle\n"); + _N(" sensorctl test auto --verbose\n"); + _N(" sensorctl test auto --output=results.log\n"); +} + +REGISTER_TESTER(TEST_AUTO, tester_auto); diff --git a/src/sensorctl/tester_manual.cpp b/src/sensorctl/tester_manual.cpp new file mode 100644 index 0000000..f2270eb --- /dev/null +++ b/src/sensorctl/tester_manual.cpp @@ -0,0 +1,152 @@ +/* + * sensorctl + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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. + * + */ + +#include + +#include "tester.h" +#include "mainloop.h" +#include "log.h" +#include "test_bench.h" +#include "sensor_adapter.h" + +#define MAX_COUNT 999999 +#define TEST_DEFAULT_INTERVAL 100 +#define TEST_DEFAULT_LATENCY 0 +#define TEST_DEFAULT_POWERSAVE_OPTION SENSOR_OPTION_ALWAYS_ON + +#define TEST_MANUAL "manual" + +static sensor_type_t type; +static int interval; +static int latency; +static int powersave; +//static int repeat; + +class tester_manual : public tester { +public: + tester_manual(const char *name); + virtual ~tester_manual(); + + bool setup(sensor_type_t type, int argc, char *argv[]); + bool teardown(void); + + bool run(int argc, char *argv[]); + void usage(void); +}; + +tester_manual::tester_manual(const char *name) +: tester(name) +{ +} + +tester_manual::~tester_manual() +{ +} + +bool tester_manual::setup(sensor_type_t type, int argc, char *argv[]) +{ + interval = TEST_DEFAULT_INTERVAL; + latency = TEST_DEFAULT_LATENCY; + powersave = TEST_DEFAULT_POWERSAVE_OPTION; + + if (!test_option::set_options(argc, argv)) { + usage(); + return false; + } + + interval = test_option::interval; + latency = test_option::latency; + powersave = test_option::powersave; + + if (interval == -1) + interval = TEST_DEFAULT_INTERVAL; + if (latency == -1) + latency = TEST_DEFAULT_LATENCY; + if (powersave == -1) + powersave = TEST_DEFAULT_POWERSAVE_OPTION; + + return true; +} + +bool tester_manual::teardown(void) +{ + return true; +} + +bool tester_manual::run(int argc, char *argv[]) +{ + test_option::filter = "^manual[\\w\\.]+"; + test_bench::run_all_testcases(); + + return true; +} + +void tester_manual::usage(void) +{ + _N("Usage : sensorctl test \n"); + _N(" [--interval=NUMBER] [--batch_latency=NUMBER] [--powersave=TYPE]\n"); + _N(" [--repeat=NUMBER] [--output=FILE_PATH] [--help] [--verbose]\n"); + + _N("Examples:\n"); + _N(" sensorctl test accelerometer\n"); + _N(" sensorctl test accelerometer --interval=100 --batch_latency=1000\n"); + _N(" sensorctl test accelerometer --i 100 --b 1000 --p 0\n"); + _N(" sensorctl test accelerometer --i 100 --shuffle\n"); + _N(" sensorctl test accelerometer --i 100 --verbose\n"); + _N(" sensorctl test accelerometer --i 100 --output=results.log\n"); +} + +static void test_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) +{ + _N("%llu ", data->timestamp); + for (int i = 0; i < data->value_count; ++i) + _N(" %10f", data->values[i]); + _N("\n"); +} + +TESTCASE(manual_test, sensor) +{ + int handle; + bool ret; + int index = 0; + sensor_data_t data; + + if (sensor_adapter::get_count(type) > 1) { + _N("There are more than 2 sensors. please enter the index : "); + if (scanf("%d", &index) != 1) + return false; + } + + sensor_info info(type, index, interval, latency, powersave, test_cb, NULL); + + ret = sensor_adapter::start(info, handle); + ASSERT_TRUE(ret); + + ret = sensor_adapter::get_data(handle, type, data); + EXPECT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::stop(info, handle); + ASSERT_TRUE(ret); + + return true; +} + +REGISTER_TESTER(TEST_MANUAL, tester_manual); -- 2.7.4 From 096cf070533dd0de883b73df21a27ae82e7bbc7d Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 20:21:03 +0900 Subject: [PATCH 15/16] sensorctl: clean up testcases Change-Id: I853f84296e788da1646483b3eb2197bd47e0229e Signed-off-by: kibak.yoon --- ...{accelerometer.cpp => sensor_accelerometer.cpp} | 86 +++++--------- src/sensorctl/testcase/sensor_basic.cpp | 128 ++++----------------- src/sensorctl/testcase/sensor_interval.cpp | 94 ++++++++++++++- .../{unit_client.cpp => sensor_listener.cpp} | 104 ++++++++++++++++- .../{unit_provider.cpp => sensor_provider.cpp} | 50 ++++---- src/sensorctl/testcase/unit_ipc.cpp | 24 ++-- src/sensorctl/testcase/unit_socket.cpp | 15 +-- 7 files changed, 284 insertions(+), 217 deletions(-) rename src/sensorctl/testcase/{accelerometer.cpp => sensor_accelerometer.cpp} (60%) rename src/sensorctl/testcase/{unit_client.cpp => sensor_listener.cpp} (54%) rename src/sensorctl/testcase/{unit_provider.cpp => sensor_provider.cpp} (94%) diff --git a/src/sensorctl/testcase/accelerometer.cpp b/src/sensorctl/testcase/sensor_accelerometer.cpp similarity index 60% rename from src/sensorctl/testcase/accelerometer.cpp rename to src/sensorctl/testcase/sensor_accelerometer.cpp index ed526c3..6f83619 100644 --- a/src/sensorctl/testcase/accelerometer.cpp +++ b/src/sensorctl/testcase/sensor_accelerometer.cpp @@ -24,7 +24,7 @@ #include "test_bench.h" #include "sensor_adapter.h" -static void basic_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) +static void test_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) { EXPECT_GT(data->timestamp, 0); EXPECT_NEAR(data->values[0], 0, 19.6); @@ -34,13 +34,16 @@ static void basic_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *da mainloop::stop(); } -TESTCASE(accelerometer_basic, start_stop_p) +TESTCASE(accelerometer_test, start_stop_p) { bool ret; int handle; + if (!sensor_adapter::is_supported(ACCELEROMETER_SENSOR)) + return true; /* Not Supported */ + sensor_info info(ACCELEROMETER_SENSOR, 0, - 100, 1000, SENSOR_OPTION_ALWAYS_ON, basic_cb, NULL); + 100, 1000, SENSOR_OPTION_ALWAYS_ON, test_cb, NULL); ret = sensor_adapter::start(info, handle); ASSERT_TRUE(ret); @@ -58,12 +61,15 @@ static void get_data_cb(sensor_t sensor, unsigned int event_type, sensor_data_t mainloop::stop(); } -TESTCASE(accelerometer_basic, get_data_p) +TESTCASE(accelerometer_test, get_data_p) { bool ret; int handle; sensor_data_t data; + if (!sensor_adapter::is_supported(ACCELEROMETER_SENSOR)) + return true; /* Not Supported */ + sensor_info info(ACCELEROMETER_SENSOR, 0, 100, 1000, SENSOR_OPTION_ALWAYS_ON, get_data_cb, NULL); @@ -81,80 +87,40 @@ TESTCASE(accelerometer_basic, get_data_p) return true; } -static unsigned long long prev_prev_ts; -static unsigned long long prev_ts; +static unsigned long long time_first; +static unsigned long long time_last; static int event_count; -static void accel_regular_interval_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) +static void accel_interval_100ms_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) { - int prev_gap; - int current_gap; - if (prev_prev_ts == 0) { - prev_prev_ts = data->timestamp; + if (event_count == 0) { + time_first = data->timestamp; + event_count++; return; } - if (prev_ts == 0) { - prev_ts = data->timestamp; - return; - } - - prev_gap = prev_ts - prev_prev_ts; - current_gap = data->timestamp - prev_ts; - - EXPECT_NEAR(current_gap, prev_gap, 10000); - prev_prev_ts = prev_ts; - prev_ts = data->timestamp; - - if (event_count++ > 3) + if (event_count == 10) { + /* 100ms + 20ms(error) */ + EXPECT_LE((data->timestamp - time_first) / 10, 120000); mainloop::stop(); -} - -TESTCASE(accelerometer_interval, regular_interval_p) -{ - bool ret; - int handle; - prev_prev_ts = 0; - prev_ts = 0; - event_count = 0; - - sensor_info info(ACCELEROMETER_SENSOR, 0, - 100, 1000, SENSOR_OPTION_ALWAYS_ON, accel_regular_interval_cb, NULL); - - ret = sensor_adapter::start(info, handle); - ASSERT_TRUE(ret); - - mainloop::run(); - - ret = sensor_adapter::stop(info, handle); - ASSERT_TRUE(ret); - - return true; -} - -static void accel_interval_100ms_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) -{ - if (prev_ts == 0) { - prev_ts = data->timestamp; return; } - /* 100ms + 20ms(error) */ - EXPECT_LE(data->timestamp - prev_ts, 120000); - prev_ts = data->timestamp; - - if (event_count++ > 3) - mainloop::stop(); + event_count++; } -TESTCASE(accelerometer_interval, 100ms_interval_p) +TESTCASE(accelscope_test, 100ms_interval_p) { bool ret; int handle; - prev_ts = 0; + time_first = 0; + time_last = 0; event_count = 0; + if (!sensor_adapter::is_supported(ACCELEROMETER_SENSOR)) + return true; /* Not Supported */ + sensor_info info(ACCELEROMETER_SENSOR, 0, 100, 1000, SENSOR_OPTION_ALWAYS_ON, accel_interval_100ms_cb, NULL); diff --git a/src/sensorctl/testcase/sensor_basic.cpp b/src/sensorctl/testcase/sensor_basic.cpp index cc56dec..ef6b139 100644 --- a/src/sensorctl/testcase/sensor_basic.cpp +++ b/src/sensorctl/testcase/sensor_basic.cpp @@ -18,6 +18,7 @@ */ #include +#include #include #include "log.h" @@ -25,19 +26,30 @@ #include "test_bench.h" #include "sensor_adapter.h" +/* exception list */ +#define SAMSUNG_PEDOMETER "http://samsung.com/sensor/healthinfo/pedometer/samsung_pedometer" + static void basic_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) { EXPECT_GT(data->timestamp, 0); - //_N("[ DATA ] %f\n", data->values[0]); + _N(_WHT "[ DATA ] %f\n" _RST, data->values[0]); mainloop::stop(); } -TESTCASE(all_sensor_test, scenario_basic_p) +static bool skip_sensor(sensor_t sensor) +{ + const char *uri = sensord_get_uri(sensor); + + if (strncmp(uri, SAMSUNG_PEDOMETER, sizeof(SAMSUNG_PEDOMETER)) == 0) + return true; + + return false; +} + +TESTCASE(sensor_basic, all_sensor_p) { - int err; + int err, count, handle; bool ret; - int count; - int handle; sensor_t *sensors; sensor_type_t type; @@ -45,10 +57,12 @@ TESTCASE(all_sensor_test, scenario_basic_p) ASSERT_EQ(err, 0); for (int i = 0; i < count; ++i) { - sensord_get_type(sensors[i], &type); - /* TODO */ - _N("[ TYPE ] %s\n", "UNKNOWN_SENSOR"); + if (skip_sensor(sensors[i])) + continue; + + _W("[ SENSOR %d ] %s\n", i, sensord_get_uri(sensors[i])); + sensord_get_type(sensors[i], &type); sensor_info info(type, 0, 100, 1000, SENSOR_OPTION_ALWAYS_ON, basic_cb, NULL); ret = sensor_adapter::start(info, handle); @@ -64,101 +78,3 @@ TESTCASE(all_sensor_test, scenario_basic_p) return true; } - -typedef bool (*process_func_t)(const char *msg, int size, int count); - -static pid_t run_process(process_func_t func, const char *msg, int size, int count) -{ - pid_t pid = fork(); - if (pid < 0) - return -1; - - if (pid == 0) { - if (!func(msg, size, count)) - _E("Failed to run process\n"); - exit(0); - } - - return pid; -} - -static bool run_echo_command_test(const char *str, int size, int cout) -{ - bool ret = true; - int handle; - char buf[4096] = {'1', '1', '1', }; - - sensor_info info(ACCELEROMETER_SENSOR, 0, - 100, 1000, SENSOR_OPTION_ALWAYS_ON, basic_cb, NULL); - sensor_adapter::get_handle(info, handle); - - for (int i = 0; i < 1024; ++i) - ret &= sensor_adapter::set_attribute(handle, SENSOR_ATTR_ACCELEROMETER_INJECTION, buf, 4096); - ASSERT_TRUE(ret); - - return true; -} - -TESTCASE(echo_command_test, echo_command_p) -{ - pid_t pid; - - for (int i = 0; i < 100; ++i) { - pid = run_process(run_echo_command_test, NULL, 0, 0); - EXPECT_GE(pid, 0); - } - - pid = run_process(run_echo_command_test, NULL, 0, 0); - EXPECT_GE(pid, 0); - - ASSERT_TRUE(true); - - return true; -} - -#if 0 -TESTCASE(gyroscope_value_p) -{ - scenario_basic_p(GYROSCOPE_SENSOR); -} - -TESTCASE(gravitye_value_p) -{ - scenario_basic_p(GRAVITY_SENSOR); -} - -TESTCASE(linear_accel_value_p) -{ - scenario_basic_p(LINEAR_ACCEL_SENSOR); -} - -TESTCASE(proximity_value_p) -{ - scenario_basic_p(PROXIMITY_SENSOR); -} - -TESTCASE(pressure_value_p) -{ - scenario_basic_p(PRESSURE_SENSOR); -} - -TESTCASE(hrm_value_p) -{ - scenario_basic_p(HRM_SENSOR); -} - -TESTCASE(hrm_raw_value_p) -{ - scenario_basic_p(HRM_RAW_SENSOR); -} - -TESTCASE(hrm_led_green_value_p) -{ - scenario_basic_p(HRM_LED_GREEN_SENSOR); -} - -TESTCASE(wrist_up_value_p) -{ - scenario_basic_p(GESTURE_WRIST_UP_SENSOR); -} -#endif diff --git a/src/sensorctl/testcase/sensor_interval.cpp b/src/sensorctl/testcase/sensor_interval.cpp index 8318fd5..7a1e254 100644 --- a/src/sensorctl/testcase/sensor_interval.cpp +++ b/src/sensorctl/testcase/sensor_interval.cpp @@ -17,10 +17,100 @@ * */ +#include +#include + +#include "log.h" +#include "mainloop.h" #include "test_bench.h" +#include "sensor_adapter.h" -TESTCASE(sensor_interval, all_sensor_interval_10ms_p) +static void basic_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) { - /* TODO: test 10ms interval */ + EXPECT_GT(data->timestamp, 0); + mainloop::stop(); +} + +TESTCASE(interval_test, 20ms_p) +{ + int err, count, handle; + bool ret; + sensor_t *sensors; + sensor_type_t type; + + err = sensord_get_sensors(ACCELEROMETER_SENSOR, &sensors, &count); + ASSERT_EQ(err, 0); + + for (int i = 0; i < count; ++i) { + sensord_get_type(sensors[i], &type); + sensor_info info(type, 0, 20, 1000, SENSOR_OPTION_ALWAYS_ON, basic_cb, NULL); + + ret = sensor_adapter::start(info, handle); + EXPECT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::stop(info, handle); + EXPECT_TRUE(ret); + } + + free(sensors); + + return true; +} + +TESTCASE(interval_test, 100ms_p) +{ + int err, count, handle; + bool ret; + sensor_t *sensors; + sensor_type_t type; + + err = sensord_get_sensors(ACCELEROMETER_SENSOR, &sensors, &count); + ASSERT_EQ(err, 0); + + for (int i = 0; i < count; ++i) { + sensord_get_type(sensors[i], &type); + sensor_info info(type, 0, 100, 1000, SENSOR_OPTION_ALWAYS_ON, basic_cb, NULL); + + ret = sensor_adapter::start(info, handle); + EXPECT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::stop(info, handle); + EXPECT_TRUE(ret); + } + + free(sensors); + + return true; +} + +TESTCASE(interval_test, 200ms_p) +{ + int err, count, handle; + bool ret; + sensor_t *sensors; + sensor_type_t type; + + err = sensord_get_sensors(ACCELEROMETER_SENSOR, &sensors, &count); + ASSERT_EQ(err, 0); + + for (int i = 0; i < count; ++i) { + sensord_get_type(sensors[i], &type); + sensor_info info(type, 0, 200, 1000, SENSOR_OPTION_ALWAYS_ON, basic_cb, NULL); + + ret = sensor_adapter::start(info, handle); + EXPECT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::stop(info, handle); + EXPECT_TRUE(ret); + } + + free(sensors); + return true; } diff --git a/src/sensorctl/testcase/unit_client.cpp b/src/sensorctl/testcase/sensor_listener.cpp similarity index 54% rename from src/sensorctl/testcase/unit_client.cpp rename to src/sensorctl/testcase/sensor_listener.cpp index 16c5f1d..f92d33a 100644 --- a/src/sensorctl/testcase/unit_client.cpp +++ b/src/sensorctl/testcase/sensor_listener.cpp @@ -30,13 +30,17 @@ #include "test_bench.h" static bool called = false; +static int count = 0; static void event_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) { _I("[%llu] %f %f %f\n", data->timestamp, data->values[0], data->values[1], data->values[2]); + + if (count++ > 3) + mainloop::stop(); } -TESTCASE(sensor_api_get_default_sensor, get_sensor_p_1) +TESTCASE(sensor_listener, get_default_sensor_p_1) { int err; sensor_t sensor; @@ -47,7 +51,7 @@ TESTCASE(sensor_api_get_default_sensor, get_sensor_p_1) return true; } -TESTCASE(sensor_api_get_sensors, get_sensor_p_2) +TESTCASE(sensor_listener, get_sensors_p_1) { int err; int count; @@ -62,7 +66,7 @@ TESTCASE(sensor_api_get_sensors, get_sensor_p_2) return true; } -TESTCASE(sensor_api_connect, connect_p_1) +TESTCASE(sensor_listener, connect_p_1) { int err; int handle; @@ -80,7 +84,7 @@ TESTCASE(sensor_api_connect, connect_p_1) return true; } -TESTCASE(sensor_api_all, all_p_1) +TESTCASE(sensor_listener, all_api_p_1) { int err; bool ret; @@ -127,3 +131,95 @@ TESTCASE(sensor_api_all, all_p_1) return true; } + +TESTCASE(sensor_listener, bad_unregister_stop_order_p_1) +{ + int err; + bool ret; + int handle; + sensor_t sensor; + + called = false; + + err = sensord_get_default_sensor(ACCELEROMETER_SENSOR, &sensor); + ASSERT_EQ(err, 0); + + handle = sensord_connect(sensor); + ret = sensord_register_event(handle, 1, 100, 100, event_cb, NULL); + ret = sensord_start(handle, 0); + ret = sensord_change_event_interval(handle, 0, 100); + + mainloop::run(); + + /* [TEST] Unregister event before stop */ + ret = sensord_unregister_event(handle, 1); + ASSERT_TRUE(ret); + + ret = sensord_stop(handle); + ASSERT_TRUE(ret); + + ret = sensord_disconnect(handle); + ASSERT_TRUE(ret); + + return true; +} + +TESTCASE(sensor_listener, bad_disconnect_p_1) +{ + int err; + bool ret; + int handle; + sensor_t sensor; + + called = false; + + err = sensord_get_default_sensor(ACCELEROMETER_SENSOR, &sensor); + ASSERT_EQ(err, 0); + + handle = sensord_connect(sensor); + ret = sensord_register_event(handle, 1, 100, 100, event_cb, NULL); + ret = sensord_start(handle, 0); + ret = sensord_change_event_interval(handle, 0, 100); + + mainloop::run(); + + /* [TEST] Unregistering event is not called */ + + ret = sensord_stop(handle); + ASSERT_TRUE(ret); + + ret = sensord_disconnect(handle); + ASSERT_TRUE(ret); + + return true; +} + +TESTCASE(sensor_listener, bad_disconnect_p_2) +{ + int err; + bool ret; + int handle; + sensor_t sensor; + + called = false; + + err = sensord_get_default_sensor(ACCELEROMETER_SENSOR, &sensor); + ASSERT_EQ(err, 0); + + handle = sensord_connect(sensor); + ret = sensord_register_event(handle, 1, 100, 100, event_cb, NULL); + ret = sensord_start(handle, 0); + ret = sensord_change_event_interval(handle, 0, 100); + + mainloop::run(); + + ret = sensord_unregister_event(handle, 1); + ASSERT_TRUE(ret); + + /* [TEST] stopping sensor is not called */ + + ret = sensord_disconnect(handle); + ASSERT_TRUE(ret); + + return true; +} diff --git a/src/sensorctl/testcase/unit_provider.cpp b/src/sensorctl/testcase/sensor_provider.cpp similarity index 94% rename from src/sensorctl/testcase/unit_provider.cpp rename to src/sensorctl/testcase/sensor_provider.cpp index 0c61862..9c76c21 100644 --- a/src/sensorctl/testcase/unit_provider.cpp +++ b/src/sensorctl/testcase/sensor_provider.cpp @@ -36,9 +36,6 @@ static bool called = false; static void event_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) { - if (test_option::full_log == false) { - while (true) {} - } _I("[%llu] %f %f %f\n", data->timestamp, data->values[0], data->values[1], data->values[2]); } @@ -107,7 +104,7 @@ static void removed_cb(const char *uri, void *user_data) mainloop::stop(); } -TESTCASE(sensor_api_provider_uri, provider_check_uri) +TESTCASE(sensor_provider, check_uri) { int err; sensord_provider_h provider; @@ -139,7 +136,27 @@ TESTCASE(sensor_api_provider_uri, provider_check_uri) } /* TODO: change it from manual test to auto-test */ -TESTCASE(sensor_api_provider_mysensor, provider_p_1) +TESTCASE(skip_sensor_provider, mysensor_added_removed_cb_p_1) +{ + int ret = sensord_add_sensor_added_cb(added_cb, NULL); + ASSERT_EQ(ret, 0); + ret = sensord_add_sensor_removed_cb(removed_cb, NULL); + ASSERT_EQ(ret, 0); + + add_mysensor(); + + mainloop::run(); + + ret = sensord_remove_sensor_added_cb(added_cb); + ASSERT_EQ(ret, 0); + ret = sensord_remove_sensor_removed_cb(removed_cb); + ASSERT_EQ(ret, 0); + + return true; +} + +/* TODO: change it from manual test to auto-test */ +TESTCASE(skip_sensor_provider, mysensor_p) { int err = 0; sensor_t sensor; @@ -181,7 +198,8 @@ TESTCASE(sensor_api_provider_mysensor, provider_p_1) return true; } -TESTCASE(sensor_api_listener_mysensor, listener_p_1) +/* TODO: change it from manual test to auto-test */ +TESTCASE(skip_sensor_provider, mysensor_with_listener_p_1) { int err; bool ret; @@ -219,23 +237,3 @@ TESTCASE(sensor_api_listener_mysensor, listener_p_1) return true; } -TESTCASE(sensor_api_provider_cb, mysensor_cb_p_1) -{ - int ret; - - ret = sensord_add_sensor_added_cb(added_cb, NULL); - ASSERT_EQ(ret, 0); - ret = sensord_add_sensor_removed_cb(removed_cb, NULL); - ASSERT_EQ(ret, 0); - - add_mysensor(); - - mainloop::run(); - - ret = sensord_remove_sensor_added_cb(added_cb); - ASSERT_EQ(ret, 0); - ret = sensord_remove_sensor_removed_cb(removed_cb); - ASSERT_EQ(ret, 0); - - return true; -} diff --git a/src/sensorctl/testcase/unit_ipc.cpp b/src/sensorctl/testcase/unit_ipc.cpp index d820707..799924a 100644 --- a/src/sensorctl/testcase/unit_ipc.cpp +++ b/src/sensorctl/testcase/unit_ipc.cpp @@ -102,7 +102,7 @@ public: }; /* IPC Client Sleep Test(4096Kb * 1024) */ -static bool run_ipc_client_sleep_10s(const char *str, int size, int count) +static bool run_ipc_client_sleep_1s(const char *str, int size, int count) { ipc_client client(TEST_PATH); test_client_handler_30_1M client_handler; @@ -355,9 +355,9 @@ static bool run_ipc_client(const char *str, int size, int count) } /** - * @brief Test 3 client + 1 client which sleeps 10 seconds + * @brief Test 3 client + 1 client which sleeps 1 seconds */ -TESTCASE(sensor_ipc_client_sleep_1s, sleep_1s_p) +TESTCASE(sensor_ipc, 3_client_with_1s_sleep_client_p) { pid_t pid = run_process(run_ipc_server_echo, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -369,7 +369,7 @@ TESTCASE(sensor_ipc_client_sleep_1s, sleep_1s_p) EXPECT_GE(pid, 0); } - bool ret = run_ipc_client_sleep_10s(NULL, 0, 0); + bool ret = run_ipc_client_sleep_1s(NULL, 0, 0); ASSERT_TRUE(ret); SLEEP_1S; @@ -378,9 +378,9 @@ TESTCASE(sensor_ipc_client_sleep_1s, sleep_1s_p) } /** - * @brief Test 3 client + 1 client which has small recv buffer + * @brief Test 3 client + 1 client which has small recv buffer(2240) */ -TESTCASE(sensor_ipc_client_small_2240, ipc_client_small_2240_p) +TESTCASE(sensor_ipc, 3_client_with_small_buffer_client_p) { pid_t pid = run_process(run_ipc_server_echo, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -403,7 +403,7 @@ TESTCASE(sensor_ipc_client_small_2240, ipc_client_small_2240_p) /** * @brief Test 30 ipc_client with 1M message */ -TESTCASE(sensor_ipc_30_client_1M, ipc_client_p_30_1M) +TESTCASE(sensor_ipc, 30_client_with_1M_message_p) { pid_t pid = run_process(run_ipc_server_echo, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -426,7 +426,7 @@ TESTCASE(sensor_ipc_30_client_1M, ipc_client_p_30_1M) /** * @brief Test 2 channel of 1 client with message */ -TESTCASE(sensor_ipc_client_2_channel_message, 2_channel_message_p) +TESTCASE(sensor_ipc, 1_client_with_2_channel_message_p) { pid_t pid = run_process(run_ipc_server, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -444,7 +444,7 @@ TESTCASE(sensor_ipc_client_2_channel_message, 2_channel_message_p) /** * @brief Test 2 channel of 1 client */ -TESTCASE(sensor_ipc_client_2_channel, 2_channel_p) +TESTCASE(sensor_ipc, 1_client_2_channel_simple_p) { pid_t pid = run_process(run_ipc_server, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -462,7 +462,7 @@ TESTCASE(sensor_ipc_client_2_channel, 2_channel_p) /** * @brief Test 100 ipc_client */ -TESTCASE(sensor_ipc_100_client, ipc_client_p_100) +TESTCASE(sensor_ipc, 100_client_p) { pid_t pid = run_process(run_ipc_server, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -485,7 +485,7 @@ TESTCASE(sensor_ipc_100_client, ipc_client_p_100) /** * @brief Test 2 ipc_client */ -TESTCASE(sensor_ipc_2_client, ipc_client_p_2) +TESTCASE(sensor_ipc, 2_client_p) { pid_t pid = run_process(run_ipc_server, NULL, 0, 0); EXPECT_GE(pid, 0); @@ -509,7 +509,7 @@ TESTCASE(sensor_ipc_2_client, ipc_client_p_2) * 2. send "TEST" message from client to server * 3. check that message in server handler */ -TESTCASE(sensor_ipc_client_0, ipc_client_p_0) +TESTCASE(sensor_ipc, server_client_basic_p) { pid_t pid = run_process(run_ipc_server, NULL, 0, 0); EXPECT_GE(pid, 0); diff --git a/src/sensorctl/testcase/unit_socket.cpp b/src/sensorctl/testcase/unit_socket.cpp index 261976f..1407cfc 100644 --- a/src/sensorctl/testcase/unit_socket.cpp +++ b/src/sensorctl/testcase/unit_socket.cpp @@ -27,11 +27,11 @@ #include "log.h" #include "test_bench.h" -using namespace ipc; - #define MAX_BUF_SIZE 4096 #define TEST_PATH "/run/.sensord_test.socket" +using namespace ipc; + typedef bool (*process_func_t)(const char *msg, int size, int count); static pid_t run_process(process_func_t func, const char *msg, int size, int count) @@ -67,7 +67,9 @@ static bool run_socket_echo_server(const char *msg, int size, int count) accept_sock.set_blocking_mode(true); accept_sock.bind(); accept_sock.listen(10); - accept_sock.accept(client_sock); + + while (!ret) + ret = accept_sock.accept(client_sock); /* receive message */ while (recv_count++ < count) { @@ -129,7 +131,6 @@ static bool run_socket_client(const char *msg, int size, int count) ASSERT_EQ(ret, 0); sock.close(); - return true; } @@ -140,7 +141,7 @@ static bool run_socket_client(const char *msg, int size, int count) * 3. check "TEST" message * @remarks we can test only regular socket, not systemd-based socket. */ -TESTCASE(sensor_ipc_socket, socket_p_0) +TESTCASE(ipc_socket, socket_simple_message_p) { const char *msg = "TEST"; int size = 4; @@ -162,7 +163,7 @@ TESTCASE(sensor_ipc_socket, socket_p_0) * 3. check total size * @remarks we can test only regular socket, not systemd-based socket. */ -TESTCASE(sensor_ipc_socket, socket_p_10) +TESTCASE(ipc_socket, socket_40K_message_p) { const char msg[MAX_BUF_SIZE] = {1, }; int size = MAX_BUF_SIZE; @@ -184,7 +185,7 @@ TESTCASE(sensor_ipc_socket, socket_p_10) * 3. check total size * @remarks we can test only regular socket, not systemd-based socket. */ -TESTCASE(sensor_ipc_socket, socket_p_1000) +TESTCASE(ipc_socket, socket_4M_message_p) { const char msg[MAX_BUF_SIZE] = {1, }; int size = MAX_BUF_SIZE; -- 2.7.4 From 4b702eda5df00c72a28b6dc913decd696eb3fdf6 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Thu, 10 Aug 2017 20:21:18 +0900 Subject: [PATCH 16/16] sensorctl: add gyroscope testcases Change-Id: Id5ef5188d07ba827db7add4c690782ae1c408722 Signed-off-by: kibak.yoon --- src/sensorctl/testcase/sensor_gyroscope.cpp | 136 ++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 src/sensorctl/testcase/sensor_gyroscope.cpp diff --git a/src/sensorctl/testcase/sensor_gyroscope.cpp b/src/sensorctl/testcase/sensor_gyroscope.cpp new file mode 100644 index 0000000..f4328e2 --- /dev/null +++ b/src/sensorctl/testcase/sensor_gyroscope.cpp @@ -0,0 +1,136 @@ +/* + * sensorctl + * + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * 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. + * + */ + +#include + +#include "log.h" +#include "mainloop.h" +#include "test_bench.h" +#include "sensor_adapter.h" + +static void test_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) +{ + EXPECT_GT(data->timestamp, 0); + EXPECT_NEAR(data->values[0], 0, 576.0); + EXPECT_NEAR(data->values[1], 0, 576.0); + EXPECT_NEAR(data->values[2], 0, 576.0); + + mainloop::stop(); +} + +TESTCASE(gyroscope_test, start_stop_p) +{ + bool ret; + int handle; + + if (!sensor_adapter::is_supported(GYROSCOPE_SENSOR)) + return true; /* Not Supported */ + + sensor_info info(GYROSCOPE_SENSOR, 0, + 100, 1000, SENSOR_OPTION_ALWAYS_ON, test_cb, NULL); + + ret = sensor_adapter::start(info, handle); + ASSERT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::stop(info, handle); + ASSERT_TRUE(ret); + + return true; +} + +static void get_data_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) +{ + mainloop::stop(); +} + +TESTCASE(gyroscope_test, get_data_p) +{ + bool ret; + int handle; + sensor_data_t data; + + if (!sensor_adapter::is_supported(GYROSCOPE_SENSOR)) + return true; /* Not Supported */ + + sensor_info info(GYROSCOPE_SENSOR, 0, + 100, 1000, SENSOR_OPTION_ALWAYS_ON, get_data_cb, NULL); + + ret = sensor_adapter::start(info, handle); + ASSERT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::get_data(handle, info.type, data); + ASSERT_TRUE(ret); + + ret = sensor_adapter::stop(info, handle); + ASSERT_TRUE(ret); + + return true; +} + +static unsigned long long time_first; +static unsigned long long time_last; +static int event_count; + +static void gyro_interval_100ms_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data) +{ + if (event_count == 0) { + time_first = data->timestamp; + event_count++; + return; + } + + if (event_count == 10) { + /* 100ms + 20ms(error) */ + EXPECT_LE((data->timestamp - time_first) / 10, 120000); + mainloop::stop(); + return; + } + + event_count++; +} + +TESTCASE(gyroscope_test, 100ms_interval_p) +{ + bool ret; + int handle; + + time_first = 0; + time_last = 0; + event_count = 0; + + if (!sensor_adapter::is_supported(GYROSCOPE_SENSOR)) + return true; /* Not Supported */ + + sensor_info info(GYROSCOPE_SENSOR, 0, + 100, 1000, SENSOR_OPTION_ALWAYS_ON, gyro_interval_100ms_cb, NULL); + + ret = sensor_adapter::start(info, handle); + ASSERT_TRUE(ret); + + mainloop::run(); + + ret = sensor_adapter::stop(info, handle); + ASSERT_TRUE(ret); + + return true; +} -- 2.7.4