From f0b884c4461d0bcaf247f70c260dd3e434c62b50 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Thu, 20 Nov 2014 11:08:23 +0530 Subject: [PATCH 01/16] Renaming cconfig files and references to csensor_config renaming cconfig to csensor_config to add cvirtual_sensor_config class for adding virtual sensor configuration. A virtual parent class cconfig will be added later. Change-Id: I801793991233a0b27cafdf0792c57443a098a067 --- src/accel/accel_sensor_hal.cpp | 6 ++--- src/geo/geo_sensor_hal.cpp | 9 +++----- src/gyro/gyro_sensor_hal.cpp | 7 +++--- src/light/light_sensor_hal.cpp | 6 ++--- src/pressure/pressure_sensor.cpp | 6 ++--- src/pressure/pressure_sensor_hal.cpp | 9 +++----- src/proxi/proxi_sensor.cpp | 2 -- src/proxi/proxi_sensor.h | 1 - src/proxi/proxi_sensor_hal.cpp | 12 ++++------ src/shared/CMakeLists.txt | 4 ++-- src/shared/{cconfig.cpp => csensor_config.cpp} | 32 +++++++++++++------------- src/shared/{cconfig.h => csensor_config.h} | 20 ++++++++-------- src/shared/sensor_hal.cpp | 6 ++--- src/temperature/temperature_sensor_hal.cpp | 9 +++----- 14 files changed, 57 insertions(+), 72 deletions(-) rename src/shared/{cconfig.cpp => csensor_config.cpp} (84%) rename src/shared/{cconfig.h => csensor_config.h} (85%) diff --git a/src/accel/accel_sensor_hal.cpp b/src/accel/accel_sensor_hal.cpp index f38a0ed..cb74385 100755 --- a/src/accel/accel_sensor_hal.cpp +++ b/src/accel/accel_sensor_hal.cpp @@ -20,13 +20,13 @@ #include #include -#include +#include #include #include using std::ifstream; -using config::CConfig; +using config::csensor_config; #define GRAVITY 9.80665 #define G_TO_MG 1000 @@ -63,7 +63,7 @@ accel_sensor_hal::accel_sensor_hal() , m_fired_time(0) { const string sensorhub_interval_node_name = "accel_poll_delay"; - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); node_path_info_query query; node_path_info info; diff --git a/src/geo/geo_sensor_hal.cpp b/src/geo/geo_sensor_hal.cpp index 872525b..bfbb50e 100755 --- a/src/geo/geo_sensor_hal.cpp +++ b/src/geo/geo_sensor_hal.cpp @@ -19,18 +19,15 @@ #include #include #include - #include -#include - +#include #include #include #include -#include #include using std::ifstream; -using config::CConfig; +using config::csensor_config; #define SENSOR_TYPE_MAGNETIC "MAGNETIC" #define ELEMENT_NAME "NAME" @@ -53,7 +50,7 @@ geo_sensor_hal::geo_sensor_hal() , m_fired_time(INITIAL_TIME) { const string sensorhub_interval_node_name = "mag_poll_delay"; - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); node_path_info_query query; node_path_info info; diff --git a/src/gyro/gyro_sensor_hal.cpp b/src/gyro/gyro_sensor_hal.cpp index fe04ca0..34184bc 100755 --- a/src/gyro/gyro_sensor_hal.cpp +++ b/src/gyro/gyro_sensor_hal.cpp @@ -21,16 +21,15 @@ #include #include -#include +#include #include #include #include -#include #include using std::ifstream; -using config::CConfig; +using config::csensor_config; #define DPS_TO_MDPS 1000 #define MIN_RANGE(RES) (-((1 << (RES))/2)) @@ -63,7 +62,7 @@ gyro_sensor_hal::gyro_sensor_hal() { const string sensorhub_interval_node_name = "gyro_poll_delay"; - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); node_path_info_query query; node_path_info info; diff --git a/src/light/light_sensor_hal.cpp b/src/light/light_sensor_hal.cpp index 445828c..b429ffc 100755 --- a/src/light/light_sensor_hal.cpp +++ b/src/light/light_sensor_hal.cpp @@ -23,12 +23,12 @@ #include #include #include -#include +#include #include #include using std::ifstream; -using config::CConfig; +using config::csensor_config; #define BIAS 1 #define INITIAL_VALUE -1 @@ -52,7 +52,7 @@ light_sensor_hal::light_sensor_hal() throw ENXIO; } - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_VENDOR, m_vendor)) { diff --git a/src/pressure/pressure_sensor.cpp b/src/pressure/pressure_sensor.cpp index e13c3a4..35461a7 100755 --- a/src/pressure/pressure_sensor.cpp +++ b/src/pressure/pressure_sensor.cpp @@ -23,9 +23,9 @@ #include #include #include -#include +#include -using config::CConfig; +using config::csensor_config; using std::bind1st; using std::mem_fun; @@ -79,7 +79,7 @@ bool pressure_sensor::init() string model_id = m_sensor_hal->get_model_id(); - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); double temperature_resolution; diff --git a/src/pressure/pressure_sensor_hal.cpp b/src/pressure/pressure_sensor_hal.cpp index 37dc7ac..764adc9 100755 --- a/src/pressure/pressure_sensor_hal.cpp +++ b/src/pressure/pressure_sensor_hal.cpp @@ -19,18 +19,15 @@ #include #include #include - #include -#include - +#include #include #include #include -#include #include using std::ifstream; -using config::CConfig; +using config::csensor_config; #define SENSOR_TYPE_PRESSURE "PRESSURE" #define ELEMENT_NAME "NAME" @@ -61,7 +58,7 @@ pressure_sensor_hal::pressure_sensor_hal() throw ENXIO; } - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) { diff --git a/src/proxi/proxi_sensor.cpp b/src/proxi/proxi_sensor.cpp index c55bc74..37dfce6 100755 --- a/src/proxi/proxi_sensor.cpp +++ b/src/proxi/proxi_sensor.cpp @@ -19,11 +19,9 @@ #include #include - #include #include - #define SENSOR_NAME "PROXI_SENSOR" proxi_sensor::proxi_sensor() diff --git a/src/proxi/proxi_sensor.h b/src/proxi/proxi_sensor.h index b61da04..f058724 100755 --- a/src/proxi/proxi_sensor.h +++ b/src/proxi/proxi_sensor.h @@ -21,7 +21,6 @@ #define _PROXI_SENSOR_H_ #include - #include #include diff --git a/src/proxi/proxi_sensor_hal.cpp b/src/proxi/proxi_sensor_hal.cpp index 1701100..328211e 100755 --- a/src/proxi/proxi_sensor_hal.cpp +++ b/src/proxi/proxi_sensor_hal.cpp @@ -19,16 +19,16 @@ #include #include #include - #include -#include - +#include #include #include #include -#include #include +using std::ifstream; +using config::csensor_config; + #define NO_FLAG 0 #define PROXIMITY_TYPE 8 @@ -42,8 +42,6 @@ #define PROXI_CODE 0x0019 -using std::ifstream; -using config::CConfig; proxi_sensor_hal::proxi_sensor_hal() : m_state(PROXIMITY_STATE_FAR) @@ -51,7 +49,7 @@ proxi_sensor_hal::proxi_sensor_hal() , m_node_handle(-1) { const string sensorhub_interval_node_name = "prox_poll_delay"; - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); node_path_info_query query; node_path_info info; diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt index 8ef03d8..9bad5a5 100755 --- a/src/shared/CMakeLists.txt +++ b/src/shared/CMakeLists.txt @@ -38,7 +38,7 @@ include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) add_library(sensord-server SHARED crw_lock.cpp worker_thread.cpp - cconfig.cpp + csensor_config.cpp csensor_event_queue.cpp csensor_event_dispatcher.cpp csensor_usage.cpp @@ -74,7 +74,7 @@ install(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) install(FILES crw_lock.h worker_thread.h - cconfig.h + csensor_config.h csensor_event_queue.h cinterval_info_list.h sensor_plugin_loader.h diff --git a/src/shared/cconfig.cpp b/src/shared/csensor_config.cpp similarity index 84% rename from src/shared/cconfig.cpp rename to src/shared/csensor_config.cpp index 34a7337..5c831b7 100755 --- a/src/shared/cconfig.cpp +++ b/src/shared/csensor_config.cpp @@ -1,7 +1,7 @@ /* * libsensord-share * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2013 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. @@ -17,7 +17,7 @@ * */ -#include +#include #include "common.h" #include #include @@ -33,17 +33,17 @@ using std::ifstream; #define MODEL_ID_ATTR "id" #define DEFAULT_ATTR "value" -CConfig::CConfig() +csensor_config::csensor_config() { } -CConfig& CConfig::get_instance(void) +csensor_config& csensor_config::get_instance(void) { static bool load_done = false; - static CConfig inst; + static csensor_config inst; if (!load_done) { - inst.load_config(); + inst.load_config(SENSOR_CONFIG_FILE_PATH); inst.get_device_id(); if (!inst.m_device_id.empty()) INFO("Device ID = %s", inst.m_device_id.c_str()); @@ -55,12 +55,12 @@ CConfig& CConfig::get_instance(void) return inst; } -bool CConfig::load_config(const string& config_path) +bool csensor_config::load_config(const string& config_path) { xmlDocPtr doc; xmlNodePtr cur; - DBG("CConfig::load_config(\"%s\") is called!\n",config_path.c_str()); + DBG("csensor_config::load_config(\"%s\") is called!\n",config_path.c_str()); doc = xmlParseFile(config_path.c_str()); @@ -163,7 +163,7 @@ bool CConfig::load_config(const string& config_path) } -bool CConfig::get(const string& sensor_type,const string& model_id, const string& element, const string& attr, string& value) +bool csensor_config::get(const string& sensor_type,const string& model_id, const string& element, const string& attr, string& value) { auto it_model_list = m_sensor_config.find(sensor_type); @@ -198,7 +198,7 @@ bool CConfig::get(const string& sensor_type,const string& model_id, const string return true; } -bool CConfig::get(const string& sensor_type, const string& model_id, const string& element, const string& attr, double& value) +bool csensor_config::get(const string& sensor_type, const string& model_id, const string& element, const string& attr, double& value) { string str_value; @@ -213,7 +213,7 @@ bool CConfig::get(const string& sensor_type, const string& model_id, const strin return true; } -bool CConfig::get(const string& sensor_type, const string& model_id, const string& element, const string& attr, long& value) +bool csensor_config::get(const string& sensor_type, const string& model_id, const string& element, const string& attr, long& value) { string str_value; @@ -228,7 +228,7 @@ bool CConfig::get(const string& sensor_type, const string& model_id, const strin return true; } -bool CConfig::get(const string& sensor_type, const string& model_id, const string& element, string& value) +bool csensor_config::get(const string& sensor_type, const string& model_id, const string& element, string& value) { if (get(sensor_type, model_id, element, m_device_id, value)) return true; @@ -239,7 +239,7 @@ bool CConfig::get(const string& sensor_type, const string& model_id, const strin return false; } -bool CConfig::get(const string& sensor_type, const string& model_id, const string& element, double& value) +bool csensor_config::get(const string& sensor_type, const string& model_id, const string& element, double& value) { if (get(sensor_type, model_id, element, m_device_id, value)) return true; @@ -250,7 +250,7 @@ bool CConfig::get(const string& sensor_type, const string& model_id, const strin return false; } -bool CConfig::get(const string& sensor_type, const string& model_id, const string& element, long& value) +bool csensor_config::get(const string& sensor_type, const string& model_id, const string& element, long& value) { if (get(sensor_type, model_id, element, m_device_id, value)) return true; @@ -261,7 +261,7 @@ bool CConfig::get(const string& sensor_type, const string& model_id, const strin return false; } -bool CConfig::is_supported(const string& sensor_type,const string& model_id) +bool csensor_config::is_supported(const string& sensor_type,const string& model_id) { auto it_model_list = m_sensor_config.find(sensor_type); @@ -276,7 +276,7 @@ bool CConfig::is_supported(const string& sensor_type,const string& model_id) return true; } -bool CConfig::get_device_id(void) +bool csensor_config::get_device_id(void) { const string INFO_INI_PATH = "/etc/info.ini"; const string START_DELIMETER = "Model="; diff --git a/src/shared/cconfig.h b/src/shared/csensor_config.h similarity index 85% rename from src/shared/cconfig.h rename to src/shared/csensor_config.h index 0017e27..03e72ea 100755 --- a/src/shared/cconfig.h +++ b/src/shared/csensor_config.h @@ -1,7 +1,7 @@ /* * libsensord-share * - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2013 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. @@ -17,8 +17,8 @@ * */ -#if !defined(_CCONFIG_CLASS_H_) -#define _CCONFIG_CLASS_H_ +#if !defined(_CSENSOR_CONFIG_CLASS_H_) +#define _CSENSOR_CONFIG_CLASS_H_ #include #include @@ -28,7 +28,7 @@ using std::unordered_map; using std::string; using std::istringstream; -#define CONFIG_FILE_PATH "/usr/etc/sensors.xml" +#define SENSOR_CONFIG_FILE_PATH "/usr/etc/sensors.xml" typedef unordered_map Element; /* @@ -76,17 +76,17 @@ typedef unordered_map Sensor_config; namespace config { - class CConfig + class csensor_config { private: - CConfig(); - CConfig(CConfig const&) {}; - CConfig& operator=(CConfig const&); - bool load_config(const string& config_path = CONFIG_FILE_PATH); + csensor_config(); + csensor_config(csensor_config const&) {}; + csensor_config& operator=(csensor_config const&); + bool load_config(const string& config_path); Sensor_config m_sensor_config; string m_device_id; public: - static CConfig& get_instance(void); + static csensor_config& get_instance(void); bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, string& value); bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, double& value); diff --git a/src/shared/sensor_hal.cpp b/src/shared/sensor_hal.cpp index e036203..55c20f7 100755 --- a/src/shared/sensor_hal.cpp +++ b/src/shared/sensor_hal.cpp @@ -21,11 +21,11 @@ #include #include #include -#include +#include using std::ifstream; using std::fstream; -using config::CConfig; +using config::csensor_config; cmutex sensor_hal::m_shared_mutex; @@ -310,7 +310,7 @@ bool sensor_hal::find_model_id(int method, const string &sensor_type, string &mo infile >> name; - if (CConfig::get_instance().is_supported(sensor_type, name)) { + if (csensor_config::get_instance().is_supported(sensor_type, name)) { model_id = name; find = true; break; diff --git a/src/temperature/temperature_sensor_hal.cpp b/src/temperature/temperature_sensor_hal.cpp index 2ba0b57..9d81381 100755 --- a/src/temperature/temperature_sensor_hal.cpp +++ b/src/temperature/temperature_sensor_hal.cpp @@ -19,17 +19,14 @@ #include #include #include - #include -#include - +#include #include #include -#include #include using std::ifstream; -using config::CConfig; +using config::csensor_config; #define SENSOR_TYPE_TEMPERATURE "TEMPERATURE" #define ELEMENT_NAME "NAME" @@ -56,7 +53,7 @@ temperature_sensor_hal::temperature_sensor_hal() throw ENXIO; } - CConfig &config = CConfig::get_instance(); + csensor_config &config = csensor_config::get_instance(); if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_VENDOR, m_vendor)) { -- 2.7.4 From c5d0338570c682b4f7d38882dd9a4232d5917422 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Thu, 20 Nov 2014 11:54:27 +0530 Subject: [PATCH 02/16] Adding virtual sensor XML and parser files Adding new virtual sensor XML file and XML parser files that are needed for configuration of the virtual sensors. Change-Id: I66673a52e23c67e1234a0abce1f10b959cb5610f --- src/shared/CMakeLists.txt | 2 + src/shared/cvirtual_sensor_config.cpp | 319 ++++++++++++++++++++++++++++++++++ src/shared/cvirtual_sensor_config.h | 82 +++++++++ virtual_sensors.xml.in | 41 +++++ 4 files changed, 444 insertions(+) create mode 100755 src/shared/cvirtual_sensor_config.cpp create mode 100755 src/shared/cvirtual_sensor_config.h create mode 100644 virtual_sensors.xml.in diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt index 9bad5a5..4a305da 100755 --- a/src/shared/CMakeLists.txt +++ b/src/shared/CMakeLists.txt @@ -39,6 +39,7 @@ add_library(sensord-server SHARED crw_lock.cpp worker_thread.cpp csensor_config.cpp + cvirtual_sensor_config.cpp csensor_event_queue.cpp csensor_event_dispatcher.cpp csensor_usage.cpp @@ -75,6 +76,7 @@ install(FILES crw_lock.h worker_thread.h csensor_config.h + cvirtual_sensor_config.h csensor_event_queue.h cinterval_info_list.h sensor_plugin_loader.h diff --git a/src/shared/cvirtual_sensor_config.cpp b/src/shared/cvirtual_sensor_config.cpp new file mode 100755 index 0000000..1666430 --- /dev/null +++ b/src/shared/cvirtual_sensor_config.cpp @@ -0,0 +1,319 @@ +/* + * libsensord-share + * + * Copyright (c) 2013 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 "common.h" +#include +#include +#include +#include +#include +#include + +using std::ifstream; +using std::string; +using std::stringstream; + +#define ROOT_ELEMENT "VIRTUAL_SENSOR" +#define TEXT_ELEMENT "text" +#define MODEL_ID_ATTR "id" +#define DEFAULT_ATTR "value" +#define DEFAULT_ATTR1 "value1" +#define DEFAULT_ATTR2 "value2" +#define DEFAULT_ATTR3 "value3" + +cvirtual_sensor_config::cvirtual_sensor_config() +{ +} + +cvirtual_sensor_config& cvirtual_sensor_config::get_instance(void) +{ + static bool load_done = false; + static cvirtual_sensor_config inst; + + if (!load_done) { + inst.load_config(VIRTUAL_SENSOR_CONFIG_FILE_PATH); + inst.get_device_id(); + if (!inst.m_device_id.empty()) + INFO("Device ID = %s", inst.m_device_id.c_str()); + else + ERR("Failed to get Device ID"); + load_done = true; + } + + return inst; +} + +bool cvirtual_sensor_config::load_config(const string& config_path) +{ + xmlDocPtr doc; + xmlNodePtr cur; + + DBG("cvirtual_sensor_config::load_config(\"%s\") is called!\n",config_path.c_str()); + + doc = xmlParseFile(config_path.c_str()); + + if (doc == NULL) { + ERR("There is no %s\n",config_path.c_str()); + return false; + } + + cur = xmlDocGetRootElement(doc); + if(cur == NULL) { + ERR("There is no root element in %s\n",config_path.c_str()); + xmlFreeDoc(doc); + return false; + } + + if(xmlStrcmp(cur->name, (const xmlChar *)ROOT_ELEMENT)) { + ERR("Wrong type document: there is no [%s] root element in %s\n",ROOT_ELEMENT,config_path.c_str()); + xmlFreeDoc(doc); + return false; + } + + xmlNodePtr virtual_sensor_node_ptr; + xmlNodePtr element_node_ptr; + xmlAttrPtr attr_ptr; + char* prop = NULL; + + virtual_sensor_node_ptr = cur->xmlChildrenNode; + + while (virtual_sensor_node_ptr != NULL) { + //skip garbage element, [text] + if (!xmlStrcmp(virtual_sensor_node_ptr->name,(const xmlChar *)TEXT_ELEMENT)) { + virtual_sensor_node_ptr = virtual_sensor_node_ptr->next; + continue; + } + + //insert Model_list to config map + m_virtual_sensor_config[(const char*)virtual_sensor_node_ptr->name]; + DBG("<%s>\n",(const char*)virtual_sensor_node_ptr->name); + + element_node_ptr = virtual_sensor_node_ptr->xmlChildrenNode; + while (element_node_ptr != NULL) { + //skip garbage element, [text] + if (!xmlStrcmp(element_node_ptr->name,(const xmlChar *)TEXT_ELEMENT)) { + element_node_ptr = element_node_ptr->next; + continue; + } + + //insert Element to Model + m_virtual_sensor_config[(const char*)virtual_sensor_node_ptr->name][(const char*)element_node_ptr->name]; + DBG("<%s><%s>\n",(const char*)virtual_sensor_node_ptr->name,(const char*)element_node_ptr->name); + + attr_ptr = element_node_ptr->properties; + while (attr_ptr != NULL) { + + string key,value; + key = (char*)attr_ptr->name; + prop = (char*)xmlGetProp(element_node_ptr,attr_ptr->name); + value = prop; + free(prop); + + //insert attribute to Element + m_virtual_sensor_config[(const char*)virtual_sensor_node_ptr->name][(const char*)element_node_ptr->name][key]=value; + DBG("<%s><%s \"%s\"=\"%s\">\n",(const char*)virtual_sensor_node_ptr->name,(const char*)element_node_ptr->name,key.c_str(),value.c_str()); + attr_ptr = attr_ptr->next; + } + + + element_node_ptr = element_node_ptr->next; + } + + DBG("\n"); + virtual_sensor_node_ptr = virtual_sensor_node_ptr->next; + } + + xmlFreeDoc(doc); + return true; +} + +bool cvirtual_sensor_config::get(const string& sensor_type, const string& element, const string& attr, string& value) +{ + auto it_virtual_sensor_list = m_virtual_sensor_config.find(sensor_type); + + if (it_virtual_sensor_list == m_virtual_sensor_config.end()) { + ERR("There is no <%s> element\n",sensor_type.c_str()); + return false; + } + + auto it_element = it_virtual_sensor_list->second.find(element); + + if (it_element == it_virtual_sensor_list->second.end()) { + ERR("There is no <%s><%s> element\n",sensor_type.c_str(),element.c_str()); + return false; + } + + auto it_attr = it_element->second.find(attr); + + if (it_attr == it_element->second.end()) { + DBG("There is no <%s><%s \"%s\">\n",sensor_type.c_str(),element.c_str(),attr.c_str()); + return false; + } + + value = it_attr->second; + + return true; +} + +bool cvirtual_sensor_config::get(const string& sensor_type, const string& element, const string& attr, float *value) +{ + string str_value; + + if (get(sensor_type,element,attr,str_value) == false) + return false; + + stringstream str_stream(str_value); + + str_stream >> *value; + + return true; +} + +bool cvirtual_sensor_config::get(const string& sensor_type, const string& element, const string& attr, int *value) +{ + string str_value; + + if (get(sensor_type,element,attr,str_value) == false) + return false; + + stringstream str_stream(str_value); + + str_stream >> *value; + + return true; +} + +bool cvirtual_sensor_config::get(const string& sensor_type, const string& element, string& value) +{ + if (get(sensor_type, element, DEFAULT_ATTR, value)) + return true; + + return false; +} + +bool cvirtual_sensor_config::get(const string& sensor_type, const string& element, float *value, int count) +{ + if (count == 1) + { + if (get(sensor_type, element, DEFAULT_ATTR, value)) + return true; + } + else if (count == 3) + { + if (!get(sensor_type, element, DEFAULT_ATTR1, value)) + return false; + + value++; + + if (!get(sensor_type, element, DEFAULT_ATTR2, value)) + return false; + + value++; + + if (!get(sensor_type, element, DEFAULT_ATTR3, value)) + return false; + + return true; + } + else + { + DBG("Count value not supported.\n"); + } + + return false; +} + +bool cvirtual_sensor_config::get(const string& sensor_type, const string& element, int *value, int count) +{ + if (count == 1) + { + if (get(sensor_type, element, DEFAULT_ATTR, value)) + return true; + } + else if (count == 3) + { + if (!get(sensor_type, element, DEFAULT_ATTR1, value)) + return false; + + value++; + + if (!get(sensor_type, element, DEFAULT_ATTR2, value)) + return false; + + value++; + + if (!get(sensor_type, element, DEFAULT_ATTR3, value)) + return false; + + return true; + } + else + { + DBG("Count value not supported.\n"); + } + + return false; +} + +bool cvirtual_sensor_config::is_supported(const string& sensor_type) +{ + auto it_virtual_sensor_list = m_virtual_sensor_config.find(sensor_type); + + if (it_virtual_sensor_list == m_virtual_sensor_config.end()) + return false; + + return true; +} + +bool cvirtual_sensor_config::get_device_id(void) +{ + const string INFO_INI_PATH = "/etc/info.ini"; + const string START_DELIMETER = "Model="; + const string END_DELIMETER = ";"; + string line; + ifstream in_file; + std::size_t start_pos, end_pos; + bool ret = false; + + in_file.open(INFO_INI_PATH); + + if (!in_file.is_open()) + return false; + + while (!in_file.eof()) { + getline(in_file, line); + start_pos = line.find(START_DELIMETER); + + if (start_pos != std::string::npos) { + start_pos = start_pos + START_DELIMETER.size(); + end_pos = line.find(END_DELIMETER, start_pos); + + if (end_pos != std::string::npos) { + m_device_id = line.substr(start_pos, end_pos - start_pos); + ret = true; + break; + } + } + } + + in_file.close(); + + return ret; +} diff --git a/src/shared/cvirtual_sensor_config.h b/src/shared/cvirtual_sensor_config.h new file mode 100755 index 0000000..35e93ad --- /dev/null +++ b/src/shared/cvirtual_sensor_config.h @@ -0,0 +1,82 @@ +/* + * libsensord-share + * + * Copyright (c) 2013 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. + * + */ + +#if !defined(_CVIRTUAL_SENSOR_CONFIG_CLASS_H_) +#define _CVIRTUAL_SENSOR_CONFIG_CLASS_H_ + +#include +#include +#include + +using std::unordered_map; +using std::string; +using std::istringstream; + +#define VIRTUAL_SENSOR_CONFIG_FILE_PATH "/usr/etc/virtual_sensors.xml" + +typedef unordered_map Element; +/* +* an Element is a group of attributes +* +* +*/ + +typedef unordered_map Virtual_sensor; +/* +* a Virtual_sensor is a group of elements to consist of one virtual sensor's configuration +* +* +* +* ... +*/ + +typedef unordered_map Virtual_sensor_config; +/* +* a Virtual_sensor_config represents virtual_sensors.xml +* +* +* +* +*/ + +class cvirtual_sensor_config +{ +private: + cvirtual_sensor_config(); + cvirtual_sensor_config(cvirtual_sensor_config const&) {}; + cvirtual_sensor_config& operator=(cvirtual_sensor_config const&); + bool load_config(const string& config_path); + Virtual_sensor_config m_virtual_sensor_config; + string m_device_id; +public: + static cvirtual_sensor_config& get_instance(void); + + bool get(const string& sensor_type, const string& element, const string& attr, string& value); + bool get(const string& sensor_type, const string& element, const string& attr, float *value); + bool get(const string& sensor_type, const string& element, const string& attr, int *value); + + bool get(const string& sensor_type, const string& element, string& value); + bool get(const string& sensor_type, const string& element, float *value, int count =1); + bool get(const string& sensor_type, const string& element, int *value, int count = 1); + + bool is_supported(const string &sensor_type); + bool get_device_id(void); +}; + +#endif diff --git a/virtual_sensors.xml.in b/virtual_sensors.xml.in new file mode 100644 index 0000000..42c9d72 --- /dev/null +++ b/virtual_sensors.xml.in @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.7.4 From 0a27751171b2bdef0c56d9626c950799a009a01d Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 21 Nov 2014 09:01:55 +0530 Subject: [PATCH 03/16] Updated year in license header to 2014 Updating license header year from 2013 to 2014 Change-Id: I11173a52e23c67e1234a0abce1f10b959cb5610f --- src/shared/csensor_config.cpp | 2 +- src/shared/csensor_config.h | 2 +- src/shared/cvirtual_sensor_config.cpp | 2 +- src/shared/cvirtual_sensor_config.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/csensor_config.cpp b/src/shared/csensor_config.cpp index 5c831b7..013a086 100755 --- a/src/shared/csensor_config.cpp +++ b/src/shared/csensor_config.cpp @@ -1,7 +1,7 @@ /* * libsensord-share * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2014 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. diff --git a/src/shared/csensor_config.h b/src/shared/csensor_config.h index 03e72ea..0c77f98 100755 --- a/src/shared/csensor_config.h +++ b/src/shared/csensor_config.h @@ -1,7 +1,7 @@ /* * libsensord-share * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2014 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. diff --git a/src/shared/cvirtual_sensor_config.cpp b/src/shared/cvirtual_sensor_config.cpp index 1666430..7aebd2d 100755 --- a/src/shared/cvirtual_sensor_config.cpp +++ b/src/shared/cvirtual_sensor_config.cpp @@ -1,7 +1,7 @@ /* * libsensord-share * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2014 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. diff --git a/src/shared/cvirtual_sensor_config.h b/src/shared/cvirtual_sensor_config.h index 35e93ad..754fd00 100755 --- a/src/shared/cvirtual_sensor_config.h +++ b/src/shared/cvirtual_sensor_config.h @@ -1,7 +1,7 @@ /* * libsensord-share * - * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2014 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. -- 2.7.4 From 453331489e51e420efa6b32102a7b376a209abe6 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 21 Nov 2014 09:27:29 +0530 Subject: [PATCH 04/16] Updating Orientation Virtual Sensor Code - Updating Orientation sensor after testing on SDK - Updating based on latest public code - Updating for new XML based configuration file Change-Id: I089d201406e03f283ed6a9bac2b1dbb8241bc219 --- packaging/sensord.spec | 2 +- src/orientation/orientation_sensor.cpp | 230 +++++++++++++++++++++++++-------- src/orientation/orientation_sensor.h | 30 ++++- 3 files changed, 202 insertions(+), 60 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index eb9d4c2..78f5b98 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -15,7 +15,7 @@ Source2: sensord.socket %define geo_state ON %define pressure_state OFF %define temperature_state OFF -%define orientation_state OFF +%define orientation_state ON %define gravity_state OFF %define linear_accel_state OFF diff --git a/src/orientation/orientation_sensor.cpp b/src/orientation/orientation_sensor.cpp index f4fbaa1..b1222e2 100755 --- a/src/orientation/orientation_sensor.cpp +++ b/src/orientation/orientation_sensor.cpp @@ -30,8 +30,10 @@ #include #include #include +#include #define SENSOR_NAME "ORIENTATION_SENSOR" +#define SENSOR_TYPE_ORIENTATION "ORIENTATION" #define ACCELEROMETER_ENABLED 0x01 #define GYROSCOPE_ENABLED 0x02 @@ -39,26 +41,28 @@ #define ORIENTATION_ENABLED 7 #define INITIAL_VALUE -1 -#define INITIAL_TIME 0 -// Below Defines const variables to be input from sensor config files once code is stabilized -#define SAMPLING_TIME 100 #define MS_TO_US 1000 -float bias_accel[] = {0.098586, 0.18385, (10.084 - GRAVITY)}; -float bias_gyro[] = {-5.3539, 0.24325, 2.3391}; -float bias_magnetic[] = {0, -37.6, +37.6}; -int sign_accel[] = {+1, +1, +1}; -int sign_gyro[] = {+1, +1, +1}; -int sign_magnetic[] = {+1, -1, +1}; -float scale_accel = 1; -float scale_gyro = 580 * 2; -float scale_magnetic = 1; - -int pitch_phase_compensation = 1; -int roll_phase_compensation = 1; -int yaw_phase_compensation = -1; -int magnetic_alignment_factor = 1; +#define AZIMUTH_OFFSET 360 + +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_DEFAULT_SAMPLING_TIME "DEFAULT_SAMPLING_TIME" +#define ELEMENT_ACCEL_STATIC_BIAS "ACCEL_STATIC_BIAS" +#define ELEMENT_GYRO_STATIC_BIAS "GYRO_STATIC_BIAS" +#define ELEMENT_GEOMAGNETIC_STATIC_BIAS "GEOMAGNETIC_STATIC_BIAS" +#define ELEMENT_ACCEL_ROTATION_DIRECTION_COMPENSATION "ACCEL_ROTATION_DIRECTION_COMPENSATION" +#define ELEMENT_GYRO_ROTATION_DIRECTION_COMPENSATION "GYRO_ROTATION_DIRECTION_COMPENSATION" +#define ELEMENT_GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION "GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION" +#define ELEMENT_ACCEL_SCALE "ACCEL_SCALE" +#define ELEMENT_GYRO_SCALE "GYRO_SCALE" +#define ELEMENT_GEOMAGNETIC_SCALE "GEOMAGNETIC_SCALE" +#define ELEMENT_MAGNETIC_ALIGNMENT_FACTOR "MAGNETIC_ALIGNMENT_FACTOR" +#define ELEMENT_PITCH_ROTATION_COMPENSATION "PITCH_ROTATION_COMPENSATION" +#define ELEMENT_ROLL_ROTATION_COMPENSATION "ROLL_ROTATION_COMPENSATION" +#define ELEMENT_AZIMUTH_ROTATION_COMPENSATION "AZIMUTH_ROTATION_COMPENSATION" void pre_process_data(sensor_data &data_out, const float *data_in, float *bias, int *sign, float scale) { @@ -73,13 +77,129 @@ orientation_sensor::orientation_sensor() , m_magnetic_sensor(NULL) , m_roll(INITIAL_VALUE) , m_pitch(INITIAL_VALUE) -, m_yaw(INITIAL_VALUE) +, m_azimuth(INITIAL_VALUE) { + cvirtual_sensor_config &config = cvirtual_sensor_config::get_instance(); + m_name = string(SENSOR_NAME); register_supported_event(ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME); - m_interval = SAMPLING_TIME * MS_TO_US; m_timestamp = get_timestamp(); m_enable_orientation = 0; + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty\n"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_RAW_DATA_UNIT, m_raw_data_unit)) { + ERR("[RAW_DATA_UNIT] is empty\n"); + throw ENXIO; + } + + INFO("m_raw_data_unit = %s", m_raw_data_unit.c_str()); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_DEFAULT_SAMPLING_TIME, &m_default_sampling_time)) { + ERR("[DEFAULT_SAMPLING_TIME] is empty\n"); + throw ENXIO; + } + + INFO("m_default_sampling_time = %d", m_default_sampling_time); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ACCEL_STATIC_BIAS, m_accel_static_bias, 3)) { + ERR("[ACCEL_STATIC_BIAS] is empty\n"); + throw ENXIO; + } + + INFO("m_accel_static_bias = (%f, %f, %f)", m_accel_static_bias[0], m_accel_static_bias[1], m_accel_static_bias[2]); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_GYRO_STATIC_BIAS, m_gyro_static_bias,3)) { + ERR("[GYRO_STATIC_BIAS] is empty\n"); + throw ENXIO; + } + + INFO("m_gyro_static_bias = (%f, %f, %f)", m_gyro_static_bias[0], m_gyro_static_bias[1], m_gyro_static_bias[2]); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_GEOMAGNETIC_STATIC_BIAS, m_geomagnetic_static_bias, 3)) { + ERR("[GEOMAGNETIC_STATIC_BIAS] is empty\n"); + throw ENXIO; + } + + INFO("m_geomagnetic_static_bias = (%f, %f, %f)", m_geomagnetic_static_bias[0], m_geomagnetic_static_bias[1], m_geomagnetic_static_bias[2]); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ACCEL_ROTATION_DIRECTION_COMPENSATION, m_accel_rotation_direction_compensation, 3)) { + ERR("[ACCEL_ROTATION_DIRECTION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_accel_rotation_direction_compensation = (%d, %d, %d)", m_accel_rotation_direction_compensation[0], m_accel_rotation_direction_compensation[1], m_accel_rotation_direction_compensation[2]); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_GYRO_ROTATION_DIRECTION_COMPENSATION, m_gyro_rotation_direction_compensation, 3)) { + ERR("[GYRO_ROTATION_DIRECTION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_gyro_rotation_direction_compensation = (%d, %d, %d)", m_gyro_rotation_direction_compensation[0], m_gyro_rotation_direction_compensation[1], m_gyro_rotation_direction_compensation[2]); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION, m_geomagnetic_rotation_direction_compensation, 3)) { + ERR("[GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_geomagnetic_rotation_direction_compensation = (%d, %d, %d)", m_geomagnetic_rotation_direction_compensation[0], m_geomagnetic_rotation_direction_compensation[1], m_geomagnetic_rotation_direction_compensation[2]); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ACCEL_SCALE, &m_accel_scale)) { + ERR("[ACCEL_SCALE] is empty\n"); + throw ENXIO; + } + + INFO("m_accel_scale = %f", m_accel_scale); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_GYRO_SCALE, &m_gyro_scale)) { + ERR("[GYRO_SCALE] is empty\n"); + throw ENXIO; + } + + INFO("m_gyro_scale = %f", m_gyro_scale); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_GEOMAGNETIC_SCALE, &m_geomagnetic_scale)) { + ERR("[GEOMAGNETIC_SCALE] is empty\n"); + throw ENXIO; + } + + INFO("m_geomagnetic_scale = %f", m_geomagnetic_scale); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_MAGNETIC_ALIGNMENT_FACTOR, &m_magnetic_alignment_factor)) { + ERR("[MAGNETIC_ALIGNMENT_FACTOR] is empty\n"); + throw ENXIO; + } + + INFO("m_magnetic_alignment_factor = %d", m_magnetic_alignment_factor); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_AZIMUTH_ROTATION_COMPENSATION, &m_azimuth_rotation_compensation)) { + ERR("[AZIMUTH_ROTATION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_azimuth_rotation_compensation = %d", m_azimuth_rotation_compensation); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_PITCH_ROTATION_COMPENSATION, &m_pitch_rotation_compensation)) { + ERR("[PITCH_ROTATION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_pitch_rotation_compensation = %d", m_pitch_rotation_compensation); + + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ROLL_ROTATION_COMPENSATION, &m_roll_rotation_compensation)) { + ERR("[ROLL_ROTATION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_roll_rotation_compensation = %d", m_roll_rotation_compensation); + + m_interval = m_default_sampling_time * MS_TO_US; + } orientation_sensor::~orientation_sensor() @@ -181,7 +301,7 @@ void orientation_sensor::synthesize(const sensor_event_t &event, vector= 0) + orientation_event.data.values[0] = euler_orientation.m_ang.m_vec[2]; + else + orientation_event.data.values[0] = euler_orientation.m_ang.m_vec[2] + AZIMUTH_OFFSET; + + push(orientation_event); } return; @@ -257,40 +380,41 @@ int orientation_sensor::get_sensor_data(const unsigned int event_type, sensor_da m_gyro_sensor->get_sensor_data(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME, gyro_data); m_magnetic_sensor->get_sensor_data(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME, magnetic_data); - pre_process_data(accel, accel_data.values, bias_accel, sign_accel, scale_accel); - pre_process_data(gyro, gyro_data.values, bias_gyro, sign_gyro, scale_gyro); - pre_process_data(magnetic, magnetic_data.values, bias_magnetic, sign_magnetic, scale_magnetic); + pre_process_data(accel, accel_data.values, m_accel_static_bias, m_accel_rotation_direction_compensation, m_accel_scale); + pre_process_data(gyro, gyro_data.values, m_gyro_static_bias, m_gyro_rotation_direction_compensation, m_gyro_scale); + pre_process_data(magnetic, magnetic_data.values, m_geomagnetic_static_bias, m_geomagnetic_rotation_direction_compensation, m_geomagnetic_scale); accel.m_time_stamp = accel_data.timestamp; gyro.m_time_stamp = gyro_data.timestamp; magnetic.m_time_stamp = magnetic_data.timestamp; - m_orientation.m_pitch_phase_compensation = pitch_phase_compensation; - m_orientation.m_roll_phase_compensation = roll_phase_compensation; - m_orientation.m_yaw_phase_compensation = yaw_phase_compensation; - m_orientation.m_magnetic_alignment_factor = magnetic_alignment_factor; + m_orientation.m_pitch_phase_compensation = m_pitch_rotation_compensation; + m_orientation.m_roll_phase_compensation = m_roll_rotation_compensation; + m_orientation.m_azimuth_phase_compensation = m_azimuth_rotation_compensation; + m_orientation.m_magnetic_alignment_factor = m_magnetic_alignment_factor; euler_orientation = m_orientation.get_orientation(accel, gyro, magnetic); - data.data_accuracy = SENSOR_ACCURACY_GOOD; - data.data_unit_idx = SENSOR_UNIT_DEGREE; + data.accuracy = SENSOR_ACCURACY_GOOD; data.timestamp = get_timestamp(); - data.values[0] = euler_orientation.m_ang.m_vec[0]; - data.values[1] = euler_orientation.m_ang.m_vec[1]; - data.values[2] = euler_orientation.m_ang.m_vec[2]; - data.values_num = 3; + data.values[1] = euler_orientation.m_ang.m_vec[0]; + data.values[2] = euler_orientation.m_ang.m_vec[1]; + if (euler_orientation.m_ang.m_vec[2] >= 0) + data.values[0] = euler_orientation.m_ang.m_vec[2]; + else + data.values[0] = euler_orientation.m_ang.m_vec[2] + AZIMUTH_OFFSET; + data.value_count = 3; return 0; } bool orientation_sensor::get_properties(sensor_properties_t &properties) { - properties.sensor_unit_idx = SENSOR_UNIT_DEGREE; - properties.sensor_min_range = -180; - properties.sensor_max_range = 180; - properties.sensor_resolution = 1; + properties.min_range = -180; + properties.max_range = 360; + properties.resolution = 1; - strncpy(properties.sensor_vendor, "Samsung", MAX_KEY_LENGTH); - strncpy(properties.sensor_name, SENSOR_NAME, MAX_KEY_LENGTH); + properties.vendor = "Samsung"; + properties.name = SENSOR_NAME; return true; } diff --git a/src/orientation/orientation_sensor.h b/src/orientation/orientation_sensor.h index f295ccc..ed61891 100755 --- a/src/orientation/orientation_sensor.h +++ b/src/orientation/orientation_sensor.h @@ -20,18 +20,16 @@ #ifndef _ORIENTATION_SENSOR_H_ #define _ORIENTATION_SENSOR_H_ -#include +#include #include #include class orientation_sensor : public virtual_sensor { public: orientation_sensor(); - ~orientation_sensor(); + virtual ~orientation_sensor(); bool init(void); - bool on_start(void); - bool on_stop(void); void synthesize(const sensor_event_t &event, vector &outs); @@ -59,9 +57,29 @@ private: float m_roll; float m_pitch; - float m_yaw; + float m_azimuth; unsigned long long m_timestamp; unsigned int m_interval; + + string m_vendor; + string m_raw_data_unit; + int m_default_sampling_time; + float m_accel_static_bias[3]; + float m_gyro_static_bias[3]; + float m_geomagnetic_static_bias[3]; + int m_accel_rotation_direction_compensation[3]; + int m_gyro_rotation_direction_compensation[3]; + int m_geomagnetic_rotation_direction_compensation[3]; + float m_accel_scale; + float m_gyro_scale; + float m_geomagnetic_scale; + int m_magnetic_alignment_factor; + int m_azimuth_rotation_compensation; + int m_pitch_rotation_compensation; + int m_roll_rotation_compensation; + + bool on_start(void); + bool on_stop(void); }; -#endif /* _ORIENTATION_SENSOR_H_ */ +#endif -- 2.7.4 From b5bdddb579134867678d99e85a32827aee6be836 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 21 Nov 2014 09:39:34 +0530 Subject: [PATCH 05/16] Updating Gravity Virtual Sensor Code - Updating Gravity sensor after testing on SDK - Updating based on latest public code - Updating for new XML based configuration file Change-Id: I2000b0ce9a5a10525d54c3d6977075cd1f70e6d0 --- packaging/sensord.spec | 2 +- src/gravity/gravity_sensor.cpp | 116 ++++++++++++++++++++++++++++------------- src/gravity/gravity_sensor.h | 24 +++++---- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index 78f5b98..bfa8fa4 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -16,7 +16,7 @@ Source2: sensord.socket %define pressure_state OFF %define temperature_state OFF %define orientation_state ON -%define gravity_state OFF +%define gravity_state ON %define linear_accel_state OFF %define build_test_suite OFF diff --git a/src/gravity/gravity_sensor.cpp b/src/gravity/gravity_sensor.cpp index 5d574a0..08b70c5 100755 --- a/src/gravity/gravity_sensor.cpp +++ b/src/gravity/gravity_sensor.cpp @@ -27,31 +27,72 @@ #include #include #include -#include #include #include +#include #define INITIAL_VALUE -1 -#define INITIAL_TIME 0 #define GRAVITY 9.80665 +#define DEG2RAD (M_PI/180) + #define SENSOR_NAME "GRAVITY_SENSOR" +#define SENSOR_TYPE_GRAVITY "GRAVITY" + +#define MS_TO_US 1000 + +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_DEFAULT_SAMPLING_TIME "DEFAULT_SAMPLING_TIME" +#define ELEMENT_GRAVITY_SIGN_COMPENSATION "GRAVITY_SIGN_COMPENSATION" gravity_sensor::gravity_sensor() : m_orientation_sensor(NULL) , m_x(INITIAL_VALUE) , m_y(INITIAL_VALUE) , m_z(INITIAL_VALUE) -, m_timestamp(INITIAL_TIME) { - m_name = string(SENSOR_NAME); + cvirtual_sensor_config &config = cvirtual_sensor_config::get_instance(); + m_name = string(SENSOR_NAME); + m_timestamp = get_timestamp(); register_supported_event(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME); + + if (!config.get(SENSOR_TYPE_GRAVITY, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty\n"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_GRAVITY, ELEMENT_RAW_DATA_UNIT, m_raw_data_unit)) { + ERR("[RAW_DATA_UNIT] is empty\n"); + throw ENXIO; + } + + INFO("m_raw_data_unit = %s", m_raw_data_unit.c_str()); + + if (!config.get(SENSOR_TYPE_GRAVITY, ELEMENT_DEFAULT_SAMPLING_TIME, &m_default_sampling_time)) { + ERR("[DEFAULT_SAMPLING_TIME] is empty\n"); + throw ENXIO; + } + + INFO("m_default_sampling_time = %d", m_default_sampling_time); + + if (!config.get(SENSOR_TYPE_GRAVITY, ELEMENT_GRAVITY_SIGN_COMPENSATION, m_gravity_sign_compensation, 3)) { + ERR("[GRAVITY_SIGN_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_gravity_sign_compensation = (%d, %d, %d)", m_gravity_sign_compensation[0], m_gravity_sign_compensation[1], m_gravity_sign_compensation[2]); + + m_interval = m_default_sampling_time * MS_TO_US; } gravity_sensor::~gravity_sensor() { - INFO("gravity_sensor is destroyed!"); + INFO("gravity_sensor is destroyed!\n"); } bool gravity_sensor::init() @@ -77,6 +118,7 @@ bool gravity_sensor::on_start(void) AUTOLOCK(m_mutex); m_orientation_sensor->add_client(ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME); + m_orientation_sensor->add_interval((int)this, (m_interval/MS_TO_US), true); m_orientation_sensor->start(); activate(); @@ -88,6 +130,7 @@ bool gravity_sensor::on_stop(void) AUTOLOCK(m_mutex); m_orientation_sensor->delete_client(ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME); + m_orientation_sensor->delete_interval((int)this, true); m_orientation_sensor->stop(); deactivate(); @@ -113,24 +156,28 @@ bool gravity_sensor::delete_interval(int client_id) void gravity_sensor::synthesize(const sensor_event_t &event, vector &outs) { sensor_event_t gravity_event; - vector orientation_event; - ((virtual_sensor *)m_orientation_sensor)->synthesize(event, orientation_event); - - if (!orientation_event.empty()) { - AUTOLOCK(m_mutex); - - m_timestamp = orientation_event[0].data.timestamp; - gravity_event.data.values[0] = GRAVITY * sin(orientation_event[0].data.values[1]); - gravity_event.data.values[1] = GRAVITY * sin(orientation_event[0].data.values[0]); - gravity_event.data.values[2] = GRAVITY * cos(orientation_event[0].data.values[1] * - orientation_event[0].data.values[0]); - gravity_event.data.values_num = 3; + + const float MIN_DELIVERY_DIFF_FACTOR = 0.75f; + unsigned long long diff_time; + + if (event.event_type == ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME) { + diff_time = event.data.timestamp - m_timestamp; + + if (m_timestamp && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR)) + return; + + gravity_event.sensor_id = get_id(); + gravity_event.event_type = GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME; + m_timestamp = get_timestamp(); + gravity_event.data.values[0] = m_gravity_sign_compensation[0] * GRAVITY * sin(event.data.values[2] * DEG2RAD); + gravity_event.data.values[1] = m_gravity_sign_compensation[1] * GRAVITY * sin(event.data.values[1] * DEG2RAD); + gravity_event.data.values[2] = m_gravity_sign_compensation[2] * GRAVITY * cos(event.data.values[2] * DEG2RAD) * + cos(event.data.values[1] * DEG2RAD); + gravity_event.data.value_count = 3; gravity_event.data.timestamp = m_timestamp; - gravity_event.data.data_accuracy = SENSOR_ACCURACY_GOOD; - gravity_event.data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; + gravity_event.data.accuracy = SENSOR_ACCURACY_GOOD; - outs.push_back(gravity_event); - return; + push(gravity_event); } } @@ -143,25 +190,24 @@ int gravity_sensor::get_sensor_data(const unsigned int event_type, sensor_data_t m_orientation_sensor->get_sensor_data(ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME, orientation_data); - data.data_accuracy = SENSOR_ACCURACY_GOOD; - data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; - data.timestamp = orientation_data.timestamp; - data.values[0] = GRAVITY * sin(orientation_data.values[1]); - data.values[1] = GRAVITY * sin(orientation_data.values[0]); - data.values[2] = GRAVITY * cos(orientation_data.values[1] * orientation_data.values[0]); - data.values_num = 3; + data.accuracy = SENSOR_ACCURACY_GOOD; + data.timestamp = get_timestamp(); + data.values[0] = m_gravity_sign_compensation[0] * GRAVITY * sin(orientation_data.values[2] * DEG2RAD); + data.values[1] = m_gravity_sign_compensation[1] * GRAVITY * sin(orientation_data.values[1] * DEG2RAD); + data.values[2] = m_gravity_sign_compensation[2] * GRAVITY * cos(orientation_data.values[2] * DEG2RAD) * + cos(orientation_data.values[1] * DEG2RAD); + data.value_count = 3; return 0; } -bool gravity_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +bool gravity_sensor::get_properties(sensor_properties_t &properties) { - properties.sensor_unit_idx = SENSOR_UNIT_DEGREE; - properties.sensor_min_range = -GRAVITY; - properties.sensor_max_range = GRAVITY; - properties.sensor_resolution = 1; - strncpy(properties.sensor_vendor, "Samsung", MAX_KEY_LENGTH); - strncpy(properties.sensor_name, SENSOR_NAME, MAX_KEY_LENGTH); + properties.min_range = -GRAVITY; + properties.max_range = GRAVITY; + properties.resolution = 1; + properties.vendor = m_vendor; + properties.name = SENSOR_NAME; return true; } diff --git a/src/gravity/gravity_sensor.h b/src/gravity/gravity_sensor.h index 33e1eaa..d7aeacb 100755 --- a/src/gravity/gravity_sensor.h +++ b/src/gravity/gravity_sensor.h @@ -20,14 +20,13 @@ #ifndef _GRAVITY_SENSOR_H_ #define _GRAVITY_SENSOR_H_ -#include +#include #include #include using std::string; -class gravity_sensor : public virtual_sensor -{ +class gravity_sensor : public virtual_sensor { public: gravity_sensor(); virtual ~gravity_sensor(); @@ -35,25 +34,30 @@ public: bool init(); sensor_type_t get_type(void); - static bool working(void *inst); - - bool on_start(void); - bool on_stop(void); - void synthesize(const sensor_event_t &event, vector &outs); bool add_interval(int client_id, unsigned int interval); bool delete_interval(int client_id); int get_sensor_data(const unsigned int event_type, sensor_data_t &data); - bool get_properties(const unsigned int type, sensor_properties_t &properties); + bool get_properties(sensor_properties_t &properties); private: sensor_base *m_orientation_sensor; + cmutex m_value_mutex; float m_x; float m_y; float m_z; unsigned long long m_timestamp; + unsigned int m_interval; + + string m_vendor; + string m_raw_data_unit; + int m_default_sampling_time; + int m_gravity_sign_compensation[3]; + + bool on_start(void); + bool on_stop(void); }; -#endif /*_GRAVITY_SENSOR_H_*/ +#endif -- 2.7.4 From c5a3d394f5744ea7f13bde16a3a87cfd09c92952 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 21 Nov 2014 09:54:58 +0530 Subject: [PATCH 06/16] Updating Linear Acceleration Virtual Sensor Code - Updating Linear Acceleration sensor after testing on SDK - Updating based on latest public code - Updating for new XML based configuration file Change-Id: I1981b0ce9a5a10525d54c3d6977075cd1f70e6d0 --- packaging/sensord.spec | 2 +- src/linear_accel/CMakeLists.txt | 1 + src/linear_accel/linear_accel_sensor.cpp | 179 ++++++++++++++++++++++++++----- src/linear_accel/linear_accel_sensor.h | 38 ++++--- 4 files changed, 175 insertions(+), 45 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index bfa8fa4..a76daab 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -17,7 +17,7 @@ Source2: sensord.socket %define temperature_state OFF %define orientation_state ON %define gravity_state ON -%define linear_accel_state OFF +%define linear_accel_state ON %define build_test_suite OFF diff --git a/src/linear_accel/CMakeLists.txt b/src/linear_accel/CMakeLists.txt index b158f2b..6601d90 100755 --- a/src/linear_accel/CMakeLists.txt +++ b/src/linear_accel/CMakeLists.txt @@ -10,6 +10,7 @@ SET(SENSOR_NAME linear_accel_sensor) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) +include_directories(${CMAKE_SOURCE_DIR}/src/sensor_fusion) include(FindPkgConfig) pkg_check_modules(rpkgs REQUIRED vconf) diff --git a/src/linear_accel/linear_accel_sensor.cpp b/src/linear_accel/linear_accel_sensor.cpp index 6967da0..794bef0 100755 --- a/src/linear_accel/linear_accel_sensor.cpp +++ b/src/linear_accel/linear_accel_sensor.cpp @@ -25,33 +25,104 @@ #include #include #include -#include #include #include -#include #include #include +#include #define SENSOR_NAME "LINEAR_ACCEL_SENSOR" +#define SENSOR_TYPE_LINEAR_ACCEL "LINEAR_ACCEL" + +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_DEFAULT_SAMPLING_TIME "DEFAULT_SAMPLING_TIME" +#define ELEMENT_ACCEL_STATIC_BIAS "ACCEL_STATIC_BIAS" +#define ELEMENT_ACCEL_ROTATION_DIRECTION_COMPENSATION "ACCEL_ROTATION_DIRECTION_COMPENSATION" +#define ELEMENT_ACCEL_SCALE "ACCEL_SCALE" +#define ELEMENT_LINEAR_ACCEL_SIGN_COMPENSATION "LINEAR_ACCEL_SIGN_COMPENSATION" #define INITIAL_VALUE -1 -#define INITIAL_TIME 0 #define GRAVITY 9.80665 +#define MS_TO_US 1000 + +#define ACCELEROMETER_ENABLED 0x01 +#define GRAVITY_ENABLED 0x02 +#define LINEAR_ACCEL_ENABLED 3 + linear_accel_sensor::linear_accel_sensor() : m_gravity_sensor(NULL) +, m_accel_sensor(NULL) , m_x(INITIAL_VALUE) , m_y(INITIAL_VALUE) , m_z(INITIAL_VALUE) -, m_time(INITIAL_TIME) { + cvirtual_sensor_config &config = cvirtual_sensor_config::get_instance(); + m_name = string(SENSOR_NAME); + m_timestamp = get_timestamp(); + m_enable_linear_accel = 0; register_supported_event(LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME); + + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty\n"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_RAW_DATA_UNIT, m_raw_data_unit)) { + ERR("[RAW_DATA_UNIT] is empty\n"); + throw ENXIO; + } + + INFO("m_raw_data_unit = %s", m_raw_data_unit.c_str()); + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_DEFAULT_SAMPLING_TIME, &m_default_sampling_time)) { + ERR("[DEFAULT_SAMPLING_TIME] is empty\n"); + throw ENXIO; + } + + INFO("m_default_sampling_time = %d", m_default_sampling_time); + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_ACCEL_STATIC_BIAS, m_accel_static_bias, 3)) { + ERR("[ACCEL_STATIC_BIAS] is empty\n"); + throw ENXIO; + } + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_ACCEL_ROTATION_DIRECTION_COMPENSATION, m_accel_rotation_direction_compensation, 3)) { + ERR("[ACCEL_ROTATION_DIRECTION_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_accel_rotation_direction_compensation = (%d, %d, %d)", m_accel_rotation_direction_compensation[0], m_accel_rotation_direction_compensation[1], m_accel_rotation_direction_compensation[2]); + + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_ACCEL_SCALE, &m_accel_scale)) { + ERR("[ACCEL_SCALE] is empty\n"); + throw ENXIO; + } + + INFO("m_accel_scale = %f", m_accel_scale); + + + if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_LINEAR_ACCEL_SIGN_COMPENSATION, m_linear_accel_sign_compensation, 3)) { + ERR("[LINEAR_ACCEL_SIGN_COMPENSATION] is empty\n"); + throw ENXIO; + } + + INFO("m_linear_accel_sign_compensation = (%d, %d, %d)", m_linear_accel_sign_compensation[0], m_linear_accel_sign_compensation[1], m_linear_accel_sign_compensation[2]); + + m_interval = m_default_sampling_time * MS_TO_US; + } linear_accel_sensor::~linear_accel_sensor() { - INFO("linear_accel_sensor is destroyed!"); + INFO("linear_accel_sensor is destroyed!\n"); } bool linear_accel_sensor::init() @@ -78,7 +149,13 @@ bool linear_accel_sensor::on_start(void) { AUTOLOCK(m_mutex); m_gravity_sensor->add_client(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME); + m_gravity_sensor->add_interval((int)this, (m_interval/MS_TO_US), true); m_gravity_sensor->start(); + + m_accel_sensor->add_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME); + m_accel_sensor->add_interval((int)this, (m_interval/MS_TO_US), true); + m_accel_sensor->start(); + activate(); return true; } @@ -87,7 +164,13 @@ bool linear_accel_sensor::on_stop(void) { AUTOLOCK(m_mutex); m_gravity_sensor->delete_client(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME); + m_gravity_sensor->delete_interval((int)this, true); m_gravity_sensor->stop(); + + m_accel_sensor->delete_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME); + m_accel_sensor->delete_interval((int)this, true); + m_accel_sensor->stop(); + deactivate(); return true; } @@ -96,6 +179,8 @@ bool linear_accel_sensor::add_interval(int client_id, unsigned int interval) { AUTOLOCK(m_mutex); m_gravity_sensor->add_interval(client_id, interval, true); + m_accel_sensor->add_interval((int)this , interval, true); + return sensor_base::add_interval(client_id, interval, true); } @@ -103,27 +188,62 @@ bool linear_accel_sensor::delete_interval(int client_id) { AUTOLOCK(m_mutex); m_gravity_sensor->delete_interval(client_id, true); + m_accel_sensor->delete_interval(client_id, true); + return sensor_base::delete_interval(client_id, true); } void linear_accel_sensor::synthesize(const sensor_event_t &event, vector &outs) { - vector gravity_event; sensor_event_t lin_accel_event; - ((virtual_sensor *)m_gravity_sensor)->synthesize(event, gravity_event); - if (!gravity_event.empty() && event.event_type == ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME) { + const float MIN_DELIVERY_DIFF_FACTOR = 0.75f; + unsigned long long diff_time; + + if (event.event_type == ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME) { + diff_time = event.data.timestamp - m_timestamp; + + if (m_timestamp && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR)) + return; + + m_accel.m_data.m_vec[0] = m_accel_rotation_direction_compensation[0] * (event.data.values[0] - m_accel_static_bias[0]) / m_accel_scale; + m_accel.m_data.m_vec[1] = m_accel_rotation_direction_compensation[1] * (event.data.values[1] - m_accel_static_bias[1]) / m_accel_scale; + m_accel.m_data.m_vec[2] = m_accel_rotation_direction_compensation[2] * (event.data.values[2] - m_accel_static_bias[2]) / m_accel_scale; + + m_accel.m_time_stamp = event.data.timestamp; + + m_enable_linear_accel |= ACCELEROMETER_ENABLED; + } + else if (event.event_type == GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME) { + diff_time = event.data.timestamp - m_timestamp; + + if (m_timestamp && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR)) + return; + + m_gravity.m_data.m_vec[0] = event.data.values[0]; + m_gravity.m_data.m_vec[1] = event.data.values[1]; + m_gravity.m_data.m_vec[2] = event.data.values[2]; + + m_gravity.m_time_stamp = event.data.timestamp; + + m_enable_linear_accel |= GRAVITY_ENABLED; + } + + if (m_enable_linear_accel == LINEAR_ACCEL_ENABLED) { + m_enable_linear_accel = 0; + m_timestamp = get_timestamp(); + AUTOLOCK(m_value_mutex); - lin_accel_event.data.values_num = 3; - lin_accel_event.data.timestamp = gravity_event[0].data.timestamp; + lin_accel_event.sensor_id = get_id(); lin_accel_event.event_type = LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME; - lin_accel_event.data.data_accuracy = SENSOR_ACCURACY_GOOD; - lin_accel_event.data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; - lin_accel_event.data.values[0] = event.data.values[0] - gravity_event[0].data.values[0]; - lin_accel_event.data.values[1] = event.data.values[1] - gravity_event[0].data.values[1]; - lin_accel_event.data.values[2] = event.data.values[2] - gravity_event[0].data.values[2]; - outs.push_back(lin_accel_event); + lin_accel_event.data.value_count = 3; + lin_accel_event.data.timestamp = m_timestamp; + lin_accel_event.data.accuracy = SENSOR_ACCURACY_GOOD; + lin_accel_event.data.values[0] = m_linear_accel_sign_compensation[0] * (m_accel.m_data.m_vec[0] - m_gravity.m_data.m_vec[0]); + lin_accel_event.data.values[1] = m_linear_accel_sign_compensation[1] * (m_accel.m_data.m_vec[1] - m_gravity.m_data.m_vec[1]); + lin_accel_event.data.values[2] = m_linear_accel_sign_compensation[2] * (m_accel.m_data.m_vec[2] - m_gravity.m_data.m_vec[2]); + push(lin_accel_event); } return; @@ -135,27 +255,28 @@ int linear_accel_sensor::get_sensor_data(const unsigned int event_type, sensor_d ((virtual_sensor *)m_gravity_sensor)->get_sensor_data(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME, gravity_data); m_accel_sensor->get_sensor_data(ACCELEROMETER_BASE_DATA_SET, accel_data); + accel_data.values[0] = m_accel_rotation_direction_compensation[0] * (accel_data.values[0] - m_accel_static_bias[0]) / m_accel_scale; + accel_data.values[1] = m_accel_rotation_direction_compensation[1] * (accel_data.values[1] - m_accel_static_bias[1]) / m_accel_scale; + accel_data.values[2] = m_accel_rotation_direction_compensation[2] * (accel_data.values[2] - m_accel_static_bias[2]) / m_accel_scale; + if (event_type != LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME) return -1; - data.data_accuracy = SENSOR_ACCURACY_GOOD; - data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; - data.timestamp = gravity_data.timestamp; - data.values[0] = accel_data.values[0] - gravity_data.values[0]; - data.values[1] = accel_data.values[1] - gravity_data.values[1]; - data.values[2] = accel_data.values[2] - gravity_data.values[2]; - data.values_num = 3; + data.accuracy = SENSOR_ACCURACY_GOOD; + data.timestamp = get_timestamp(); + data.values[0] = m_linear_accel_sign_compensation[0] * (accel_data.values[0] - gravity_data.values[0]); + data.values[1] = m_linear_accel_sign_compensation[1] * (accel_data.values[1] - gravity_data.values[1]); + data.values[2] = m_linear_accel_sign_compensation[2] * (accel_data.values[2] - gravity_data.values[2]); + data.value_count = 3; return 0; } -bool linear_accel_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +bool linear_accel_sensor::get_properties(sensor_properties_t &properties) { - m_gravity_sensor->get_properties(type, properties); - - if (type != LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME) - return true; + m_gravity_sensor->get_properties(properties); + properties.name = "Linear Acceleration Sensor"; + properties.vendor = m_vendor; - strncpy(properties.sensor_name, "Linear Accelerometer Sensor", MAX_KEY_LENGTH); return true; } diff --git a/src/linear_accel/linear_accel_sensor.h b/src/linear_accel/linear_accel_sensor.h index 1616392..273fa84 100755 --- a/src/linear_accel/linear_accel_sensor.h +++ b/src/linear_accel/linear_accel_sensor.h @@ -20,15 +20,11 @@ #ifndef _LINEAR_ACCEL_SENSOR_H_ #define _LINEAR_ACCEL_SENSOR_H_ -#include -#include -#include +#include #include +#include -using std::string; - -class linear_accel_sensor : public virtual_sensor -{ +class linear_accel_sensor : public virtual_sensor { public: linear_accel_sensor(); virtual ~linear_accel_sensor(); @@ -36,27 +32,39 @@ public: bool init(); sensor_type_t get_type(void); - static bool working(void *inst); - - bool on_start(void); - bool on_stop(void); - void synthesize(const sensor_event_t &event, vector &outs); bool add_interval(int client_id, unsigned int interval); bool delete_interval(int client_id); int get_sensor_data(const unsigned int event_type, sensor_data_t &data); - bool get_properties(const unsigned int type, sensor_properties_t &properties); + bool get_properties(sensor_properties_t &properties); private: sensor_base *m_accel_sensor; sensor_base *m_gravity_sensor; cmutex m_value_mutex; + sensor_data m_accel; + sensor_data m_gravity; + float m_x; float m_y; float m_z; - unsigned long long m_time; + unsigned long long m_timestamp; + unsigned int m_interval; + + unsigned int m_enable_linear_accel; + + string m_vendor; + string m_raw_data_unit; + int m_default_sampling_time; + float m_accel_static_bias[3]; + int m_accel_rotation_direction_compensation[3]; + float m_accel_scale; + int m_linear_accel_sign_compensation[3]; + + bool on_start(void); + bool on_stop(void); }; -#endif /*_LINEAR_ACCEL_SENSOR_H_*/ +#endif -- 2.7.4 From fec0e8f54ebe88fb558f51566cdbb893dd2caeec Mon Sep 17 00:00:00 2001 From: Vibhor Gaur Date: Fri, 21 Nov 2014 15:35:04 +0530 Subject: [PATCH 07/16] Synchronizing light sensor plugin with addition of IIO interface support Change-Id: Icd70f7833feef03ce6d9daf7dd4aabf721d5d146 --- packaging/sensord.spec | 3 +- src/light/light_sensor.cpp | 8 +- src/light/light_sensor_hal.cpp | 192 +++++++++++++++++++---------------------- src/light/light_sensor_hal.h | 39 +++++---- 4 files changed, 114 insertions(+), 128 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index eb9d4c2..c7e8946 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -11,7 +11,7 @@ Source2: sensord.socket %define accel_state ON %define gyro_state ON %define proxi_state ON -%define light_state OFF +%define light_state ON %define geo_state ON %define pressure_state OFF %define temperature_state OFF @@ -144,6 +144,7 @@ systemctl daemon-reload /usr/bin/gyro /usr/bin/proxi /usr/bin/pressure + %license LICENSE.APLv2 %{_datadir}/license/test %endif diff --git a/src/light/light_sensor.cpp b/src/light/light_sensor.cpp index 4c8481d..af222e1 100755 --- a/src/light/light_sensor.cpp +++ b/src/light/light_sensor.cpp @@ -159,10 +159,9 @@ bool light_sensor::get_properties(const unsigned int type, sensor_properties_t & return 0; if (type == LIGHT_BASE_DATA_SET) { - properties.sensor_unit_idx = SENSOR_UNIT_LEVEL; - properties.sensor_min_range = 0; - properties.sensor_max_range = sizeof(m_light_level) / sizeof(m_light_level[0]) - 1; - properties.sensor_resolution = 1; + properties.min_range = 0; + properties.max_range = sizeof(m_light_level) / sizeof(m_light_level[0]) - 1; + properties.resolution = 1; return 0; } @@ -198,7 +197,6 @@ bool light_sensor::set_interval(unsigned long interval) void light_sensor::raw_to_level(sensor_data_t &data) { - data.data_unit_idx = SENSOR_UNIT_LEVEL; data.values[0] = (int) adc_to_light_level((int)data.values[0]); data.values_num = 1; } diff --git a/src/light/light_sensor_hal.cpp b/src/light/light_sensor_hal.cpp index b429ffc..6498728 100755 --- a/src/light/light_sensor_hal.cpp +++ b/src/light/light_sensor_hal.cpp @@ -1,5 +1,5 @@ /* - * sensord + * light_sensor_hal * * Copyright (c) 2014 Samsung Electronics Co., Ltd. * @@ -16,65 +16,106 @@ * limitations under the License. * */ - #include #include #include -#include #include + #include #include + #include +#include #include using std::ifstream; using config::csensor_config; -#define BIAS 1 -#define INITIAL_VALUE -1 -#define INITIAL_TIME 0 -#define NO_OF_DATA_VAL 1 - #define SENSOR_TYPE_LIGHT "LIGHT" #define ELEMENT_NAME "NAME" #define ELEMENT_VENDOR "VENDOR" #define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" #define ELEMENT_RESOLUTION "RESOLUTION" #define ATTR_VALUE "value" +#define INITIAL_TIME -1 +#define BIAS 1 +#define INVALID_VALUE -1 +#define INITIAL_VALUE -1 light_sensor_hal::light_sensor_hal() -: m_adc(INITIAL_VALUE) -, m_sensorhub_supported(false) +: m_polling_interval(POLL_1HZ_MS) +, m_adc(INVALID_VALUE) +, m_fired_time(INITIAL_TIME) +, m_node_handle(-1) { - if (!check_hw_node()) - { - ERR("check_hw_node() fail"); + const string sensorhub_interval_node_name = "light_poll_delay"; + csensor_config &config = csensor_config::get_instance(); + + node_path_info_query query; + node_path_info info; + int input_method = IIO_METHOD; + + if (!get_model_properties(SENSOR_TYPE_LIGHT, m_model_id, input_method)) { + ERR("Failed to find model_properties"); throw ENXIO; + } - csensor_config &config = csensor_config::get_instance(); + query.input_method = IIO_METHOD; + query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name); + query.sensor_type = SENSOR_TYPE_LIGHT; + query.input_event_key = "light_sensor"; + query.iio_enable_node_name = "light_enable"; + query.sensorhub_interval_node_name = sensorhub_interval_node_name; - if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_VENDOR, m_vendor)) - { - ERR("[VENDOR] is empty"); + if (!get_node_path_info(query, info)) { + ERR("Failed to get node info"); + throw ENXIO; + } + + show_node_path_info(info); + + m_data_node = info.data_node_path; + m_enable_node = info.enable_node_path; + m_interval_node = info.interval_node_path; + + if(input_method == IIO_METHOD) { + m_light_dir=info.base_dir; + m_light_node = m_light_dir + string(ILL_CLEAR_NODE); + + INFO("m_light_node = %s", m_light_node.c_str()); + INFO("m_light_dir = %s", m_light_dir.c_str()); + } + + if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty\n"); throw ENXIO; } INFO("m_vendor = %s", m_vendor.c_str()); - if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_NAME, m_chip_name)) - { - ERR("[NAME] is empty"); + if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_NAME, m_chip_name)) { + ERR("[NAME] is empty\n"); throw ENXIO; } - INFO("m_chip_name = %s", m_chip_name.c_str()); - INFO("light_sensor_hal is created!"); + INFO("m_chip_name = %s\n",m_chip_name.c_str()); + + if ((m_node_handle = open(m_light_node.c_str(),O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + INFO("light_sensor_hal is created!\n"); + } light_sensor_hal::~light_sensor_hal() { - INFO("light_sensor_hal is destroyed!"); + close(m_node_handle); + m_node_handle = -1; + + INFO("light_sensor_hal is destroyed!\n"); } string light_sensor_hal::get_model_id(void) @@ -82,6 +123,7 @@ string light_sensor_hal::get_model_id(void) return m_model_id; } + sensor_type_t light_sensor_hal::get_type(void) { return LIGHT_SENSOR; @@ -89,26 +131,28 @@ sensor_type_t light_sensor_hal::get_type(void) bool light_sensor_hal::enable(void) { - INFO("Resource already enabled. Enable not supported."); + m_fired_time = INITIAL_TIME; + INFO("Light sensor real starting"); return true; } bool light_sensor_hal::disable(void) { - INFO("Disable not supported."); + INFO("Light sensor real stopping"); return true; } bool light_sensor_hal::set_interval(unsigned long val) { - INFO("Polling not supported. Polling interval cannot be changed."); return true; } -bool light_sensor_hal::update_value(void) + +bool light_sensor_hal::update_value(bool wait) { + unsigned short int adc = INITIAL_VALUE; - if (!read_node_value(m_clear_raw_node, adc)) + if (!read_node_value(m_light_node, adc)) { INFO("Read Value Failed. clear val: %d", adc); return false; @@ -118,99 +162,41 @@ bool light_sensor_hal::update_value(void) m_adc = (int)adc; return true; + } bool light_sensor_hal::is_data_ready(bool wait) { bool ret; - ret = update_value(); + ret = update_value(wait); return ret; } int light_sensor_hal::get_sensor_data(sensor_data_t &data) { AUTOLOCK(m_value_mutex); - data.data_accuracy = SENSOR_ACCURACY_GOOD; - data.data_unit_idx = SENSOR_UNIT_LUX; - data.timestamp = INITIAL_TIME; - data.values_num = NO_OF_DATA_VAL; + data.accuracy = SENSOR_ACCURACY_GOOD; + data.timestamp = m_fired_time ; + data.value_count = 1; data.values[0] = (float) m_adc; return 0; } + bool light_sensor_hal::get_properties(sensor_properties_t &properties) { - properties.sensor_unit_idx = SENSOR_UNIT_LUX; - properties.sensor_min_range = 0; - properties.sensor_max_range = 65536; - snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); - snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); - properties.sensor_resolution = 1.0f; + properties.name = m_chip_name; + properties.vendor = m_vendor; + properties.min_range = 0; + properties.max_range = 65536; + properties.min_interval = 1; + properties.resolution = 1; + properties.fifo_count = 0; + properties.max_batch_count = 0; return true; } -bool light_sensor_hal::is_sensorhub_supported(void) -{ - return false; -} - -bool light_sensor_hal::check_hw_node(void) -{ - string name_node; - string hw_name; - string file_name; - DIR *main_dir = NULL; - struct dirent *dir_entry = NULL; - bool find_node = false; - - INFO("======================start check_hw_node============================="); - - m_sensorhub_supported = is_sensorhub_supported(); - main_dir = opendir(IIO_DIR); - - if (!main_dir) - { - ERR("Directory open failed to collect data"); - return false; - } - - while (!find_node) - { - dir_entry = readdir(main_dir); - if(dir_entry == NULL) - break; - - if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) - { - file_name = string(IIO_DIR) + string(dir_entry->d_name) + string(NAME_NODE); - - ifstream infile(file_name.c_str()); - - if (!infile) - continue; - - infile >> hw_name; - - if (strncmp(dir_entry->d_name, IIO_DEV_BASE_NAME, IIO_DEV_STR_LEN) == 0) - { - if (CConfig::get_instance().is_supported(SENSOR_TYPE_LIGHT, hw_name) == true) - { - m_name = m_model_id = hw_name; - m_clear_raw_node = string(IIO_DIR) + string(dir_entry->d_name) + string(ILL_CLEAR_NODE); - INFO("m_model_id = %s", m_model_id.c_str()); - INFO("m_clear_raw_node = %s", m_clear_raw_node.c_str()); - find_node = true; - break; - } - } - } - } - closedir(main_dir); - - return find_node; -} - extern "C" void *create(void) { light_sensor_hal *inst; @@ -218,14 +204,14 @@ extern "C" void *create(void) try { inst = new light_sensor_hal(); } catch (int err) { - ERR("Failed to create light_sensor_hal class, errno : %d, errstr : %s", err, strerror(err)); + ERR("light_sensor_hal class create fail , errno : %d , errstr : %s\n", err, strerror(err)); return NULL; } - return (void *)inst; + return (void*)inst; } extern "C" void destroy(void *inst) { - delete (light_sensor_hal *)inst; + delete (light_sensor_hal*)inst; } diff --git a/src/light/light_sensor_hal.h b/src/light/light_sensor_hal.h index 30c53f2..ec35104 100755 --- a/src/light/light_sensor_hal.h +++ b/src/light/light_sensor_hal.h @@ -1,5 +1,5 @@ /* - * sensord + * light_sensor_hal * * Copyright (c) 2014 Samsung Electronics Co., Ltd. * @@ -19,17 +19,10 @@ #ifndef _LIGHT_SENSOR_HAL_H_ #define _LIGHT_SENSOR_HAL_H_ - +#define ILL_CLEAR_NODE "in_illuminance_clear_raw" #include #include -#define IIO_DIR "/sys/bus/iio/devices/" -#define NAME_NODE "/name" -#define ILL_CLEAR_NODE "/in_illuminance_clear_raw" - -#define IIO_DEV_BASE_NAME "iio:device" -#define IIO_DEV_STR_LEN 10 - using std::string; class light_sensor_hal : public sensor_hal @@ -45,21 +38,29 @@ public: bool is_data_ready(bool wait); virtual int get_sensor_data(sensor_data_t &data); bool get_properties(sensor_properties_t &properties); - bool check_hw_node(void); - private: - int m_adc; - bool m_sensorhub_supported; - string m_model_id; - string m_name; string m_vendor; string m_chip_name; - cmutex m_value_mutex; + unsigned long m_polling_interval; + + int m_adc; + + unsigned long long m_fired_time; + int m_node_handle; + + string m_enable_node; + string m_data_node; + string m_interval_node; string m_clear_raw_node; + string m_light_dir; + string m_light_node; + + bool m_sensorhub_controlled; + + cmutex m_value_mutex; - bool update_value(void); - bool is_sensorhub_supported(void); + bool update_value(bool wait); }; -#endif /*_LIGHT_SENSOR_HAL_H_*/ +#endif /*_GYRO_SENSOR_HAL_CLASS_H_*/ -- 2.7.4 From 4e843927e279ed03c43a8e4f17baf4a793439b62 Mon Sep 17 00:00:00 2001 From: Amit Dharmapurikar Date: Fri, 21 Nov 2014 18:08:58 +0530 Subject: [PATCH 08/16] Synchronizing pressure sensor plugin with addition of IIO interface support Change-Id: I298a4e11dd2944724988d0fce061f4fee7a3e459 Signed-off-by: Amit Dharmapurikar --- packaging/sensord.spec | 2 +- src/pressure/CMakeLists.txt | 2 +- src/pressure/pressure_sensor.cpp | 50 +++---- src/pressure/pressure_sensor.h | 8 +- src/pressure/pressure_sensor_hal.cpp | 248 ++++++++++++++--------------------- src/pressure/pressure_sensor_hal.h | 35 ++--- 6 files changed, 133 insertions(+), 212 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index eb9d4c2..c9e381a 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -13,7 +13,7 @@ Source2: sensord.socket %define proxi_state ON %define light_state OFF %define geo_state ON -%define pressure_state OFF +%define pressure_state ON %define temperature_state OFF %define orientation_state OFF %define gravity_state OFF diff --git a/src/pressure/CMakeLists.txt b/src/pressure/CMakeLists.txt index b1984d0..ea13698 100755 --- a/src/pressure/CMakeLists.txt +++ b/src/pressure/CMakeLists.txt @@ -15,7 +15,7 @@ include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) include(FindPkgConfig) pkg_check_modules(rpkgs REQUIRED vconf) -add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE -DUSE_LCD_TYPE_CHECK) set(PROJECT_MAJOR_VERSION "0") set(PROJECT_MINOR_VERSION "0") diff --git a/src/pressure/pressure_sensor.cpp b/src/pressure/pressure_sensor.cpp index 35461a7..710c86a 100755 --- a/src/pressure/pressure_sensor.cpp +++ b/src/pressure/pressure_sensor.cpp @@ -29,17 +29,15 @@ using config::csensor_config; using std::bind1st; using std::mem_fun; -#define SENSOR_NAME "PRESSURE_SENSOR" -#define SENSOR_TYPE_PRESSURE "PRESSURE" +#define SENSOR_NAME "PRESSURE_SENSOR" +#define SENSOR_TYPE_PRESSURE "PRESSURE" #define ELEMENT_NAME "NAME" #define ELEMENT_VENDOR "VENDOR" #define ELEMENT_TEMPERATURE_RESOLUTION "TEMPERATURE_RESOLUTION" #define ELEMENT_TEMPERATURE_OFFSET "TEMPERATURE_OFFSET" #define ATTR_VALUE "value" -#define SEA_LEVEL_RESOLUTION 0.01 -#define ALT_CONST1 44330.0 -#define ALT_CONST2 (1.0f/5.255f) +#define SEA_LEVEL_RESOLUTION 0.01 pressure_sensor::pressure_sensor() : m_sensor_hal(NULL) @@ -61,21 +59,19 @@ bool pressure_sensor::init() { m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(PRESSURE_SENSOR); - if (!m_sensor_hal) - { + if (!m_sensor_hal) { ERR("cannot load sensor_hal[%s]", sensor_base::get_name()); return false; } sensor_properties_t properties; - if (m_sensor_hal->get_properties(properties) == false) - { + if (!m_sensor_hal->get_properties(properties)) { ERR("sensor->get_properties() is failed!\n"); return false; } - m_resolution = properties.sensor_resolution; + m_resolution = properties.resolution; string model_id = m_sensor_hal->get_model_id(); @@ -83,8 +79,7 @@ bool pressure_sensor::init() double temperature_resolution; - if (!config.get(SENSOR_TYPE_PRESSURE, model_id, ELEMENT_TEMPERATURE_RESOLUTION, temperature_resolution)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, model_id, ELEMENT_TEMPERATURE_RESOLUTION, temperature_resolution)) { ERR("[TEMPERATURE_RESOLUTION] is empty\n"); throw ENXIO; } @@ -94,8 +89,7 @@ bool pressure_sensor::init() double temperature_offset; - if (!config.get(SENSOR_TYPE_PRESSURE, model_id, ELEMENT_TEMPERATURE_OFFSET, temperature_offset)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, model_id, ELEMENT_TEMPERATURE_OFFSET, temperature_offset)) { ERR("[TEMPERATURE_OFFSET] is empty\n"); throw ENXIO; } @@ -122,7 +116,6 @@ bool pressure_sensor::working(void *inst) bool pressure_sensor::process_event(void) { sensor_event_t event; - int pressure; if (!m_sensor_hal->is_data_ready(true)) return true; @@ -131,8 +124,8 @@ bool pressure_sensor::process_event(void) AUTOLOCK(m_client_info_mutex); - if (get_client_cnt(PRESSURE_EVENT_RAW_DATA_REPORT_ON_TIME)) - { + if (get_client_cnt(PRESSURE_EVENT_RAW_DATA_REPORT_ON_TIME)) { + event.sensor_id = get_id(); event.event_type = PRESSURE_EVENT_RAW_DATA_REPORT_ON_TIME; raw_to_base(event.data); push(event); @@ -143,8 +136,7 @@ bool pressure_sensor::process_event(void) bool pressure_sensor::on_start(void) { - if (!m_sensor_hal->enable()) - { + if (!m_sensor_hal->enable()) { ERR("m_sensor_hal start fail\n"); return false; } @@ -154,8 +146,7 @@ bool pressure_sensor::on_start(void) bool pressure_sensor::on_stop(void) { - if (!m_sensor_hal->disable()) - { + if (!m_sensor_hal->disable()) { ERR("m_sensor_hal stop fail\n"); return false; } @@ -163,12 +154,12 @@ bool pressure_sensor::on_stop(void) return stop_poll(); } -bool pressure_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +bool pressure_sensor::get_properties(sensor_properties_t &properties) { return m_sensor_hal->get_properties(properties); } -int pressure_sensor::get_sensor_data(const unsigned int type, sensor_data_t &data) +int pressure_sensor::get_sensor_data(unsigned int type, sensor_data_t &data) { int ret; @@ -177,8 +168,7 @@ int pressure_sensor::get_sensor_data(const unsigned int type, sensor_data_t &dat if (ret < 0) return -1; - if (type == PRESSURE_BASE_DATA_SET) - { + if (type == PRESSURE_BASE_DATA_SET) { raw_to_base(data); return 0; } @@ -197,25 +187,23 @@ bool pressure_sensor::set_interval(unsigned long interval) float pressure_sensor::pressure_to_altitude(float pressure) { - return ALT_CONST1 * (1.0f - pow(pressure/m_sea_level_pressure, ALT_CONST2)); + return 44330.0f * (1.0f - pow(pressure/m_sea_level_pressure, 1.0f/5.255f)); } void pressure_sensor::raw_to_base(sensor_data_t &data) { m_sea_level_pressure = data.values[1] * SEA_LEVEL_RESOLUTION; data.values[1] = pressure_to_altitude(data.values[0]); + data.value_count = 3; } extern "C" void *create(void) { pressure_sensor *inst; - try - { + try { inst = new pressure_sensor(); - } - catch (int err) - { + } catch (int err) { ERR("pressure_sensor class create fail , errno : %d , errstr : %s\n", err, strerror(err)); return NULL; } diff --git a/src/pressure/pressure_sensor.h b/src/pressure/pressure_sensor.h index 2124f6c..1da5cab 100755 --- a/src/pressure/pressure_sensor.h +++ b/src/pressure/pressure_sensor.h @@ -25,8 +25,7 @@ #include #include -class pressure_sensor : public physical_sensor -{ +class pressure_sensor : public physical_sensor { public: pressure_sensor(); virtual ~pressure_sensor(); @@ -37,8 +36,8 @@ public: static bool working(void *inst); bool set_interval(unsigned long interval); - bool get_properties(const unsigned int type, sensor_properties_t &properties); - int get_sensor_data(const unsigned int type, sensor_data_t &data); + virtual bool get_properties(sensor_properties_t &properties); + int get_sensor_data(unsigned int type, sensor_data_t &data); private: sensor_hal *m_sensor_hal; @@ -53,6 +52,7 @@ private: bool process_event(void); float pressure_to_altitude(float pressure); void raw_to_base(sensor_data_t &data); + }; #endif diff --git a/src/pressure/pressure_sensor_hal.cpp b/src/pressure/pressure_sensor_hal.cpp index 764adc9..2823baa 100755 --- a/src/pressure/pressure_sensor_hal.cpp +++ b/src/pressure/pressure_sensor_hal.cpp @@ -21,55 +21,87 @@ #include #include #include -#include #include +#include #include +#include #include using std::ifstream; +using std::string; using config::csensor_config; #define SENSOR_TYPE_PRESSURE "PRESSURE" #define ELEMENT_NAME "NAME" #define ELEMENT_VENDOR "VENDOR" #define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_RESOLUTION "RESOLUTION" #define ELEMENT_MIN_RANGE "MIN_RANGE" #define ELEMENT_MAX_RANGE "MAX_RANGE" +#define ELEMENT_TEMPERATURE_RESOLUTION "TEMPERATURE_RESOLUTION" +#define ELEMENT_TEMPERATURE_OFFSET "TEMPERATURE_OFFSET" +#define ATTR_VALUE "value" + +#define SEA_LEVEL_PRESSURE 101325.0 -#define ENABLE_VAL true -#define DISABLE_VAL false -#define SEA_LEVEL_PRESSURE 101325.0 -#define NO_FLAG 0 -#define TIMEOUT 1 +#define EVENT_EN_NODE "events/in_pressure_mag_either_en" +#define PRESSURE_SCALE "/in_pressure_scale" +#define PRESSURE_RAW "/in_pressure_raw" +#define TEMP_OFFSET "/in_temp_offset" +#define TEMP_SCALE "/in_temp_scale" +#define TEMP_RAW "/in_temp_raw" +#define NO_FLAG 0 +#define TIMEOUT 1 pressure_sensor_hal::pressure_sensor_hal() : m_pressure(0) , m_temperature(0) , m_polling_interval(POLL_1HZ_MS) , m_fired_time(0) -, m_sensorhub_supported(false) +, m_node_handle(-1) { - int fd, ret; - string file_name; + const string sensorhub_interval_node_name = "pressure_poll_delay"; + csensor_config &config = csensor_config::get_instance(); - if (!check_hw_node()) - { - ERR("check_hw_node() fail"); + node_path_info_query query; + node_path_info info; + int input_method = IIO_METHOD; + + if (!get_model_properties(SENSOR_TYPE_PRESSURE, m_model_id, input_method)) { + ERR("Failed to find model_properties"); throw ENXIO; + } - csensor_config &config = csensor_config::get_instance(); + query.input_method = input_method; + query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name); + query.sensor_type = SENSOR_TYPE_PRESSURE; + query.input_event_key = "pressure_sensor"; + query.iio_enable_node_name = EVENT_EN_NODE; + query.sensorhub_interval_node_name = sensorhub_interval_node_name; + + if (!get_node_path_info(query, info)) { + ERR("Failed to get node info"); + throw ENXIO; + } + m_data_node = info.data_node_path; + m_pressure_dir = info.base_dir; + m_enable_node = info.enable_node_path; + m_pressure_node = m_pressure_dir + string(PRESSURE_RAW); + m_temp_node = m_pressure_dir + string(TEMP_RAW); + + INFO("m_data_node:%s",m_data_node.c_str()); + INFO("m_pressure_dir:%s",m_pressure_dir.c_str()); + INFO("m_enable_node:%s",m_enable_node.c_str()); - if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_VENDOR, m_vendor)) { ERR("[VENDOR] is empty\n"); throw ENXIO; } INFO("m_vendor = %s", m_vendor.c_str()); - if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_NAME, m_chip_name)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_NAME, m_chip_name)) { ERR("[NAME] is empty\n"); throw ENXIO; } @@ -78,8 +110,7 @@ pressure_sensor_hal::pressure_sensor_hal() double min_range; - if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MIN_RANGE, min_range)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MIN_RANGE, min_range)) { ERR("[MIN_RANGE] is empty\n"); throw ENXIO; } @@ -89,8 +120,7 @@ pressure_sensor_hal::pressure_sensor_hal() double max_range; - if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MAX_RANGE, max_range)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_MAX_RANGE, max_range)) { ERR("[MAX_RANGE] is empty\n"); throw ENXIO; } @@ -100,8 +130,7 @@ pressure_sensor_hal::pressure_sensor_hal() double raw_data_unit; - if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) - { + if (!config.get(SENSOR_TYPE_PRESSURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) { ERR("[RAW_DATA_UNIT] is empty\n"); throw ENXIO; } @@ -109,15 +138,17 @@ pressure_sensor_hal::pressure_sensor_hal() m_raw_data_unit = (float)(raw_data_unit); INFO("m_raw_data_unit = %f\n", m_raw_data_unit); - file_name = string(IIO_DIR) + m_pressure_dir + string(TEMP_SCALE); + string file_name; + + file_name = m_pressure_dir + string(TEMP_SCALE); if (!read_node_value(file_name, m_temp_scale)) throw ENXIO; - file_name = string(IIO_DIR) + m_pressure_dir + string(TEMP_OFFSET); + file_name = m_pressure_dir + string(TEMP_OFFSET); if (!read_node_value(file_name, m_temp_offset)) throw ENXIO; - file_name = string(IIO_DIR) + m_pressure_dir + string(PRESSURE_SCALE); + file_name = m_pressure_dir + string(PRESSURE_SCALE); if (!read_node_value(file_name, m_pressure_scale)) throw ENXIO; @@ -125,20 +156,19 @@ pressure_sensor_hal::pressure_sensor_hal() INFO("Temperature offset:%f", m_temp_offset); INFO("Pressure scale:%d", m_pressure_scale); - fd = open(m_event_resource.c_str(), NO_FLAG); - if (fd == -1) - { + int fd, ret; + fd = open(m_data_node.c_str(), NO_FLAG); + if (fd == -1) { ERR("Could not open event resource"); throw ENXIO; } - ret = ioctl(fd, IOCTL_IIO_EVENT_FD, &m_event_fd); + ret = ioctl(fd, IOCTL_IIO_EVENT_FD, &m_node_handle); close(fd); - if ((ret == -1) || (m_event_fd == -1)) - { - ERR("Failed to retrieve event fd"); + if ((ret == -1) || (m_node_handle == -1)) { + ERR("Failed to retrieve node handle from event node: %s", m_data_node.c_str()); throw ENXIO; } @@ -147,7 +177,9 @@ pressure_sensor_hal::pressure_sensor_hal() pressure_sensor_hal::~pressure_sensor_hal() { - close(m_event_fd); + close(m_node_handle); + m_node_handle = -1; + INFO("pressure_sensor_hal is destroyed!\n"); } @@ -161,17 +193,11 @@ sensor_type_t pressure_sensor_hal::get_type(void) return PRESSURE_SENSOR; } -bool pressure_sensor_hal::enable_resource(bool enable) -{ - update_sysfs_num(m_enable_resource.c_str(), enable); - return true; -} - bool pressure_sensor_hal::enable(void) { AUTOLOCK(m_mutex); - - enable_resource(ENABLE_VAL); + update_sysfs_num(m_enable_node.c_str(), true); + set_interval(m_polling_interval); m_fired_time = 0; INFO("Pressure sensor real starting"); @@ -182,7 +208,7 @@ bool pressure_sensor_hal::disable(void) { AUTOLOCK(m_mutex); - enable_resource(DISABLE_VAL); + update_sysfs_num(m_enable_node.c_str(), false); INFO("Pressure sensor real stopping"); return true; @@ -190,6 +216,7 @@ bool pressure_sensor_hal::disable(void) bool pressure_sensor_hal::set_interval(unsigned long val) { + INFO("set_interval not supported"); return true; } @@ -204,47 +231,40 @@ bool pressure_sensor_hal::update_value(bool wait) FD_ZERO(&readfds); FD_ZERO(&exceptfds); - FD_SET(m_event_fd, &readfds); - FD_SET(m_event_fd, &exceptfds); + FD_SET(m_node_handle, &readfds); + FD_SET(m_node_handle, &exceptfds); - if (wait) - { + if (wait) { tv.tv_sec = TIMEOUT; tv.tv_usec = 0; } - else - { + else { tv.tv_sec = 0; tv.tv_usec = 0; } - ret = select(m_event_fd + 1, &readfds, NULL, &exceptfds, &tv); + ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, &tv); - if (ret == -1) - { - ERR("select error:%s m_event_fd:d", strerror(errno), m_event_fd); + if (ret == -1) { + ERR("select error:%s m_node_handle:d", strerror(errno), m_node_handle); return false; } - else if (!ret) - { + else if (!ret) { DBG("select timeout"); return false; } - if (FD_ISSET(m_event_fd, &exceptfds)) - { + if (FD_ISSET(m_node_handle, &exceptfds)) { ERR("select exception occurred!"); return false; } - if (FD_ISSET(m_event_fd, &readfds)) - { + if (FD_ISSET(m_node_handle, &readfds)) { INFO("pressure event detection!"); - int len = read(m_event_fd, &pressure_event, sizeof(pressure_event)); + int len = read(m_node_handle, &pressure_event, sizeof(pressure_event)); - if (len == -1) - { - DBG("Error in read(m_event_fd):%s.", strerror(errno)); + if (len == -1) { + ERR("Error in read(m_event_fd):%s.", strerror(errno)); return false; } m_fired_time = pressure_event.timestamp; @@ -255,12 +275,12 @@ bool pressure_sensor_hal::update_value(bool wait) m_pressure = ((float)raw_pressure_count)/((float)m_pressure_scale); m_temperature = m_temp_offset + ((float)raw_temp_count)/((float)m_temp_scale); } - else - { + else { ERR("No pressure event data available to read"); return false; } return true; + } bool pressure_sensor_hal::is_data_ready(bool wait) @@ -273,10 +293,9 @@ bool pressure_sensor_hal::is_data_ready(bool wait) int pressure_sensor_hal::get_sensor_data(sensor_data_t &data) { AUTOLOCK(m_value_mutex); - data.data_accuracy = SENSOR_ACCURACY_GOOD; - data.data_unit_idx = SENSOR_UNIT_HECTOPASCAL; + data.accuracy = SENSOR_ACCURACY_GOOD; data.timestamp = m_fired_time ; - data.values_num = 3; + data.value_count = 3; data.values[0] = m_pressure; data.values[1] = SEA_LEVEL_PRESSURE; data.values[2] = m_temperature; @@ -284,98 +303,27 @@ int pressure_sensor_hal::get_sensor_data(sensor_data_t &data) return 0; } + bool pressure_sensor_hal::get_properties(sensor_properties_t &properties) { - properties.sensor_unit_idx = SENSOR_UNIT_HECTOPASCAL; - properties.sensor_min_range = m_min_range; - properties.sensor_max_range = m_max_range; - snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); - snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); - properties.sensor_resolution = m_raw_data_unit; + properties.name = m_chip_name; + properties.vendor = m_vendor; + properties.min_range = m_min_range; + properties.max_range = m_max_range; + properties.min_interval = 1; + properties.resolution = m_raw_data_unit; + properties.fifo_count = 0; + properties.max_batch_count = 0; return true; } -bool pressure_sensor_hal::is_sensorhub_supported(void) -{ - return false; -} - -bool pressure_sensor_hal::check_hw_node(void) -{ - string name_node; - string hw_name; - string file_name; - - DIR *main_dir = NULL; - struct dirent *dir_entry = NULL; - bool find_node = false; - - INFO("======================start check_hw_node=============================\n"); - - m_sensorhub_supported = is_sensorhub_supported(); - - main_dir = opendir(IIO_DIR); - - if (!main_dir) - { - ERR("Could not open IIO directory\n"); - return false; - } - - while (!find_node) - { - dir_entry = readdir(main_dir); - if(dir_entry == NULL) - break; - - if ((strncasecmp(dir_entry->d_name ,".",1 ) != 0) && (strncasecmp(dir_entry->d_name ,"..",2 ) != 0) && (dir_entry->d_ino != 0)) - { - file_name = string(IIO_DIR) + string(dir_entry->d_name) + string(NAME_NODE); - - ifstream infile(file_name.c_str()); - - if (!infile) - continue; - - infile >> hw_name; - - if (strncmp(dir_entry->d_name, IIO_DEV_BASE_NAME, IIO_DEV_STR_LEN) == 0) - { - if (CConfig::get_instance().is_supported(SENSOR_TYPE_PRESSURE, hw_name) == true) - { - m_name = m_model_id = hw_name; - m_pressure_dir = string(dir_entry->d_name); - m_enable_resource = string(IIO_DIR) + m_pressure_dir + string(EVENT_DIR) + string(EVENT_EN_NODE); - m_event_resource = string(DEV_DIR) + m_pressure_dir; - m_pressure_node = string(IIO_DIR) + m_pressure_dir + string(PRESSURE_RAW); - m_temp_node = string(IIO_DIR) + m_pressure_dir + string(TEMP_RAW); - - INFO("m_enable_resource = %s", m_enable_resource.c_str()); - INFO("m_model_id = %s", m_model_id.c_str()); - INFO("m_pressure_dir = %s", m_pressure_dir.c_str()); - INFO("m_event_resource = %s", m_event_resource.c_str()); - - find_node = true; - break; - } - } - } - } - - closedir(main_dir); - return find_node; -} - extern "C" void *create(void) { pressure_sensor_hal *inst; - try - { + try { inst = new pressure_sensor_hal(); - } - catch (int err) - { + } catch (int err) { ERR("pressure_sensor_hal class create fail , errno : %d , errstr : %s\n", err, strerror(err)); return NULL; } diff --git a/src/pressure/pressure_sensor_hal.h b/src/pressure/pressure_sensor_hal.h index 96fc362..42e5310 100755 --- a/src/pressure/pressure_sensor_hal.h +++ b/src/pressure/pressure_sensor_hal.h @@ -23,20 +23,6 @@ #include #include -#define IIO_DIR "/sys/bus/iio/devices/" -#define NAME_NODE "/name" -#define EVENT_DIR "/events" -#define EVENT_EN_NODE "/in_pressure_mag_either_en" -#define DEV_DIR "/dev/" -#define PRESSURE_SCALE "/in_pressure_scale" -#define PRESSURE_RAW "/in_pressure_raw" -#define TEMP_OFFSET "/in_temp_offset" -#define TEMP_SCALE "/in_temp_scale" -#define TEMP_RAW "/in_temp_raw" - -#define IIO_DEV_BASE_NAME "iio:device" -#define IIO_DEV_STR_LEN 10 - using std::string; class pressure_sensor_hal : public sensor_hal @@ -46,17 +32,15 @@ public: virtual ~pressure_sensor_hal(); string get_model_id(void); sensor_type_t get_type(void); - bool enable(void); bool disable(void); bool set_interval(unsigned long val); bool is_data_ready(bool wait); virtual int get_sensor_data(sensor_data_t &data); - bool get_properties(sensor_properties_t &properties); + virtual bool get_properties(sensor_properties_t &properties); private: string m_model_id; - string m_name; string m_vendor; string m_chip_name; @@ -67,6 +51,8 @@ private: float m_temp_offset; float m_temperature; + int m_resolution; + float m_min_range; float m_max_range; float m_raw_data_unit; @@ -74,21 +60,20 @@ private: unsigned long m_polling_interval; unsigned long long m_fired_time; - int m_event_fd; + int m_node_handle; + + string m_enable_node; + string m_data_node; + string m_interval_node; string m_pressure_dir; string m_pressure_node; string m_temp_node; - string m_event_resource; - string m_enable_resource; - cmutex m_value_mutex; + bool m_sensorhub_controlled; - bool m_sensorhub_supported; + cmutex m_value_mutex; - bool check_hw_node(void); bool update_value(bool wait); - bool enable_resource(bool enable); - bool is_sensorhub_supported(void); }; #endif /*_PRESSURE_SENSOR_HAL_CLASS_H_*/ -- 2.7.4 From 312b2adf6397cceec85052438939bd9742794d46 Mon Sep 17 00:00:00 2001 From: Vibhor Gaur Date: Mon, 24 Nov 2014 11:54:00 +0530 Subject: [PATCH 09/16] Synchronizing temperature sensor plugin with addition of IIO interface support Change-Id: I8e10ad057ac667cf7576560875cb2572a9efb7df --- packaging/sensord.spec | 2 +- src/temperature/temperature_sensor.cpp | 2 +- src/temperature/temperature_sensor_hal.cpp | 202 +++++++++++++---------------- src/temperature/temperature_sensor_hal.h | 24 ++-- 4 files changed, 101 insertions(+), 129 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index 74e9594..f5aefe8 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -14,7 +14,7 @@ Source2: sensord.socket %define light_state ON %define geo_state ON %define pressure_state ON -%define temperature_state OFF +%define temperature_state ON %define orientation_state ON %define gravity_state ON %define linear_accel_state ON diff --git a/src/temperature/temperature_sensor.cpp b/src/temperature/temperature_sensor.cpp index 4e0d66a..944d3c5 100755 --- a/src/temperature/temperature_sensor.cpp +++ b/src/temperature/temperature_sensor.cpp @@ -59,7 +59,7 @@ bool temperature_sensor::init() return false; } - m_resolution = properties.sensor_resolution; + m_resolution = properties.resolution; INFO("%s is created!", sensor_base::get_name()); diff --git a/src/temperature/temperature_sensor_hal.cpp b/src/temperature/temperature_sensor_hal.cpp index 9d81381..350d530 100755 --- a/src/temperature/temperature_sensor_hal.cpp +++ b/src/temperature/temperature_sensor_hal.cpp @@ -21,10 +21,12 @@ #include #include #include -#include #include +#include +#include #include + using std::ifstream; using config::csensor_config; @@ -33,71 +35,104 @@ using config::csensor_config; #define ELEMENT_VENDOR "VENDOR" #define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" -#define ENABLE_VAL true -#define DISABLE_VAL false -#define NO_FLAG 0 -#define TIMEOUT 1 -#define INITIAL_TIME 0 -#define NO_OF_DATA_VAL 1 +#define TEMP_INPUT_NAME "temperature_sensor" +#define TEMP_IIO_ENABLE_NODE_NAME "temp_enable" +#define TEMP_SENSORHUB_POLL_NODE_NAME "temp_poll_delay" +#define INITIAL_TIME -1 temperature_sensor_hal::temperature_sensor_hal() : m_temperature(0) -, m_sensorhub_supported(false) +, m_node_handle(-1) +, m_polling_interval(POLL_1HZ_MS) +, m_fired_time(INITIAL_TIME) { - int fd, ret; + const string sensorhub_interval_node_name = TEMP_SENSORHUB_POLL_NODE_NAME; string file_name; + node_path_info_query query; + node_path_info info; + int input_method = IIO_METHOD; + + if (!get_model_properties(SENSOR_TYPE_TEMPERATURE, m_model_id, input_method)) { + ERR("Failed to find model_properties"); + throw ENXIO; + } - if (!check_hw_node()) - { - ERR("check_hw_node() fail"); + query.input_method = input_method; + query.sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name); + query.sensor_type = SENSOR_TYPE_TEMPERATURE; + query.input_event_key = TEMP_INPUT_NAME; + query.iio_enable_node_name = TEMP_IIO_ENABLE_NODE_NAME; + query.sensorhub_interval_node_name = sensorhub_interval_node_name; + + if (!get_node_path_info(query, info)) { + ERR("Failed to get node info"); throw ENXIO; } + show_node_path_info(info); + + m_data_node = info.data_node_path; + m_enable_node = info.enable_node_path; + m_interval_node = info.interval_node_path; + + if(input_method == IIO_METHOD) { + m_temperature_dir=info.base_dir; + m_temp_node = m_temperature_dir + string(TEMP_RAW); + INFO("m_temperature_dir = %s", m_temperature_dir.c_str()); + INFO("m_temp_node = %s", m_temp_node.c_str()); + } csensor_config &config = csensor_config::get_instance(); - if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_VENDOR, m_vendor)) - { + if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_VENDOR, m_vendor)) { ERR("[VENDOR] is empty\n"); throw ENXIO; } - INFO("m_vendor = %s", m_vendor.c_str()); - - if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_NAME, m_chip_name)) - { + if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_NAME, m_chip_name)) { ERR("[NAME] is empty\n"); throw ENXIO; } - INFO("m_chip_name = %s", m_chip_name.c_str()); - double raw_data_unit; - if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) - { + if (!config.get(SENSOR_TYPE_TEMPERATURE, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) { ERR("[RAW_DATA_UNIT] is empty\n"); throw ENXIO; } m_raw_data_unit = (float)(raw_data_unit); + + INFO("m_data_node = %s\n",m_data_node.c_str()); + + if ((m_node_handle = open(m_temp_node.c_str(),O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + INFO("m_data_node = %s\n",m_data_node.c_str()); INFO("m_raw_data_unit = %f\n", m_raw_data_unit); - file_name = string(IIO_DIR) + m_temperature_dir + string(TEMP_SCALE); + file_name = m_temperature_dir + string(TEMP_SCALE); if (!read_node_value(file_name, m_temp_scale)) throw ENXIO; - file_name = string(IIO_DIR) + m_temperature_dir + string(TEMP_OFFSET); + file_name = m_temperature_dir + string(TEMP_OFFSET); if (!read_node_value(file_name, m_temp_offset)) throw ENXIO; - INFO("Temperature scale:%d", m_temp_scale); - INFO("Temperature offset:%f", m_temp_offset); - + INFO("m_temp_offset %f",m_temp_offset); + INFO("m_temp_scale %d",m_temp_scale); + INFO("m_vendor = %s", m_vendor.c_str()); + INFO("m_chip_name = %s", m_chip_name.c_str()); + INFO("m_raw_data_unit = %f\n", m_raw_data_unit); INFO("temperature_sensor_hal is created!\n"); } temperature_sensor_hal::~temperature_sensor_hal() { + close(m_node_handle); + m_node_handle = -1; + INFO("temperature_sensor_hal is destroyed!\n"); } @@ -111,27 +146,23 @@ sensor_type_t temperature_sensor_hal::get_type(void) return TEMPERATURE_SENSOR; } -bool temperature_sensor_hal::enable_resource(bool enable) -{ - INFO("Enable not supported"); - return true; -} - bool temperature_sensor_hal::enable(void) { - enable_resource(ENABLE_VAL); + m_fired_time = INITIAL_TIME; + INFO("Temperature sensor real starting"); return true; } bool temperature_sensor_hal::disable(void) { - enable_resource(DISABLE_VAL); + INFO("Temperature sensor real stopping"); return true; } bool temperature_sensor_hal::set_interval(unsigned long val) { return true; + } bool temperature_sensor_hal::update_value(bool wait) @@ -141,6 +172,10 @@ bool temperature_sensor_hal::update_value(bool wait) if (!read_node_value(m_temp_node, raw_temp_count)) return false; m_temperature = m_temp_offset + ((float)raw_temp_count)/((float)m_temp_scale); + INFO("m_temperature %f",m_temperature); + INFO("m_temp_offset %f",m_temp_offset); + INFO("raw_temp_count %d",raw_temp_count); + INFO("m_temp_scale %d",m_temp_scale); return true; } @@ -154,99 +189,36 @@ bool temperature_sensor_hal::is_data_ready(bool wait) int temperature_sensor_hal::get_sensor_data(sensor_data_t &data) { AUTOLOCK(m_value_mutex); - data.data_accuracy = SENSOR_ACCURACY_GOOD; - data.data_unit_idx = SENSOR_UNIT_CELSIUS; - data.timestamp = INITIAL_TIME; - data.values_num = NO_OF_DATA_VAL; - data.values[0] = m_temperature; - return 0; -} + data.accuracy = SENSOR_ACCURACY_GOOD; + data.timestamp = m_fired_time ; + data.value_count = 1; + data.values[0] = (float) m_temperature; -bool temperature_sensor_hal::get_properties(sensor_properties_t &properties) -{ - properties.sensor_unit_idx = SENSOR_UNIT_CELSIUS; - snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); - snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); - properties.sensor_resolution = m_raw_data_unit; - return true; + return 0; } -bool temperature_sensor_hal::is_sensorhub_supported(void) -{ - return false; -} -bool temperature_sensor_hal::check_hw_node(void) +bool temperature_sensor_hal::get_properties(sensor_properties_t &properties) { - string name_node; - string hw_name; - string file_name; - - DIR *main_dir = NULL; - struct dirent *dir_entry = NULL; - bool find_node = false; - - INFO("======================start check_hw_node=============================\n"); - - m_sensorhub_supported = is_sensorhub_supported(); - - main_dir = opendir(IIO_DIR); + properties.name = m_chip_name; + properties.vendor = m_vendor; + properties.min_range = -45; + properties.max_range = 130; + properties.min_interval = 1; + properties.resolution = 1; + properties.fifo_count = 0; + properties.max_batch_count = 0; - if (!main_dir) - { - ERR("Could not open IIO directory\n"); - return false; - } - - while (!find_node) - { - dir_entry = readdir(main_dir); - if(dir_entry == NULL) - break; - - if ((strncasecmp(dir_entry->d_name ,".",1 ) != 0) && (strncasecmp(dir_entry->d_name ,"..",2 ) != 0) && (dir_entry->d_ino != 0)) - { - file_name = string(IIO_DIR) + string(dir_entry->d_name) + string(NAME_NODE); - - ifstream infile(file_name.c_str()); - - if (!infile) - continue; - - infile >> hw_name; - - if (strncmp(dir_entry->d_name, IIO_DEV_BASE_NAME, IIO_DEV_STR_LEN) == 0) - { - if (CConfig::get_instance().is_supported(SENSOR_TYPE_TEMPERATURE, hw_name) == true) - { - m_model_id = hw_name; - m_temperature_dir = string(dir_entry->d_name); - m_temp_node = string(IIO_DIR) + m_temperature_dir + string(TEMP_RAW); - - INFO("m_model_id = %s", m_model_id.c_str()); - INFO("m_temperature_dir = %s", m_temperature_dir.c_str()); - - find_node = true; - break; - } - } - } - } - - closedir(main_dir); - return find_node; + return true; } extern "C" void *create(void) { temperature_sensor_hal *inst; - try - { + try { inst = new temperature_sensor_hal(); - } - catch (int err) - { + } catch (int err) { ERR("temperature_sensor_hal class create fail , errno : %d , errstr : %s\n", err, strerror(err)); return NULL; } diff --git a/src/temperature/temperature_sensor_hal.h b/src/temperature/temperature_sensor_hal.h index 7c86c49..f492ee4 100755 --- a/src/temperature/temperature_sensor_hal.h +++ b/src/temperature/temperature_sensor_hal.h @@ -22,15 +22,13 @@ #include #include - - #define IIO_DIR "/sys/bus/iio/devices/" #define IIO_DEV_BASE_NAME "iio:device" #define IIO_DEV_STR_LEN 10 #define NAME_NODE "/name" -#define TEMP_OFFSET "/in_temp_offset" -#define TEMP_SCALE "/in_temp_scale" -#define TEMP_RAW "/in_temp_raw" +#define TEMP_OFFSET "in_temp_offset" +#define TEMP_SCALE "in_temp_scale" +#define TEMP_RAW "in_temp_raw" using std::string; @@ -47,9 +45,11 @@ public: bool is_data_ready(bool wait); virtual int get_sensor_data(sensor_data_t &data); bool get_properties(sensor_properties_t &properties); - private: - int m_temperature; + float m_temperature; + int m_node_handle; + unsigned long m_polling_interval; + unsigned long long m_fired_time; string m_model_id; string m_vendor; @@ -59,16 +59,16 @@ private: float m_raw_data_unit; float m_temp_offset; - string m_temp_node; + string m_data_node; + string m_enable_node; + string m_interval_node; string m_temperature_dir; + string m_temp_node; - bool m_sensorhub_supported; + bool m_sensorhub_controlled; cmutex m_value_mutex; bool update_value(bool wait); - bool is_sensorhub_supported(void); - bool check_hw_node(void); - bool enable_resource(bool enable); }; #endif /*_TEMPERATURE_SENSOR_HAL_CLASS_H_*/ -- 2.7.4 From 4115585f5d82c120f055a933e7db32c14d7b97f0 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Mon, 24 Nov 2014 13:16:58 +0530 Subject: [PATCH 10/16] Adding cconfig parent class for XML configuration Adding cconfig parent class for XML configuration Added cconfig parent class for cvirtual_sensor_config and csensor_config. Removed config namespace as XML configuration related code is small to have a separate namespace. Cleanup of namespace related code. Changed derived class cvirtual_sensor_config and csensor_config classes code based on new cconfig parent class Change-Id: I296dc7be45b201c70d040e7dac2e2b5325d5abc5 --- src/accel/accel_sensor_hal.cpp | 3 -- src/geo/geo_sensor_hal.cpp | 1 - src/gyro/gyro_sensor_hal.cpp | 3 -- src/light/light_sensor_hal.cpp | 3 -- src/pressure/pressure_sensor.cpp | 2 - src/pressure/pressure_sensor.h | 4 +- src/pressure/pressure_sensor_hal.cpp | 1 - src/proxi/proxi_sensor_hal.cpp | 2 - src/shared/CMakeLists.txt | 2 + src/shared/cconfig.cpp | 69 ++++++++++++++++++++++++++++++ src/shared/cconfig.h | 45 +++++++++++++++++++ src/shared/csensor_config.cpp | 37 ---------------- src/shared/csensor_config.h | 50 +++++++++------------- src/shared/cvirtual_sensor_config.cpp | 37 ---------------- src/shared/cvirtual_sensor_config.h | 14 ++---- src/shared/sensor_hal.cpp | 1 - src/temperature/temperature_sensor_hal.cpp | 2 - 17 files changed, 143 insertions(+), 133 deletions(-) create mode 100644 src/shared/cconfig.cpp create mode 100644 src/shared/cconfig.h diff --git a/src/accel/accel_sensor_hal.cpp b/src/accel/accel_sensor_hal.cpp index cb74385..53bb2d7 100755 --- a/src/accel/accel_sensor_hal.cpp +++ b/src/accel/accel_sensor_hal.cpp @@ -18,15 +18,12 @@ */ #include #include - #include #include - #include #include using std::ifstream; -using config::csensor_config; #define GRAVITY 9.80665 #define G_TO_MG 1000 diff --git a/src/geo/geo_sensor_hal.cpp b/src/geo/geo_sensor_hal.cpp index bfbb50e..d742b26 100755 --- a/src/geo/geo_sensor_hal.cpp +++ b/src/geo/geo_sensor_hal.cpp @@ -27,7 +27,6 @@ #include using std::ifstream; -using config::csensor_config; #define SENSOR_TYPE_MAGNETIC "MAGNETIC" #define ELEMENT_NAME "NAME" diff --git a/src/gyro/gyro_sensor_hal.cpp b/src/gyro/gyro_sensor_hal.cpp index 34184bc..c9bf135 100755 --- a/src/gyro/gyro_sensor_hal.cpp +++ b/src/gyro/gyro_sensor_hal.cpp @@ -19,17 +19,14 @@ #include #include #include - #include #include - #include #include #include #include using std::ifstream; -using config::csensor_config; #define DPS_TO_MDPS 1000 #define MIN_RANGE(RES) (-((1 << (RES))/2)) diff --git a/src/light/light_sensor_hal.cpp b/src/light/light_sensor_hal.cpp index 6498728..4cc630c 100755 --- a/src/light/light_sensor_hal.cpp +++ b/src/light/light_sensor_hal.cpp @@ -20,16 +20,13 @@ #include #include #include - #include #include - #include #include #include using std::ifstream; -using config::csensor_config; #define SENSOR_TYPE_LIGHT "LIGHT" #define ELEMENT_NAME "NAME" diff --git a/src/pressure/pressure_sensor.cpp b/src/pressure/pressure_sensor.cpp index 710c86a..d29311c 100755 --- a/src/pressure/pressure_sensor.cpp +++ b/src/pressure/pressure_sensor.cpp @@ -19,13 +19,11 @@ #include #include - #include #include #include #include -using config::csensor_config; using std::bind1st; using std::mem_fun; diff --git a/src/pressure/pressure_sensor.h b/src/pressure/pressure_sensor.h index 1da5cab..1bd8df2 100755 --- a/src/pressure/pressure_sensor.h +++ b/src/pressure/pressure_sensor.h @@ -25,7 +25,8 @@ #include #include -class pressure_sensor : public physical_sensor { +class pressure_sensor : public physical_sensor +{ public: pressure_sensor(); virtual ~pressure_sensor(); @@ -52,7 +53,6 @@ private: bool process_event(void); float pressure_to_altitude(float pressure); void raw_to_base(sensor_data_t &data); - }; #endif diff --git a/src/pressure/pressure_sensor_hal.cpp b/src/pressure/pressure_sensor_hal.cpp index 2823baa..c899d3e 100755 --- a/src/pressure/pressure_sensor_hal.cpp +++ b/src/pressure/pressure_sensor_hal.cpp @@ -29,7 +29,6 @@ using std::ifstream; using std::string; -using config::csensor_config; #define SENSOR_TYPE_PRESSURE "PRESSURE" #define ELEMENT_NAME "NAME" diff --git a/src/proxi/proxi_sensor_hal.cpp b/src/proxi/proxi_sensor_hal.cpp index 328211e..3154c18 100755 --- a/src/proxi/proxi_sensor_hal.cpp +++ b/src/proxi/proxi_sensor_hal.cpp @@ -27,7 +27,6 @@ #include using std::ifstream; -using config::csensor_config; #define NO_FLAG 0 #define PROXIMITY_TYPE 8 @@ -42,7 +41,6 @@ using config::csensor_config; #define PROXI_CODE 0x0019 - proxi_sensor_hal::proxi_sensor_hal() : m_state(PROXIMITY_STATE_FAR) , m_fired_time(0) diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt index 4a305da..2653782 100755 --- a/src/shared/CMakeLists.txt +++ b/src/shared/CMakeLists.txt @@ -38,6 +38,7 @@ include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) add_library(sensord-server SHARED crw_lock.cpp worker_thread.cpp + cconfig.cpp csensor_config.cpp cvirtual_sensor_config.cpp csensor_event_queue.cpp @@ -75,6 +76,7 @@ install(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) install(FILES crw_lock.h worker_thread.h + cconfig.h csensor_config.h cvirtual_sensor_config.h csensor_event_queue.h diff --git a/src/shared/cconfig.cpp b/src/shared/cconfig.cpp new file mode 100644 index 0000000..23d11a5 --- /dev/null +++ b/src/shared/cconfig.cpp @@ -0,0 +1,69 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 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 + +using std::ifstream; + +cconfig::cconfig(void) +{ + +} + +cconfig::~cconfig(void) +{ + +} + +bool cconfig::get_device_id(void) +{ + const string INFO_INI_PATH = "/etc/info.ini"; + const string START_DELIMETER = "Model="; + const string END_DELIMETER = ";"; + string line; + ifstream in_file; + std::size_t start_pos, end_pos; + bool ret = false; + + in_file.open(INFO_INI_PATH); + + if (!in_file.is_open()) + return false; + + while (!in_file.eof()) { + getline(in_file, line); + start_pos = line.find(START_DELIMETER); + + if (start_pos != std::string::npos) { + start_pos = start_pos + START_DELIMETER.size(); + end_pos = line.find(END_DELIMETER, start_pos); + + if (end_pos != std::string::npos) { + m_device_id = line.substr(start_pos, end_pos - start_pos); + ret = true; + break; + } + } + } + + in_file.close(); + + return ret; +} diff --git a/src/shared/cconfig.h b/src/shared/cconfig.h new file mode 100644 index 0000000..aa92fdd --- /dev/null +++ b/src/shared/cconfig.h @@ -0,0 +1,45 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 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 _CCONFIG_H_ +#define _CCONFIG_H_ + +#include +#include +#include + +using std::unordered_map; +using std::string; +using std::istringstream; + +class cconfig +{ +protected: + virtual bool load_config(const string& config_path) = 0; + + string m_device_id; +public: + cconfig(); + virtual ~cconfig(); + + bool get_device_id(void); + +}; + +#endif /* _CCONFIG_H_ */ diff --git a/src/shared/csensor_config.cpp b/src/shared/csensor_config.cpp index 013a086..1f193a7 100755 --- a/src/shared/csensor_config.cpp +++ b/src/shared/csensor_config.cpp @@ -25,7 +25,6 @@ #include #include -using namespace config; using std::ifstream; #define ROOT_ELEMENT "SENSOR" @@ -275,39 +274,3 @@ bool csensor_config::is_supported(const string& sensor_type,const string& model_ return true; } - -bool csensor_config::get_device_id(void) -{ - const string INFO_INI_PATH = "/etc/info.ini"; - const string START_DELIMETER = "Model="; - const string END_DELIMETER = ";"; - string line; - ifstream in_file; - std::size_t start_pos, end_pos; - bool ret = false; - - in_file.open(INFO_INI_PATH); - - if (!in_file.is_open()) - return false; - - while (!in_file.eof()) { - getline(in_file, line); - start_pos = line.find(START_DELIMETER); - - if (start_pos != std::string::npos) { - start_pos = start_pos + START_DELIMETER.size(); - end_pos = line.find(END_DELIMETER, start_pos); - - if (end_pos != std::string::npos) { - m_device_id = line.substr(start_pos, end_pos - start_pos); - ret = true; - break; - } - } - } - - in_file.close(); - - return ret; -} diff --git a/src/shared/csensor_config.h b/src/shared/csensor_config.h index 0c77f98..d4c69a5 100755 --- a/src/shared/csensor_config.h +++ b/src/shared/csensor_config.h @@ -20,13 +20,7 @@ #if !defined(_CSENSOR_CONFIG_CLASS_H_) #define _CSENSOR_CONFIG_CLASS_H_ -#include -#include -#include - -using std::unordered_map; -using std::string; -using std::istringstream; +#include #define SENSOR_CONFIG_FILE_PATH "/usr/etc/sensors.xml" @@ -74,30 +68,28 @@ typedef unordered_map Sensor_config; * */ -namespace config +class csensor_config : public cconfig { - class csensor_config - { - private: - csensor_config(); - csensor_config(csensor_config const&) {}; - csensor_config& operator=(csensor_config const&); - bool load_config(const string& config_path); - Sensor_config m_sensor_config; - string m_device_id; - public: - static csensor_config& get_instance(void); +private: + csensor_config(); + csensor_config(csensor_config const&) {}; + csensor_config& operator=(csensor_config const&); + + bool load_config(const string& config_path); + + Sensor_config m_sensor_config; +public: + static csensor_config& get_instance(void); + + bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, string& value); + bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, double& value); + bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, long& value); - bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, string& value); - bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, double& value); - bool get(const string& sensor_type, const string& model_id, const string& element, const string& attr, long& value); + bool get(const string& sensor_type, const string& model_id, const string& element, string& value); + bool get(const string& sensor_type, const string& model_id, const string& element, double& value); + bool get(const string& sensor_type, const string& model_id, const string& element, long& value); - bool get(const string& sensor_type, const string& model_id, const string& element, string& value); - bool get(const string& sensor_type, const string& model_id, const string& element, double& value); - bool get(const string& sensor_type, const string& model_id, const string& element, long& value); + bool is_supported(const string &sensor_type, const string &model_id); +}; - bool is_supported(const string &sensor_type, const string &model_id); - bool get_device_id(void); - }; -} #endif diff --git a/src/shared/cvirtual_sensor_config.cpp b/src/shared/cvirtual_sensor_config.cpp index 7aebd2d..c0d0f0b 100755 --- a/src/shared/cvirtual_sensor_config.cpp +++ b/src/shared/cvirtual_sensor_config.cpp @@ -24,9 +24,7 @@ #include #include #include -#include -using std::ifstream; using std::string; using std::stringstream; @@ -282,38 +280,3 @@ bool cvirtual_sensor_config::is_supported(const string& sensor_type) return true; } -bool cvirtual_sensor_config::get_device_id(void) -{ - const string INFO_INI_PATH = "/etc/info.ini"; - const string START_DELIMETER = "Model="; - const string END_DELIMETER = ";"; - string line; - ifstream in_file; - std::size_t start_pos, end_pos; - bool ret = false; - - in_file.open(INFO_INI_PATH); - - if (!in_file.is_open()) - return false; - - while (!in_file.eof()) { - getline(in_file, line); - start_pos = line.find(START_DELIMETER); - - if (start_pos != std::string::npos) { - start_pos = start_pos + START_DELIMETER.size(); - end_pos = line.find(END_DELIMETER, start_pos); - - if (end_pos != std::string::npos) { - m_device_id = line.substr(start_pos, end_pos - start_pos); - ret = true; - break; - } - } - } - - in_file.close(); - - return ret; -} diff --git a/src/shared/cvirtual_sensor_config.h b/src/shared/cvirtual_sensor_config.h index 754fd00..7cfbcb6 100755 --- a/src/shared/cvirtual_sensor_config.h +++ b/src/shared/cvirtual_sensor_config.h @@ -20,13 +20,7 @@ #if !defined(_CVIRTUAL_SENSOR_CONFIG_CLASS_H_) #define _CVIRTUAL_SENSOR_CONFIG_CLASS_H_ -#include -#include -#include - -using std::unordered_map; -using std::string; -using std::istringstream; +#include #define VIRTUAL_SENSOR_CONFIG_FILE_PATH "/usr/etc/virtual_sensors.xml" @@ -55,15 +49,16 @@ typedef unordered_map Virtual_sensor_config; * */ -class cvirtual_sensor_config +class cvirtual_sensor_config : public cconfig { private: cvirtual_sensor_config(); cvirtual_sensor_config(cvirtual_sensor_config const&) {}; cvirtual_sensor_config& operator=(cvirtual_sensor_config const&); + bool load_config(const string& config_path); + Virtual_sensor_config m_virtual_sensor_config; - string m_device_id; public: static cvirtual_sensor_config& get_instance(void); @@ -76,7 +71,6 @@ public: bool get(const string& sensor_type, const string& element, int *value, int count = 1); bool is_supported(const string &sensor_type); - bool get_device_id(void); }; #endif diff --git a/src/shared/sensor_hal.cpp b/src/shared/sensor_hal.cpp index 55c20f7..a312162 100755 --- a/src/shared/sensor_hal.cpp +++ b/src/shared/sensor_hal.cpp @@ -25,7 +25,6 @@ using std::ifstream; using std::fstream; -using config::csensor_config; cmutex sensor_hal::m_shared_mutex; diff --git a/src/temperature/temperature_sensor_hal.cpp b/src/temperature/temperature_sensor_hal.cpp index 350d530..cf562bb 100755 --- a/src/temperature/temperature_sensor_hal.cpp +++ b/src/temperature/temperature_sensor_hal.cpp @@ -26,9 +26,7 @@ #include #include - using std::ifstream; -using config::csensor_config; #define SENSOR_TYPE_TEMPERATURE "TEMPERATURE" #define ELEMENT_NAME "NAME" -- 2.7.4 From b857b3f8962a12646ee9afba0c0008db29096783 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Mon, 24 Nov 2014 13:31:46 +0530 Subject: [PATCH 11/16] Updating configurability support for Orientation Sensor - Added support for getting output orientation as both radians and degrees - Updating orientation sensor properties Change-Id: I296dc7be45b201c70d151e7dac2e2b5325d5abc5 --- src/orientation/orientation_sensor.cpp | 40 ++++++++++++++++++++++++++------ src/sensor_fusion/orientation_filter.cpp | 2 +- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/orientation/orientation_sensor.cpp b/src/orientation/orientation_sensor.cpp index b1222e2..72145b0 100755 --- a/src/orientation/orientation_sensor.cpp +++ b/src/orientation/orientation_sensor.cpp @@ -44,7 +44,9 @@ #define MS_TO_US 1000 -#define AZIMUTH_OFFSET 360 +#define PI 3.141593 +#define AZIMUTH_OFFSET_DEGREES 360 +#define AZIMUTH_OFFSET_RADIANS (2 * PI) #define ELEMENT_NAME "NAME" #define ELEMENT_VENDOR "VENDOR" @@ -294,6 +296,7 @@ void orientation_sensor::synthesize(const sensor_event_t &event, vector euler_orientation; float raw_data[3]; + float azimuth_offset; if (event.event_type == ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME) { diff_time = event.data.timestamp - m_timestamp; @@ -343,6 +346,14 @@ void orientation_sensor::synthesize(const sensor_event_t &event, vector= 0) orientation_event.data.values[0] = euler_orientation.m_ang.m_vec[2]; else - orientation_event.data.values[0] = euler_orientation.m_ang.m_vec[2] + AZIMUTH_OFFSET; + orientation_event.data.values[0] = euler_orientation.m_ang.m_vec[2] + azimuth_offset; push(orientation_event); } @@ -372,6 +383,7 @@ int orientation_sensor::get_sensor_data(const unsigned int event_type, sensor_da sensor_data_t magnetic_data; euler_angles euler_orientation; + float azimuth_offset; if (event_type != ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME) return -1; @@ -394,6 +406,14 @@ int orientation_sensor::get_sensor_data(const unsigned int event_type, sensor_da euler_orientation = m_orientation.get_orientation(accel, gyro, magnetic); + if(m_raw_data_unit == "DEGREES") { + euler_orientation = rad2deg(euler_orientation); + azimuth_offset = AZIMUTH_OFFSET_DEGREES; + } + else { + azimuth_offset = AZIMUTH_OFFSET_RADIANS; + } + data.accuracy = SENSOR_ACCURACY_GOOD; data.timestamp = get_timestamp(); data.values[1] = euler_orientation.m_ang.m_vec[0]; @@ -401,7 +421,7 @@ int orientation_sensor::get_sensor_data(const unsigned int event_type, sensor_da if (euler_orientation.m_ang.m_vec[2] >= 0) data.values[0] = euler_orientation.m_ang.m_vec[2]; else - data.values[0] = euler_orientation.m_ang.m_vec[2] + AZIMUTH_OFFSET; + data.values[0] = euler_orientation.m_ang.m_vec[2] + azimuth_offset; data.value_count = 3; return 0; @@ -409,11 +429,17 @@ int orientation_sensor::get_sensor_data(const unsigned int event_type, sensor_da bool orientation_sensor::get_properties(sensor_properties_t &properties) { - properties.min_range = -180; - properties.max_range = 360; - properties.resolution = 1; + if(m_raw_data_unit == "DEGREES") { + properties.min_range = -180; + properties.max_range = 360; + } + else { + properties.min_range = -PI; + properties.max_range = 2 * PI; + } + properties.resolution = 0.000001;; - properties.vendor = "Samsung"; + properties.vendor = m_vendor; properties.name = SENSOR_NAME; return true; diff --git a/src/sensor_fusion/orientation_filter.cpp b/src/sensor_fusion/orientation_filter.cpp index 14058a6..a615217 100644 --- a/src/sensor_fusion/orientation_filter.cpp +++ b/src/sensor_fusion/orientation_filter.cpp @@ -220,7 +220,7 @@ inline void orientation_filter::time_update() m_quat_driv.quat_normalize(); quat_output = phase_correction(m_quat_driv, m_quat_aid); - orientation = rad2deg(quat2euler(quat_output)); + orientation = quat2euler(quat_output); m_orientation.m_ang.m_vec[0] = orientation.m_ang.m_vec[0] * m_pitch_phase_compensation; m_orientation.m_ang.m_vec[1] = orientation.m_ang.m_vec[1] * m_roll_phase_compensation; -- 2.7.4 From 2b50ed33632907e91e1d73923c0d97cc50e6094f Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Mon, 24 Nov 2014 13:39:01 +0530 Subject: [PATCH 12/16] Updating the get_properties method - Updating get_properties method for gravity and linear acceleration Change-Id: I296dc7be45b201c55d151e7dac2e2b5325d5abc5 --- src/gravity/gravity_sensor.cpp | 2 +- src/linear_accel/linear_accel_sensor.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gravity/gravity_sensor.cpp b/src/gravity/gravity_sensor.cpp index 08b70c5..328cab8 100755 --- a/src/gravity/gravity_sensor.cpp +++ b/src/gravity/gravity_sensor.cpp @@ -205,7 +205,7 @@ bool gravity_sensor::get_properties(sensor_properties_t &properties) { properties.min_range = -GRAVITY; properties.max_range = GRAVITY; - properties.resolution = 1; + properties.resolution = 0.000001;; properties.vendor = m_vendor; properties.name = SENSOR_NAME; diff --git a/src/linear_accel/linear_accel_sensor.cpp b/src/linear_accel/linear_accel_sensor.cpp index 794bef0..f975733 100755 --- a/src/linear_accel/linear_accel_sensor.cpp +++ b/src/linear_accel/linear_accel_sensor.cpp @@ -276,6 +276,9 @@ bool linear_accel_sensor::get_properties(sensor_properties_t &properties) m_gravity_sensor->get_properties(properties); properties.name = "Linear Acceleration Sensor"; properties.vendor = m_vendor; + properties.min_range = - 2 * GRAVITY; + properties.max_range = 2 * GRAVITY; + properties.resolution = 0.000001; return true; } -- 2.7.4 From 02d8a813cd1d4673841ffe3a49ac547df4b8f5b8 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Mon, 24 Nov 2014 17:40:44 +0530 Subject: [PATCH 13/16] Adding Virtual Sensor Configuration Information Adding html document for information on configuring virtual sensors. Change-Id: I296dc7be45b201c70d151e7dac2e2b5325d5abd6 --- Virtual_Sensor_Configuration.htm | 146 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 Virtual_Sensor_Configuration.htm diff --git a/Virtual_Sensor_Configuration.htm b/Virtual_Sensor_Configuration.htm new file mode 100644 index 0000000..596d3fe --- /dev/null +++ b/Virtual_Sensor_Configuration.htm @@ -0,0 +1,146 @@ + +Information on Configuration of Virtual Sensors + +

