ADD_SUBDIRECTORY(src/client)
ADD_SUBDIRECTORY(src/client-dummy)
ADD_SUBDIRECTORY(src/sensorctl)
+ADD_SUBDIRECTORY(src/sensor)
INSTALL(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
%manifest packaging/sensord.manifest
%{_libdir}/libsensor-genuine.so.*
%{_libdir}/libsensord-shared.so
+%{_libdir}/sensor/fusion/libsensor-fusion.so
%{_bindir}/sensord
%{_unitdir}/sensord.service
%{_unitdir}/sensord.socket
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(sensors CXX)
+PROJECT(sensor-fusion CXX)
INCLUDE(GNUInstallDirs)
-SET(ACC "OFF")
-SET(HRM "OFF")
-SET(HRM_VIRT "OFF")
-SET(AUTO_ROTATION "OFF")
+SET(AUTO_ROTATION "ON")
SET(GRAVITY "OFF")
SET(LINEAR_ACCEL "OFF")
-SET(RV "OFF")
-SET(ORIENTATION "OFF")
-SET(FACE_DOWN "OFF")
-SET(SENSORHUB "OFF")
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/src/shared
- ${CMAKE_SOURCE_DIR}/src/server
${CMAKE_CURRENT_SOURCE_DIR}
)
-FILE(GLOB SENSOR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
-SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR})
+# Common Options
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2 -omit-frame-pointer -std=gnu++0x")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
+SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -Wl,--print-gc-sections")
+MESSAGE("FLAGS: ${CMAKE_CXX_FLAGS}")
+MESSAGE("FLAGS: ${CMAKE_EXE_LINKER_FLAGS}")
-IF("${ACC}" STREQUAL "ON")
-FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/accel/*.cpp)
-SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/accel)
-SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_ACCEL")
-ENDIF()
+# Internal Debugging Options
+#ADD_DEFINITIONS(-Wall -g -D_DEBUG)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(PLUGINS_PKGS REQUIRED dlog)
+
+FOREACH(flag ${PLUGINS_PKGS_CFLAGS})
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
+
+FILE(GLOB SRCS *.cpp)
-IF("${HRM}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/hrm/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/hrm)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_HRM")
-ENDIF()
-IF("${HRM_VIRT}" STREQUAL "ON")
-add_subdirectory(hrm_virt)
-ENDIF()
IF("${AUTO_ROTATION}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/auto_rotation/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/auto_rotation)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_AUTO_ROTATION")
+FILE(GLOB_RECURSE SRCS ${SRCS} auto_rotation/*.cpp)
+ADD_DEFINITIONS(-DENABLE_AUTO_ROTATION)
ENDIF()
+
IF("${GRAVITY}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/gravity/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/gravity)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_GRAVITY")
+FILE(GLOB_RECURSE SRCS ${SRCS} gravity/*.cpp)
+ADD_DEFINITIONS(-DENABLE_GRAVITY)
ENDIF()
+
IF("${LINEAR_ACCEL}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/linear_accel/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/linear_accel)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_LINEAR_ACCEL")
-ENDIF()
-IF("${ORIENTATION}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/orientation/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/orientation)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_ORIENTATION")
-ENDIF()
-IF("${RV}" STREQUAL "ON")
- FILE(GLOB SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/rotation_vector/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/rotation_vector)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_ROTATION_VECTOR")
- FILE(GLOB SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/rotation_vector/fusion_utils/*.cpp)
-ENDIF()
-IF("${FACE_DOWN}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/gesture/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/gesture)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_FACE_DOWN")
-ENDIF()
-IF("${SENSORHUB}" STREQUAL "ON")
- FILE(GLOB_RECURSE SENSOR_SRCS ${SENSOR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/sensorhub/*.cpp)
- SET(SENSOR_HEADERS ${SENSOR_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/sensorhub)
- SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} "-DENABLE_SENSORHUB")
+FILE(GLOB_RECURSE SRCS ${SRCS} linear_accel/*.cpp)
+ADD_DEFINITIONS(-DENABLE_LINEAR_ACCEL)
ENDIF()
-MESSAGE("${SENSOR_SRCS}")
-SET(SENSOR_SRCS ${SENSOR_SRCS} PARENT_SCOPE)
-SET(SENSOR_HEADERS ${SENSOR_HEADERS} PARENT_SCOPE)
-SET(SENSOR_DEFINITIONS ${SENSOR_DEFINITIONS} PARENT_SCOPE)
+MESSAGE("Sources: ${SRCS}")
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${PLUGINS_PKGS_LDFLAGS})
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/sensor/fusion)
*
*/
-#include <sensor_log.h>
-#include <auto_rotation_alg.h>
+#include "auto_rotation_alg.h"
auto_rotation_alg::auto_rotation_alg()
{
*
*/
-#ifndef _AUTO_ROTATION_ALG_H_
-#define _AUTO_ROTATION_ALG_H_
+#ifndef __AUTO_ROTATION_ALG_H__
+#define __AUTO_ROTATION_ALG_H__
class auto_rotation_alg {
public:
virtual bool get_rotation(float acc[3], unsigned long long timestamp, int prev_rotation, int &rotation) = 0;
};
-#endif /* _AUTO_ROTATION_ALG_H_ */
+#endif /* __AUTO_ROTATION_ALG_H__ */
*
*/
-#include <sensor_common.h>
-#include <sensor_log.h>
-#include <sensor_types.h>
-#include <auto_rotation_alg_emul.h>
-#include <stdlib.h>
+#include "auto_rotation_alg_emul.h"
+
#include <math.h>
+#include <stdlib.h>
+#include <sensor_types.h>
#define ROTATION_RULE_CNT 4
*
*/
-#ifndef _AUTO_ROTATION_ALG_EMUL_H_
-#define _AUTO_ROTATION_ALG_EMUL_H_
+#ifndef __AUTO_ROTATION_ALG_EMUL_H__
+#define __AUTO_ROTATION_ALG_EMUL_H__
-#include <auto_rotation_alg.h>
+#include "auto_rotation_alg.h"
class auto_rotation_alg_emul : public auto_rotation_alg {
public:
auto_rotation_alg_emul();
virtual ~auto_rotation_alg_emul();
- virtual bool get_rotation(float acc[3], unsigned long long timestamp, int prev_rotation, int &cur_rotation);
+ bool get_rotation(float acc[3], unsigned long long timestamp,
+ int prev_rotation, int &cur_rotation);
private:
int convert_rotation(int prev_rotation, float acc_pitch, float acc_theta);
};
-#endif /* _AUTO_ROTATION_ALG_EMUL_H_ */
+#endif /* __AUTO_ROTATION_ALG_EMUL_H__ */
/*
* sensord
*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
*
*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <math.h>
-#include <time.h>
-#include <sys/types.h>
-#include <dlfcn.h>
+#include "auto_rotation_sensor.h"
#include <sensor_log.h>
#include <sensor_types.h>
-#include <sensor_common.h>
-#include <virtual_sensor.h>
-#include <auto_rotation_sensor.h>
-#include <sensor_loader.h>
-#include <auto_rotation_alg.h>
-#include <auto_rotation_alg_emul.h>
+#include "auto_rotation_alg_emul.h"
-#define SENSOR_NAME "SENSOR_AUTO_ROTATION"
+#define NAME_SENSOR "http://tizen.org/sensor/auto_rotation/AUTO_ROTATION"
+#define NAME_VENDOR "Samsung"
+
+#define SRC_ID_ACC 0x1
+#define SRC_STR_ACC "http://tizen.org/sensor/accelerometer"
+
+static sensor_info2_t sensor_info = {
+ id: 0x1,
+ type: AUTO_ROTATION_SENSOR,
+ uri: NAME_SENSOR,
+ vendor: NAME_VENDOR,
+ min_range: AUTO_ROTATION_DEGREE_UNKNOWN,
+ max_range: AUTO_ROTATION_DEGREE_270,
+ resolution: 1,
+ min_interval: 60,
+ max_batch_count: 0,
+ wakeup_supported: false,
+ privilege:"",
+};
+
+static required_sensor_s required_sensors[] = {
+ {SRC_ID_ACC, SRC_STR_ACC}
+};
auto_rotation_sensor::auto_rotation_sensor()
-: m_accel_sensor(NULL)
-, m_alg(NULL)
-, m_rotation(0)
-, m_interval(100)
+: m_rotation(0)
, m_rotation_time(0)
+, m_alg(NULL)
{
+ if (!init())
+ throw OP_ERROR;
}
auto_rotation_sensor::~auto_rotation_sensor()
{
- delete m_alg;
-
- _I("auto_rotation_sensor is destroyed!\n");
+ deinit();
}
bool auto_rotation_sensor::init(void)
{
- m_accel_sensor = sensor_loader::get_instance().get_sensor(ACCELEROMETER_SENSOR);
-
- if (!m_accel_sensor) {
- _W("cannot load accel sensor_hal from %s", get_name());
- return false;
- }
-
m_alg = get_alg();
-
- if (!m_alg) {
- _E("Not supported AUTO ROTATION sensor");
- return false;
- }
-
- if (!m_alg->open())
- return false;
-
- _I("%s is created!\n", get_name());
-
+ retvm_if(!m_alg, false, "Not supported");
+ retvm_if(!m_alg->open(), false, "Cannot open auto rotation algorithm");
return true;
}
-sensor_type_t auto_rotation_sensor::get_type(void)
+void auto_rotation_sensor::deinit(void)
{
- return AUTO_ROTATION_SENSOR;
+ delete m_alg;
}
-unsigned int auto_rotation_sensor::get_event_type(void)
+int auto_rotation_sensor::get_sensor_info(const sensor_info2_t **info)
{
- return AUTO_ROTATION_EVENT_CHANGE_STATE;
+ *info = &sensor_info;
+ return OP_SUCCESS;
}
-const char* auto_rotation_sensor::get_name(void)
+int auto_rotation_sensor::get_required_sensors(const required_sensor_s **sensors)
{
- return SENSOR_NAME;
+ *sensors = required_sensors;
+ return 1;
}
-bool auto_rotation_sensor::get_sensor_info(sensor_info &info)
+int auto_rotation_sensor::update(uint32_t id, sensor_data_t *data, int len)
{
- info.set_type(get_type());
- info.set_id(get_id());
- info.set_privilege(SENSOR_PRIVILEGE_PUBLIC); // FIXME
- info.set_name("Auto Rotation Sensor");
- info.set_vendor("Samsung Electronics");
- info.set_min_range(AUTO_ROTATION_DEGREE_UNKNOWN);
- info.set_max_range(AUTO_ROTATION_DEGREE_270);
- info.set_resolution(1);
- info.set_min_interval(1);
- info.set_fifo_count(0);
- info.set_max_batch_count(0);
- info.set_supported_event(get_event_type());
- info.set_wakeup_supported(false);
-
- return true;
-}
-
-void auto_rotation_sensor::synthesize(const sensor_event_t& event)
-{
- if (event.event_type != ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME)
- return;
-
int rotation;
float acc[3];
- acc[0] = event.data->values[0];
- acc[1] = event.data->values[1];
- acc[2] = event.data->values[2];
-
- if (!m_alg->get_rotation(acc, event.data->timestamp, m_rotation, rotation))
- return;
-
- m_rotation = rotation;
- m_rotation_time = event.data->timestamp;
+ acc[0] = data->values[0];
+ acc[1] = data->values[1];
+ acc[2] = data->values[2];
- sensor_event_t *rotation_event;
- sensor_data_t *rotation_data;
- int data_length;
- int remains;
+ if (!m_alg->get_rotation(acc, data->timestamp, m_rotation, rotation))
+ return OP_ERROR;
- rotation_event = (sensor_event_t *)malloc(sizeof(sensor_event_t));
- if (!rotation_event) {
- _E("Failed to allocate memory");
- return;
- }
+ _D("Rotation: %d, ACC[0]: %f, ACC[1]: %f, ACC[2]: %f",
+ rotation, data->values[0], data->values[1], data->values[2]);
- remains = get_data(&rotation_data, &data_length);
-
- if (remains < 0) {
- free(rotation_event);
- return;
- }
-
- rotation_event->sensor_id = get_id();
- rotation_event->event_type = AUTO_ROTATION_EVENT_CHANGE_STATE;
- rotation_event->data_length = data_length;
- rotation_event->data = rotation_data;
-
- push(rotation_event);
+ m_rotation = rotation;
+ m_rotation_time = data->timestamp;
- _D("Rotation: %d, ACC[0]: %f, ACC[1]: %f, ACC[2]: %f", rotation, event.data->values[0], event.data->values[1], event.data->values[2]);
+ return OP_SUCCESS;
}
int auto_rotation_sensor::get_data(sensor_data_t **data, int *length)
{
- /* if It is batch sensor, remains can be 2+ */
- int remains = 1;
-
sensor_data_t *sensor_data;
sensor_data = (sensor_data_t *)malloc(sizeof(sensor_data_t));
*data = sensor_data;
*length = sizeof(sensor_data_t);
- return --remains;
+ return 1;
}
-bool auto_rotation_sensor::set_interval(unsigned long interval)
+int auto_rotation_sensor::start(observer_h ob)
{
- m_accel_sensor->add_interval((intptr_t)this , interval, true);
-
- m_interval = interval;
- return false;
-}
+ m_rotation = AUTO_ROTATION_DEGREE_UNKNOWN;
-bool auto_rotation_sensor::set_batch_latency(unsigned long latency)
-{
- return false;
-}
+ /* TODO: cache */
-bool auto_rotation_sensor::set_wakeup(int wakeup)
-{
- return false;
-}
+ m_alg->start();
-bool auto_rotation_sensor::pre_start(void)
-{
- m_rotation = AUTO_ROTATION_DEGREE_UNKNOWN;
- return true;
+ /* if OP_DEFAULT is returned,
+ * this function is not called anymore before stop() is called */
+ return OP_DEFAULT;
}
-bool auto_rotation_sensor::on_start(void)
+int auto_rotation_sensor::stop(observer_h ob)
{
- int length;
- m_rotation = AUTO_ROTATION_DEGREE_UNKNOWN;
+ m_alg->stop();
- get_data(&m_last_data, &length);
-
- m_alg->start();
-
- m_accel_sensor->add_interval((intptr_t)this , m_interval, true);
- m_accel_sensor->start();
-
- return activate();
+ /* if OP_DEFAULT is returned,
+ * this function is not called anymore before start() is called */
+ return OP_DEFAULT;
}
-bool auto_rotation_sensor::on_stop(void)
+int auto_rotation_sensor::set_interval(observer_h ob, int32_t &interval)
{
- m_accel_sensor->delete_interval((intptr_t)this , true);
- m_accel_sensor->stop();
-
- return deactivate();
+ /* Fix internal */
+ interval = 60;
+ return OP_SUCCESS;
}
auto_rotation_alg *auto_rotation_sensor::get_alg(void)
/*
* sensord
*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * 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.
*
*/
-#ifndef _AUTO_ROTATION_SENSOR_H_
-#define _AUTO_ROTATION_SENSOR_H_
+#ifndef __AUTO_ROTATION_SENSOR_H__
+#define __AUTO_ROTATION_SENSOR_H__
-#include <virtual_sensor.h>
+#include <fusion_sensor.h>
#include <sensor_types.h>
-#include <auto_rotation_alg.h>
-class auto_rotation_sensor : public virtual_sensor {
+#include "auto_rotation_alg.h"
+
+class auto_rotation_sensor : public fusion_sensor {
public:
auto_rotation_sensor();
virtual ~auto_rotation_sensor();
- /* initialize sensor */
- bool init(void);
+ int get_sensor_info(const sensor_info2_t **info);
+ int get_required_sensors(const required_sensor_s **sensors);
- /* sensor info */
- virtual sensor_type_t get_type(void);
- virtual unsigned int get_event_type(void);
- virtual const char* get_name(void);
+ int update(uint32_t id, sensor_data_t *data, int len);
+ int get_data(sensor_data_t **data, int *len);
- virtual bool get_sensor_info(sensor_info &info);
+ int start(observer_h ob);
+ int stop(observer_h ob);
- /* synthesize event */
- virtual void synthesize(const sensor_event_t& event);
+ int set_interval(observer_h ob, int32_t &interval);
- /* get data */
- virtual int get_data(sensor_data_t **data, int *length);
private:
- sensor_base *m_accel_sensor;
- auto_rotation_alg *m_alg;
+ bool init(void);
+ void deinit(void);
+
+ auto_rotation_alg *get_alg(void);
int m_rotation;
- unsigned int m_interval;
unsigned long long m_rotation_time;
- virtual bool set_interval(unsigned long interval);
- virtual bool set_batch_latency(unsigned long latency);
- virtual bool set_wakeup(int wakeup);
-
- virtual bool pre_start(void);
- virtual bool on_start(void);
- virtual bool on_stop(void);
-
- auto_rotation_alg *get_alg(void);
+ auto_rotation_alg *m_alg;
};
-#endif /* _AUTO_ROTATION_SENSOR_H_ */
+#endif /* __AUTO_ROTATION_SENSOR_H__ */
--- /dev/null
+/*
+ * Copyright (c) 2016 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 <sensor_log.h>
+#include <fusion_sensor.h>
+#include <vector>
+
+#ifdef ENABLE_AUTO_ROTATION
+#include "auto_rotation/auto_rotation_sensor.h"
+#endif
+#ifdef ENABLE_GRAVITY
+#include "gravity/gravity_lowpass_sensor.h"
+#include "gravity/gravity_comp_sensor.h"
+#endif
+#ifdef ENABLE_LINEAR_ACCEL
+#include "linear_accel/linear_accel_sensor.h"
+#endif
+
+static std::vector<fusion_sensor_t> sensors;
+
+template<typename _sensor>
+void create_sensor(const char *name)
+{
+ fusion_sensor *instance = NULL;
+ try {
+ instance = new _sensor;
+ } catch (std::exception &e) {
+ _E("Failed to create %s sensor, exception: %s", name, e.what());
+ return;
+ } catch (int err) {
+ _ERRNO(err, _E, "Failed to create %s sensor device", name);
+ return;
+ }
+
+ sensors.push_back(instance);
+}
+
+extern "C" int create(fusion_sensor_t **fsensors)
+{
+#ifdef ENABLE_AUTO_ROTATION
+ create_sensor<auto_rotation_sensor>("Accelerometer");
+#endif
+
+#ifdef ENABLE_GRAVITY
+ create_sensor<gravity_lowpass_sensor>("Gravity(Lowpass)");
+ create_sensor<gravity_comp_sensor>("Gravity(Complementary)");
+#endif
+
+#ifdef ENABLE_LINEAR_ACCEL
+ create_sensor<linear_accel_sensor>("Linear Acceleration Sensor");
+#endif
+
+ *fsensors = &sensors[0];
+ return sensors.size();
+}