Description for Orientation Virtual Sensor "ORIENTATION"

+ +

XML Code

+ + +<ORIENTATION>
+ <NAME value="ORIENTATION_SENSOR" >
+ <VENDOR value="SAMSUNG" >
+ <RAW_DATA_UNIT value="DEGREES" >
+ <DEFAULT_SAMPLING_TIME value="100" >
+ <ACCEL_STATIC_BIAS value1="0" value2="0" value3="0" >
+ <GYRO_STATIC_BIAS value1="0" value2="0" value3="0" >
+ <GEOMAGNETIC_STATIC_BIAS value1="0" value2="0" value3="0" >
+ <ACCEL_ROTATION_DIRECTION_COMPENSATION value1="-1" value2="-1" value3="-1" >
+ <GYRO_ROTATION_DIRECTION_COMPENSATION value1="1" value2="1" value3="1" >
+ <GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION value1="-1" value2="-1" value3="-1" >
+ <ACCEL_SCALE value="1" >
+ <GYRO_SCALE value="1146" >
+ <GEOMAGNETIC_SCALE value="1" >
+ <MAGNETIC_ALIGNMENT_FACTOR value="1" >
+ <AZIMUTH_ROTATION_COMPENSATION value="-1" >
+ <PITCH_ROTATION_COMPENSATION value="-1" >
+ <ROLL_ROTATION_COMPENSATION value="-1" >
+<ORIENTATION>
+ +

Description of Congiguration in XML Code

+ +

Based on the configuration parameter there may be a single value or +three values assigned. In case of three values, 'value1' represents X-axis +component, 'value2' represents Y-axis component and 'value3' represents +Z-axis component for any sensor.

+ +

NAME

+

Name of the Virtual Sensor

+ +

VENDOR

+

Name of the vendor who developed Orientation virtual sensor.

+ +

RAW_DATA_UNIT

+

Units for the raw data output from the Orientation virtual sensor. The +unit options available are 'DEGREES' and 'RADIANS'. The output device +orientation would be expresses in terms of degrees or radians based on the +option selected.

+ +

DEFAULT_SAMPLING_TIME

+

Default sampling interval (in msec) value at which the Orientation +virtual sensor is initialized.

+ +

ACCEL_STATIC_BIAS

+

The static bias value for accelerometer X, Y and Z axis data is +computed when the device is at rest with an device orientation (pitch, +roll, azimuth) as (0, 0, 0). The non-zero accelerometer data values observed +on the X, Y and Z axis are the bias values to be entered respectively. +The entered bias values would be subtracted from the accelerometer input +data in the pre-processing stage of the sensor fusion algorithm.

+ +

GYRO_STATIC_BIAS

+

The static bias value for gyroscope X, Y and Z axis data is computed +when the device is at rest with an device orientation (pitch, roll, azimuth) +as (0, 0, 0). The non-zero gyroscope data values observed on the X, Y and +Z axis are the bias values to be entered respectively. The entered bias +values would be subtracted from the gyroscope input data in the +pre-processing stage of the sensor fusion algorithm.

+ +

GEOMAGNETIC_STATIC_BIAS

+

The static bias value for geomagnetic sensor X, Y and Z axis data is +computed when the device is at rest with an device orientation (pitch, roll, +azimuth) as (0, 0, 0). The non-zero geomagnetic sensor data values observed +on the X, Y and Z axis are the bias values to be entered respectively. The +entered bias values would be subtracted from the geomagnetic sensor input +data in the pre-processing stage of the sensor fusion algorithm.

+ +

ACCEL_ROTATION_DIRECTION_COMPENSATION

+

The rotation direction compensation for each axis X, Y and Z is assigned a +value of "+1" if the clockwise rotation of the device for the particular axis +results in positive increase in accelerometer data values. The rotation +direction compensation for each axis is assigned a value of "-1" if for the +clockwise rotation of the device for the particular axis results in negative +increase in accelerometer data value. This parameter will take only take two +values +1 or -1.

+ +

GYRO_ROTATION_DIRECTION_COMPENSATION

+

The rotation direction compensation for each axis X, Y and Z is assigned a +value of "+1" if the clockwise rotation of the device for the particular axis +results in positive change in gyroscope angular rate values. The rotation +direction compensation for each axis is assigned a value of "-1" if for the +clockwise rotation of the device for the particular axis results in negative +change in gyroscope angular rate value. This parameter will take only take +two values of either +1 or -1.

+ +

GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION

+

The rotation direction compensation for each axis X, Y and Z is assigned a +value of "+1" if the clockwise rotation of the device around any of the +different axis results in a positive increase in geomagnetic sensor data values. +The rotation direction compensation for the axis is assigned a value of "-1" +if for the clockwise rotation of the device for the any axis results in +negative increase in geomagnetic sensor value. This parameter will only take +two values of either +1 or -1.

+ +

ACCEL_SCALE

+

In the current version of the sensor fusion algorithm this value is always +set to +1.

+ +

GYRO_SCALE

+

If MAX_VAL is the maximum possible gyroscope data magnitude on all three +axes for both the positive and negative measured values, then the value equal +to (2 x MAX_VAL) should be entered for this field. The MAX_VAL magnitude which +also is the same as the maximum range of the gyroscope sensor has to be taken +from the sensor specification document or can be computed by rotating the +device on all axis and measuring the maximum possible gyroscope value during +the rotations.

+ +

GEOMAGNETIC_SCALE

+

In the current version of the sensor fusion algorithm this value is always +set to +1.

+ +

MAGNETIC_ALIGNMENT_FACTOR

+

If the magnetic orientation of the device geomagnetic sensor points to north +when the device azimuth is pointing north this value is set as +1. If the +magnetic orientation of the device geomagnetic sensor points to south +when the device azimuth is pointing north this value is set as -1. For both +the settings the North->East->South->West rotation of the device results in +positive change in geomagnetic sensor data values and North->West->South->East +rotation results in a negative change in geomagnetic sensor data values.

+ +

AZIMUTH_ROTATION_COMPENSATION

+

If the North->East->South->West azimuth rotation of the device results in +positive increase in the azimuth output this value is set to +1.If the +North->East->South->West azimuth rotation of the device results in negative +increase in the azimuth output this value is set to -1.

+ +

PITCH_ROTATION_COMPENSATION

+

If the clockwise pitch rotation of the device results in positive increase +in the pitch output this value is set to +1.If the clockwise pitch rotation +of the device results in negative increase in the pitch output this value is +set to -1.

+ +

ROLL_ROTATION_COMPENSATION

+

If the clockwise roll rotation of the device results in positive increase +in the roll output this value is set to +1.If the clockwise roll rotation +of the device results in negative increase in the roll output this value is +set to -1.

+ -- 2.7.4 From e36e52947f79f79596d03c7fd8d66b9824bf4a82 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Tue, 25 Nov 2014 13:42:53 +0530 Subject: [PATCH 14/16] Updating orientation input units support for gravity - Adding support for input orientation in terms of degrees and radians during computation of gravity. Change-Id: Ib14b4b95f3ba98b924f0da16683bd1bc077c4ac3 --- src/gravity/gravity_sensor.cpp | 33 +++++++++++++++++++++++++-------- src/gravity/gravity_sensor.h | 1 + 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/gravity/gravity_sensor.cpp b/src/gravity/gravity_sensor.cpp index 328cab8..a870244 100755 --- a/src/gravity/gravity_sensor.cpp +++ b/src/gravity/gravity_sensor.cpp @@ -38,6 +38,7 @@ #define SENSOR_NAME "GRAVITY_SENSOR" #define SENSOR_TYPE_GRAVITY "GRAVITY" +#define SENSOR_TYPE_ORIENTATION "ORIENTATION" #define MS_TO_US 1000 @@ -46,6 +47,7 @@ #define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" #define ELEMENT_DEFAULT_SAMPLING_TIME "DEFAULT_SAMPLING_TIME" #define ELEMENT_GRAVITY_SIGN_COMPENSATION "GRAVITY_SIGN_COMPENSATION" +#define ELEMENT_ORIENTATION_DATA_UNIT "RAW_DATA_UNIT" gravity_sensor::gravity_sensor() : m_orientation_sensor(NULL) @@ -66,6 +68,13 @@ gravity_sensor::gravity_sensor() INFO("m_vendor = %s", m_vendor.c_str()); + if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ORIENTATION_DATA_UNIT, m_orientation_data_unit)) { + ERR("[ORIENTATION_DATA_UNIT] is empty\n"); + throw ENXIO; + } + + INFO("m_orientation_data_unit = %s", m_orientation_data_unit.c_str()); + if (!config.get(SENSOR_TYPE_GRAVITY, ELEMENT_RAW_DATA_UNIT, m_raw_data_unit)) { ERR("[RAW_DATA_UNIT] is empty\n"); throw ENXIO; @@ -156,10 +165,14 @@ bool gravity_sensor::delete_interval(int client_id) void gravity_sensor::synthesize(const sensor_event_t &event, vector &outs) { sensor_event_t gravity_event; + float conversion_const = 1; const float MIN_DELIVERY_DIFF_FACTOR = 0.75f; unsigned long long diff_time; + if(m_orientation_data_unit == "DEGREES") + conversion_const = DEG2RAD; + if (event.event_type == ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME) { diff_time = event.data.timestamp - m_timestamp; @@ -169,10 +182,10 @@ void gravity_sensor::synthesize(const sensor_event_t &event, vector Date: Tue, 25 Nov 2014 14:58:55 +0530 Subject: [PATCH 15/16] Adding diagram to Configuration document - Adding device orientation diagram - Formating document for better readability Change-Id: Ib14b4b95f3ba14b924f0da16683bd1bc077c4ac3 --- Virtual_Sensor_Configuration.htm | 51 +++++++++++++++++++++------------------ device_orientation.png | Bin 0 -> 37845 bytes 2 files changed, 28 insertions(+), 23 deletions(-) create mode 100755 device_orientation.png diff --git a/Virtual_Sensor_Configuration.htm b/Virtual_Sensor_Configuration.htm index 596d3fe..ad40152 100644 --- a/Virtual_Sensor_Configuration.htm +++ b/Virtual_Sensor_Configuration.htm @@ -1,10 +1,15 @@ Information on Configuration of Virtual Sensors -

Description for Orientation Virtual Sensor "ORIENTATION"

+

Configuration of Virtual Sensors


-

XML Code

+

1. Orientation Virtual Sensor

+
+ +

+ +

1.1 XML Code

<ORIENTATION>
 <NAME value="ORIENTATION_SENSOR" >
@@ -26,30 +31,30 @@  <ROLL_ROTATION_COMPENSATION value="-1" >
<ORIENTATION>
-

Description of Congiguration in XML Code

+

1.2 Description of Configuration in XML Code

Based on the configuration parameter there may be a single value or three values assigned. In case of three values, 'value1' represents X-axis component, 'value2' represents Y-axis component and 'value3' represents Z-axis component for any sensor.

-

NAME

+

1.2.1 NAME

Name of the Virtual Sensor

-

VENDOR

+

1.2.2 VENDOR

Name of the vendor who developed Orientation virtual sensor.

-

RAW_DATA_UNIT

+

1.2.3 RAW_DATA_UNIT

Units for the raw data output from the Orientation virtual sensor. The unit options available are 'DEGREES' and 'RADIANS'. The output device orientation would be expresses in terms of degrees or radians based on the option selected.

-

DEFAULT_SAMPLING_TIME

+

1.2.4 DEFAULT_SAMPLING_TIME

Default sampling interval (in msec) value at which the Orientation virtual sensor is initialized.

-

ACCEL_STATIC_BIAS

+

1.2.5 ACCEL_STATIC_BIAS

The static bias value for accelerometer X, Y and Z axis data is computed when the device is at rest with an device orientation (pitch, roll, azimuth) as (0, 0, 0). The non-zero accelerometer data values observed @@ -57,7 +62,7 @@ on the X, Y and Z axis are the bias values to be entered respectively. The entered bias values would be subtracted from the accelerometer input data in the pre-processing stage of the sensor fusion algorithm.

-

GYRO_STATIC_BIAS

+

1.2.6 GYRO_STATIC_BIAS

The static bias value for gyroscope X, Y and Z axis data is computed when the device is at rest with an device orientation (pitch, roll, azimuth) as (0, 0, 0). The non-zero gyroscope data values observed on the X, Y and @@ -65,7 +70,7 @@ Z axis are the bias values to be entered respectively. The entered bias values would be subtracted from the gyroscope input data in the pre-processing stage of the sensor fusion algorithm.

-

GEOMAGNETIC_STATIC_BIAS

+

1.2.7 GEOMAGNETIC_STATIC_BIAS

The static bias value for geomagnetic sensor X, Y and Z axis data is computed when the device is at rest with an device orientation (pitch, roll, azimuth) as (0, 0, 0). The non-zero geomagnetic sensor data values observed @@ -73,7 +78,7 @@ on the X, Y and Z axis are the bias values to be entered respectively. The entered bias values would be subtracted from the geomagnetic sensor input data in the pre-processing stage of the sensor fusion algorithm.

-

ACCEL_ROTATION_DIRECTION_COMPENSATION

+

1.2.8 ACCEL_ROTATION_DIRECTION_COMPENSATION

The rotation direction compensation for each axis X, Y and Z is assigned a value of "+1" if the clockwise rotation of the device for the particular axis results in positive increase in accelerometer data values. The rotation @@ -82,7 +87,7 @@ clockwise rotation of the device for the particular axis results in negative increase in accelerometer data value. This parameter will take only take two values +1 or -1.

-

GYRO_ROTATION_DIRECTION_COMPENSATION

+

1.2.9 GYRO_ROTATION_DIRECTION_COMPENSATION

The rotation direction compensation for each axis X, Y and Z is assigned a value of "+1" if the clockwise rotation of the device for the particular axis results in positive change in gyroscope angular rate values. The rotation @@ -91,7 +96,7 @@ clockwise rotation of the device for the particular axis results in negative change in gyroscope angular rate value. This parameter will take only take two values of either +1 or -1.

-

GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION

+

1.2.10 GEOMAGNETIC_ROTATION_DIRECTION_COMPENSATION

The rotation direction compensation for each axis X, Y and Z is assigned a value of "+1" if the clockwise rotation of the device around any of the different axis results in a positive increase in geomagnetic sensor data values. @@ -100,11 +105,11 @@ if for the clockwise rotation of the device for the any axis results in negative increase in geomagnetic sensor value. This parameter will only take two values of either +1 or -1.

-

ACCEL_SCALE

+

1.2.11 ACCEL_SCALE

In the current version of the sensor fusion algorithm this value is always set to +1.

-

GYRO_SCALE

+

1.2.12 GYRO_SCALE

If MAX_VAL is the maximum possible gyroscope data magnitude on all three axes for both the positive and negative measured values, then the value equal to (2 x MAX_VAL) should be entered for this field. The MAX_VAL magnitude which @@ -113,11 +118,11 @@ from the sensor specification document or can be computed by rotating the device on all axis and measuring the maximum possible gyroscope value during the rotations.

-

GEOMAGNETIC_SCALE

+

1.2.13 GEOMAGNETIC_SCALE

In the current version of the sensor fusion algorithm this value is always set to +1.

-

MAGNETIC_ALIGNMENT_FACTOR

+

1.2.14 MAGNETIC_ALIGNMENT_FACTOR

If the magnetic orientation of the device geomagnetic sensor points to north when the device azimuth is pointing north this value is set as +1. If the magnetic orientation of the device geomagnetic sensor points to south @@ -126,21 +131,21 @@ the settings the North->East->South->West rotation of the device results in positive change in geomagnetic sensor data values and North->West->South->East rotation results in a negative change in geomagnetic sensor data values.

-

AZIMUTH_ROTATION_COMPENSATION

+

1.2.15 AZIMUTH_ROTATION_COMPENSATION

If the North->East->South->West azimuth rotation of the device results in -positive increase in the azimuth output this value is set to +1.If the +positive increase in the azimuth output this value is set to +1. If the North->East->South->West azimuth rotation of the device results in negative increase in the azimuth output this value is set to -1.

-

PITCH_ROTATION_COMPENSATION

+

1.2.16 PITCH_ROTATION_COMPENSATION

If the clockwise pitch rotation of the device results in positive increase -in the pitch output this value is set to +1.If the clockwise pitch rotation +in the pitch output this value is set to +1. If the clockwise pitch rotation of the device results in negative increase in the pitch output this value is set to -1.

-

ROLL_ROTATION_COMPENSATION

+

1.2.17 ROLL_ROTATION_COMPENSATION

If the clockwise roll rotation of the device results in positive increase -in the roll output this value is set to +1.If the clockwise roll rotation +in the roll output this value is set to +1. If the clockwise roll rotation of the device results in negative increase in the roll output this value is set to -1.

diff --git a/device_orientation.png b/device_orientation.png new file mode 100755 index 0000000000000000000000000000000000000000..037ad6a769216912b9618b714166135aad1c28a3 GIT binary patch literal 37845 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 Date: Wed, 26 Nov 2014 12:03:13 +0530 Subject: [PATCH 16/16] Fixing build issues in virtual sensors test files Change-Id: Ic009931a0bac60f27cd832e089097c034e5721af --- test/src/gravity.c | 2 +- test/src/linear_acceleration.c | 2 +- test/src/orientation.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/src/gravity.c b/test/src/gravity.c index 48081ce..a055013 100755 --- a/test/src/gravity.c +++ b/test/src/gravity.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/src/linear_acceleration.c b/test/src/linear_acceleration.c index ed36928..5e157e5 100755 --- a/test/src/linear_acceleration.c +++ b/test/src/linear_acceleration.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include diff --git a/test/src/orientation.c b/test/src/orientation.c index ca9b083..1886ad1 100755 --- a/test/src/orientation.c +++ b/test/src/orientation.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include -- 2.7.4