System:Sensord

From Tizen Wiki
Jump to: navigation, search

Contents

Introduction to Sensor Framework

Sensor devices are used widely in mobile devices to enhance user experience. Most modern mobile OSs have a framework which manages sensor hardware on the platform and provides convenient API to the application.

Types of Sensors

Sensors are classified as hardware and virtual sensors. Tizen supports individual plugins for the following sensors:

Hardware Sensors

  • Accelerometer sensor
  • Geomagnetic Sensor
  • Gyroscope Sensor
  • Light Sensor
  • Proximity Sensor
  • Pressure Sensor
  • Ultraviolet Sensor
  • Temperature Sensor
  • Humidity Sensor
  • HRM(Heart Rate Monitor) Sensor
  • HRM LED Green Sensor
  • HRM LED IR Sensor
  • HRM LED Red Sensor
  • Uncalibrated Geomagnetic Sensor
  • Uncalibrated Gyroscope Sensor

Virtual Sensors

  • Orientation Sensor
  • Gravity Sensor
  • Linear Acceleration Sensor
  • Rotation Vector Sensor
  • Gyroscope Rotation Vector Sensor
  • Geomagnetic Rotation Vector Sensor


Architectural Overview

Sensor Framework Architecture

The Sensor framework provides a sensor server for creating plugins and a medium through which the client applications are connected to the sensor hardware to exchange data. The sensor plugins retrieve data from sensor hardware and enable the client applications to use the data for specific requirements.


Components of Sensor Framework

Here's the brief description of the major sensor framework components:

Sensor Client Library

Any application that wants to access the sensor server and communicate with it should use the sensor API and the client library. Using the Sensor API, the application can connect to the sensor server. As shown in the below diagram, any application or middleware framework, by using the sensor API, can have the sensor-framework client library executing within its own process context.

Client Commands

These are the APIs exposed to the user at application level with which he can connect to a sensor, register for a particular event and start receiving data for that particular event with a time interval the user can select as specified by the driver for that particular sensor. Default time interval is 100ms.

Example Client Commands
int sensord_connect(sensor_t sensor)

bool sensord_disconnect(int handle)

bool sensord_register_event(int handle, unsigned int event_type, unsigned int interval, unsigned int max_batch_latency, sensor_cb_t cb, void *user_data)

bool sensord_unregister_event(int handle, unsigned int event_type)

bool sensord_start(int handle, int option)

bool sensord_stop(int handle)

bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* sensor_data)
Description of Client Commands
Prototype Description Return Value
int sensord_connect(sensor_t sensor) Connect a given sensor and get a handle of a given sensor. a handle of a given sensor on success, otherwise negative value
bool sensord_disconnect(int handle) Disconnect a given sensor for a given handle Success - True

Failure - False

bool sensord_register_event(int handle, unsigned int event_type, unsigned int interval, unsigned int max_batch_latency, sensor_cb_t cb, void *user_data) Register a callback with a connected sensor for a given event_type. This callback will be called when a given event occurs in a connected sensor. Success - True

Failure - False

bool sensord_unregister_event(int handle, unsigned int event_type); Unregister an event with a connected sensor. After unregistering, that event will not be sent. Success - True

Failure - False

bool sensord_start(int handle, int option) Start listening events with a connected sensor. Success - True

Failure - False

bool sensord_stop(int handle) Stop listening events with a connected sensor. Success - True

Failure - False

bool sensord_get_data(int handle, unsigned int data_id, sensor_data_t* sensor_data) Get sensor data from a connected sensor. Success - True

Failure - False

Command Channel

It is used for sending commands to the interface from the client side to the server to register events for a particular sensor, unregister events, set or unset interval. It also provides a command handler which sends the command from the client side in the form of a packet and expects to receive a command acknowledgement packet which would consist of the header and the return payload.

Example Command Channel Interface

The major components of the interface are

class command_channel
{
public:
	command_channel();
        ~command_channel();
		
	bool cmd_register_event(unsigned int event_type);
	bool cmd_unregister_event(unsigned int event_type);
	bool cmd_set_interval(unsigned int interval);
	bool cmd_unset_interval(void);
	bool cmd_set_command(unsigned int cmd, long value);
	bool cmd_get_data(unsigned int type, sensor_data_t* values);
	
private:
	bool command_handler(cpacket *packet, void **return_payload);
};
Description of Command Channel Interface
Prototype Description Return Value
command_channel() Initializes private variables m_client_id and m_sensor_id

m_client_id stores the client id and m_sensor_id stores the sensor id for which the command will be sent.

NA
~command_channel() Closes the command socket channel NA
bool cmd_register_event(unsigned int event_type) Registers the input event with the server Success - True

Failure - False

bool cmd_unregister_event(unsigned int event_type) Unregisters the input event from the server side Success - True

Failure - False

bool cmd_set_interval(unsigned int interval) Sends command for setting the interval for the client Success - True

Failure - False

bool cmd_unset_interval(void) Sends command for unsetting the interval for the client Success - True

Failure - False

bool cmd_get_data(unsigned int type, sensor_data_t* values) Sends command for receiving data for the input sensor type Success - True

Failure - False

bool command_handler(cpacket *packet, void **return_payload) Recieves the command packet from the client and returns the acknowledgement from the server as payload Success - True

Failure - False

Client information

Stores client information regarding events such as registration,deletion,changing registered event information and interval information on the client side.

Example Client Information Interface

The major components of the interface are

class csensor_handle_info {
public:
	bool add_reg_event_info(unsigned int event_type, unsigned int interval, int cb_type, void *cb,void *user_data);
	bool delete_reg_event_info(unsigned int event_type);
	bool change_reg_event_interval(unsigned int event_type, unsigned int interval);
	creg_event_info* get_reg_event_info(const unsigned int event_type);	
	unsigned int get_min_interval(void);
};
Description of Client Information Interface
Prototype Description Return Value
bool add_reg_event_info(unsigned int event_type, unsigned int interval, int cb_type, void *cb,void *user_data) Adds event info for the registered event such as time interval and call back function in the client information storage block m_reg_event_infos map Success - True

Failure - False

bool delete_reg_event_info(unsigned int event_type) Deletes the registered event of event_type from the client information block Success - True

Failure - False

bool change_reg_event_interval(unsigned int event_type, unsigned int interval) Changes the event interval for the registered event event_type Success - True

Failure - False

creg_event_info* get_reg_event_info(const unsigned int event_type) Returns event information for the registered event of event_type Pointer object of creg_event_info class
unsigned int get_min_interval(void) Returns the minimum interval out of all the registered events in the client information block. Value of minimum interval

Event handler

Example Event handler Interface

The major components of the interface are

class csensor_event_listener {
public:
	static csensor_event_listener& get_instance(void);
	int create_handle(sensor_id_t sensor_id);
	bool delete_handle(int handle);
	bool start_handle(int handle);
	bool stop_handle(int handle);
        void get_all_handles(handle_vector &handles);
};
Description of Event handler Interface
Prototype Description Return Value
static csensor_event_listener& get_instance(void) Returns an instance of the event listener class Static object of class csensor_event_listener
int create_handle(sensor_id_t sensor_id) Creates an event handle for a given sensor and adds it to the map containing all handles information. Returns the value of the created event handle.

If it is less than 0 ,handle was not created.

bool delete_handle(int handle) Checks for the given handle and if present removes it from the map having handles information. Success - True

Failure - False

bool start_handle(int handle) Sets the sensor state as started for the given handle. Success - True

Failure - False

bool stop_handle(int handle) Sets the sensor state as stopped for the given handle. Success - True

Failure - False

void get_all_handles(handle_vector &handles) Returns a vector of all handles registered by all clients in the m_sensor_handle_infos map NA

Event Listener

Example Event Listener Interface

The major components of the interface are

class csensor_event_listener {
public:
	bool register_event(int handle, unsigned int event_type, unsigned int interval, int cb_type, void *cb, void* user_data);
        bool unregister_event(int handle, unsigned int event_type);
        bool change_event_interval(int handle, unsigned int event_type, unsigned int interval);
        void get_listening_sensors(sensor_id_vector &sensors);
        bool add_command_channel(sensor_id_t sensor_id, command_channel *cmd_channel);
        bool start_event_listener(void);

};
Description of Event Listener Interface
Prototype Description Return Value
bool register_event(int handle, unsigned int event_type, unsigned int interval, int cb_type, void *cb, void* user_data) If the input handle exists, the event information with respect to the input parameters such as event type, event interval and call back function are added for the corresponding handle. Success - True

Failure - False

bool unregister_event(int handle, unsigned int event_type) Removes the event for the given handle Success - True

Failure - False

bool change_event_interval(int handle, unsigned int event_type, unsigned int interval) Changes the event interval for a given event type associated with an event handle. Success - True

Failure - False

void get_listening_sensors(sensor_id_vector &sensors) Gives the list of sensors with a handle for listening for an event in sensor_id_vector &sensors from the map m_sensor_handle_infos. NA
bool add_command_channel(sensor_id_t sensor_id, command_channel *cmd_channel) Adds the command channel for the given sensor to the map m_command_channels if no command channel exists. Success - True

Failure - False

bool start_event_listener(void) Creates an event channel for the client Sets the state of the thread for listening events to start state


Success - True

Failure - False

Client function callback

The event handler executes the client call back function which was registered by the client at the time of event registration. It is a GMainloop based event handler. The application running the sensor framework client code, on receiving the sensor event data from the server, triggers the registered call back function for the specific event. The call back function implements a specific set of functionality which needs to be executed in the application based on the sensor event and data that is received.

Sensor Server

The sensor server is a daemon which communicates uniquely to multiple sensors (through drivers) in the system and dispatches sensor data/events back to the application. The sensor server takes care of initializing sensors during boot, driver configuration, sensor data fetching/delivery and management of all sensors on the platform.

Sensor plugin loader

Example Sensor plugin loader Interface

The major components of the interface are

class sensor_plugin_loader
{
private:	
        bool get_paths_from_config(const string &config_path, vector<string> &hal_paths, vector<string> &sensor_paths);

public:
        bool load_plugins();
        vector<sensor_base *> get_sensors(sensor_type_t type);
        vector<sensor_base *> get_virtual_sensors(void);
        void show_sensor_info (void);
};
Description of Sensor plugin loader interface
Prototype Description Return Value
bool get_paths_from_config(const string &config_path, vector<string> &hal_paths, vector<string> &sensor_paths) Parses the xml file at the location config_path.

Pushes the paths in the xml file into hal_paths or sensor_paths depending on the plugin type.

Success - True

Failure - False

bool load_plugins() Loads the sensor plugins from the path /usr/etc/sensor_plugins.xml Success - True

Failure - False

vector<sensor_base *> get_sensors(sensor_type_t type) Returns a vector of sensor class base objects corresponding to the input sensor type. Vector of sensor_base class object
vector<sensor_base *> get_virtual_sensors(void) Returns vector of sensor class base objects corresponding to any sensor which is a virtual sensor. Vector of sensor_base class object
void show_sensor_info void() Displays the information for each of the loaded sensors such as the sensor name, id,min_range,max_range,vendor,min_interval. NA

Sensor configuration

Example Sensor configuration Interface

Path used for obtaining sensor configuration information: /usr/etc/sensors.xml.

The major components of the interface are:

class csensor_config : public cconfig
{
private:	
        bool load_config(const string& config_path)

public:
        bool is_supported(const string& sensor_type,const string& model_id)
        bool get(const string& sensor_type, const string& model_id, const string& element, double& value)
};
Description of Sensor configuration interface
Prototype Description Return Value
bool load_config(const string& config_path) Loads the configuration for the sensor by parsing the xml file at the location config_path which has the configuration details for the sensor at that location. Success - True

Failure - False

bool is_supported(const string& sensor_type,const string& model_id) Returns true if a particular model (model_id) is supported for the sensor(sensor_type),returns false otherwise. Success - True

Failure - False

bool get(const string& sensor_type, const string& model_id, const string& element, double& value) Gives the supported model id for a sensor of type sensor_type Success - True

Failure - False

Example Virtual Sensor configuration Interface

Path used for obtaining the virtual sensor configuration information: /usr/etc/virtual_sensors.xml.

The major components of the interface are:

class cvirtual_sensor_config : public cconfig
{
private:	
        bool load_config(const string& config_path);

public:
        bool is_supported(const string& sensor_type);
        bool get(const string& sensor_type, const string& element, double& value)
};
Description of Virtual Sensor configuration Interface
Prototype Description Return Value
bool load_config(const string& config_path) Loads the configuration for the virtual sensor by parsing the xml file at the location config_path which has the configuration details for the sensor at that location. Success - True

Failure - False

bool is_supported(const string& sensor_type) Returns true if the device model is supported for the virtual sensor(sensor_type),returns false otherwise. Success - True

Failure - False

bool get(const string& sensor_type, const string& element, double& value) Gives the supported device model for a sensor of type sensor_type Success - True

Failure - False

Command worker

Runs as a separate thread to receive commands from clients such as registering event, unregistering event, setting interval, getting interval, getting data on a socket .Each command uses a separate command handler.

Example Command worker Interface

The major components of the interface are

class command_worker
{ 
private:
       static void init_cmd_handlers(void);     
       bool working(void *ctx);
       bool dispatch_command (int cmd, void* payload);
 
public:
        bool start(void);
};
Description of command worker interface
Prototype Description Return Value
static void init_cmd_handlers(void) Initializes the command handlers depending on their packet type such as command to get sensor list, command to register/unregister an event, command to set/unset and interval. NA
bool working(void *ctx) Receives the size of the header from the input instance of the command worker. Creates a character array payload of size of the header and then receives the command packet into this payload. It then calls the dispatch_command (int cmd,void *payload) function to decode the received command. The type of command information is in the header and the actual command is the payload. Success - True

Failure - False

bool dispatch_command (int cmd, void* payload) Creates a command handler for the input command (cmd) and dispatches the command(payload) to be decoded by the appropriate command handler. Success - True

Failure - False

Command handler

The socket on the sensor framework server receives the command packets from the application and creates a new worker thread for processing the command. The worker thread then calls the command handler which decodes the received command. The acknowledgement for the command packet received on the server is sent back to the application.

Server Information

Client info manager
Example client info manager interface

The major components of the interface are

class cclient_info_manager {
       unsigned int get_interval(int client_id, sensor_id_t sensor_id);
       bool get_registered_events(int client_id, sensor_id_t sensor_id, event_type_vector &event_vec);
       bool get_listener_ids(sensor_id_t sensor_id, unsigned int event_type, client_id_vec &id_vec);
}
Description of client info manager interface
Prototype Description Return Value
unsigned int get_interval(int client_id, sensor_id_t sensor_id) Gives the registered interval for a given client and a particular sensor that the client has registered for. Value of the interval
bool get_registered_events(int client_id, sensor_id_t sensor_id, event_type_vector &event_vec) Gives the registered events for a given client and a particular sensor that client has registered for. Success - True

Failure - False

bool get_listener_ids(sensor_id_t sensor_id, unsigned int event_type, client_id_vec &id_vec) Gives listener ids of all clients listening for a specific event from a specific sensor. Success - True

Failure - False

Server Info
Example Sensor Info interface

The major components of the interface are

class sensor_info {
      void set_name(const char *name);
      void set_vendor(const char *vendor);
      void set_min_range(float min_range);
      void set_max_range(float max_range);
      void set_resolution(float resolution);
      void set_min_interval(int min_interval);
      void set_fifo_count(int fifo_count);
      void set_max_batch_count(int max_batch_count); 
}
Description of Sensor Info interface
Prototype Description Return Value
void set_name(const char *name) Sets information for name of the sensor NA
void set_vendor(const char *vendor) Sets information for vendor name of the sensor NA
void set_min_range(float min_range) Sets information for minimum range of the sensor NA
void set_max_range(float max_range) Sets information for the maximum range of the sensor NA
void set_resolution(float resolution) Sets information for the resolution of the sensor NA
void set_min_interval(int min_interval) Sets information for the minimum interval of the sensor NA
void set_max_batch_count(int max_batch_count) Sets information for the maximum batch count of the sensor NA
Sensor Usage
Example Sensor Usage interface

The major components of the interface are

class csensor_usage {
       bool register_event(unsigned int event_type);
       bool unregister_event(unsigned int event_type;
       bool is_event_registered(unsigned int event_type);
}
Description of Sensor Usage interface
Prototype Description Return Value
bool register_event(unsigned int event_type) Adds the event (event_type) to the list of registered events Success - True

Failure - False

bool unregister_event(unsigned int event_type) removes the event (event_type) from the list of registered events Success - True

Failure - False

bool is_event_registered(unsigned int event_type); Returns true if the event (event_type) is already registered, false otherwise Success - True

Failure - False

Event dispatcher

It dispatches the event popped from the event queue to clients using client-event registration information stored in the server block to the listener ids listening for that event.

Example Event dispatcher Interface

The major components of the interface are

class csensor_event_dispatcher
{
private:
       void accept_connections(void);
       void dispatch_event(void);
       void send_sensor_events(void* events, int event_cnt, bool is_hub_event);

public:
        bool run(void);
};
Description of Event dispatcher interface
Prototype Description Return Value
void accept_connections(void) Accepts incoming connections from clients to receive events. NA
void dispatch_event() It pops the event to be dispatched from the event queue .

Then it calls the send_sensor_events() function.

NA
void send_sensor_events (void *events, int event_cnt, bool is_hub_event) Based on information stored in client info manager it gets the list of the listener ids that have been created for receiving that particular event and uses it to send the event data through the corresponding sockets to each client. NA
bool run(void) It creates the socket, binds it to the event channel path and listens for connections from clients to dispatch events. Success - True

Failure - False

Event queue

The data read from the device driver using the plugin layer is pushed up the event queue. This is the common event queue for all sensors .In case of virtual sensors it is possible to prioritize events coming from physical sensors that are being used by that virtual sensor. Events to be prioritized are put in a priority list when event registration occurs on server side.

Example Event queue Interface

The major components of the interface are

class csensor_event_queue
{
private:	
        void push_internal(void *event);
public:
        void* pop(void);
};
Description of Event queue interface
Prototype Description Return Value
void push_internal(void *event) Pushes the event into the event queue if the queue size is less than it’s full capacity,else it drops the event. NA
void* pop(void) Pops the top event from the event queue. NA

Sensor Plugins

Sensor plugins which are interfaced to the sensor server take care of interacting with the sensor drivers. Plugins process the data from the sensor drivers and communicate it to the server. Hardware sensors have to support three interfaces namely sensor_base, physical_sensor and sensor_hal. Virtual sensors have to support two interfaces namely sensor_base and virtual_sensor.

(For more information please refer to the sensor porting guide below)

Sensor Porting Guide

Adding New Hardware Sensors

For porting new hardware sensors, the sensor_base interface, the physical_sensor interface and the sensor_hal interface have to be implemented.

Interface of sensor_base

The sensor_base interface provides the following functionality:

  • connect the sensor plugin to the sensor server
  • passes on configuration and control information from server to sensor_hal
  • receives raw sensor data from sensor_hal and sends to server
  • further processing of raw sensor data to generate sensor events
class sensor_base
{
private:
	typedef unordered_map<unsigned int, unsigned int> client_info;

public:
	sensor_base();
	virtual ~sensor_base();

	virtual bool init(void);
	void set_id(sensor_id_t id);
	sensor_id_t get_id(void);
	virtual sensor_type_t get_type(void);
	sensor_privilege_t get_privilege(void);
	int get_permission(void);
	virtual const char* get_name(void);
	virtual bool is_virtual(void);

	bool start(void);
	bool stop(void);
	bool is_started(void);

	virtual bool add_client(unsigned int event_type);
	virtual bool delete_client(unsigned int event_type);

	virtual bool add_interval(int client_id, unsigned int interval, bool is_processor);
	virtual bool delete_interval(int client_id, bool is_processor);
	unsigned int get_interval(int client_id, bool is_processor);


	void get_sensor_info(sensor_info &info);
	virtual bool get_properties(sensor_properties_s &properties);
	bool is_supported(unsigned int event_type);

	virtual long set_command(unsigned int cmd, long value);
	virtual int send_sensorhub_data(const char* data, int data_len);

	virtual int get_sensor_data(unsigned int type, sensor_data_t &data);

	void register_supported_event(unsigned int event_type);
protected:
	typedef lock_guard<mutex> lock;
	typedef lock_guard<recursive_mutex> rlock;
	typedef unique_lock<mutex> ulock;

	sensor_id_t m_id;
	sensor_privilege_t m_privilege;
	int m_permission;

	cinterval_info_list m_interval_info_list;
	cmutex m_interval_info_list_mutex;

	cmutex m_mutex;

	unsigned int m_client;
	cmutex m_client_mutex;

	client_info m_client_info;
	cmutex m_client_info_mutex;

	vector<unsigned int> m_supported_event_info;

	bool m_started;

	string m_name;

	void set_privilege(sensor_privilege_t privilege);
	void set_permission(int permission);
	unsigned int get_client_cnt(unsigned int event_type);
	virtual bool set_interval(unsigned long val);

	static unsigned long long get_timestamp(void);
	static unsigned long long get_timestamp(timeval *t);
private:
	virtual bool on_start(void);
	virtual bool on_stop(void);
};
Example sensor_base interface for Accelerometer
#ifndef _ACCEL_SENSOR_H_
#define _ACCEL_SENSOR_H_

#include <sensor_common.h>

#include <physical_sensor.h>
#include <sensor_hal.h>

class accel_sensor : public physical_sensor {
public:
	accel_sensor();
	virtual ~accel_sensor();

	bool init();
	virtual sensor_type_t get_type(void);

	static bool working(void *inst);
	virtual bool set_interval(unsigned long interval);
	virtual bool get_properties(sensor_properties_s &properties);
	virtual int get_sensor_data(unsigned int type, sensor_data_t &data);
private:
	sensor_hal *m_sensor_hal;
	cmutex m_value_mutex;

	float m_raw_data_unit;

	unsigned long m_interval;

	virtual bool on_start(void);
	virtual bool on_stop(void);

	void raw_to_base(sensor_data_t &data);
        bool process_event(void);
};
#endif
Description of sensor_base interface
Prototype Description Return Value
accel_sensor() Constructor, initializes all privite variables

Assigns sensor name to m_name

Uses sensor_base::register_supported_event(event) for registering event_type

Uses physical_sensor::set_poller(cb, this), if it is derived from class physical_sensor.

NA
virtual ~ accel_sensor() Destructor, deallocate variables NA
bool init() Initializes the accel sensor by using sensor_plugin_loader::get_instance() and sensor_plugin_loader::get_sensor_hal() Success - True

Failure - False

sensor_type_t get_type) Returns the type of sensor from enum sensor_type_t

In case it is new sensor and there is no type in sensord, please return UNKNOWN_SENSOR.

Return sensor_type_t
bool working(void *inst) Gets sensor event data and pushes the event

Calls push(event)(in physical sensor) to deliver an event to the sensor daemon.

[If it is derived from physical sensor, this function can be written in internal thread loop.] [refer to physical_sensor::set_poller()]

Success - True

Failure - False

bool on_start(void) Enables the sensor [calls m_sensor_hal->enable()] Success - True

Failure - False

bool on_stop(void) Disables the sensor [calls m_sensor_hal->disable()] Success - True

Failure - False

bool set_interval(unsigned long interval) Sets the interval

Uses sensor_hal::set_interval(value) to set the interval

Success - True

Failure - False

bool get_properties(sensor_properties_s &properties) Updates the sensor properties in the sensor_properties_s struct (&properties) Success - True

Failure - False

bool get_sensor_data(unsigned int type, sensor_data_t &data) Updates the sensor data in the sensor_data_t struct (&data) Success - True

Failure - False

extern "C" sensor_module* create(void) You MUST write this interface for creating sensor module in sensord Success- sensor module instance
Example sensor_base implementation for Accelerometer
	
#include <common.h>
#include <sf_common.h>

#include <accel_sensor.h>
#include <sensor_plugin_loader.h>
#include <algorithm>

#define GRAVITY 9.80665
#define G_TO_MG 1000

#define RAW_DATA_TO_G_UNIT(X) (((float)(X))/((float)G_TO_MG))
#define RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(X) (GRAVITY * (RAW_DATA_TO_G_UNIT(X)))

#define SENSOR_NAME "ACCELEROMETER_SENSOR"

accel_sensor::accel_sensor()
: m_sensor_hal(NULL)
, m_interval(POLL_1HZ_MS)
{
        /* m_name should be allocated. */
	m_name = string(SENSOR_NAME);

        /* event should be registered. event should be registered in sensord */
        register_supported_event(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME);

	physical_sensor::set_poller(accel_sensor::working, this);
}

accel_sensor::~accel_sensor()
{
	INFO("accel_sensor is destroyed!\n");
}

bool accel_sensor::init()
{
        /* sensor_hal class is for abstracting hardware */
	m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(ACCELEROMETER_SENSOR);

	if (!m_sensor_hal) {
		ERR("cannot load sensor_hal[%s]", sensor_base::get_name());
		return false;
	}

	sensor_properties_s properties;

	if (m_sensor_hal->get_properties(properties) == false) {
		ERR("sensor->get_properties() is failed!\n");
		return false;
	}

	m_raw_data_unit = properties.resolution / GRAVITY * G_TO_MG;

	INFO("m_raw_data_unit accel : [%f]\n", m_raw_data_unit);

	INFO("%s is created!\n", sensor_base::get_name());
	return true;
}

sensor_type_t accel_sensor::get_type(void)
{
	return ACCELEROMETER_SENSOR;
}

bool accel_sensor::working(void *inst)
{
	accel_sensor *sensor = (accel_sensor*)inst;
	return sensor->process_event();
}

bool accel_sensor::process_event(void)
{
	sensor_event_t base_event;

	if (!m_sensor_hal->is_data_ready(true))
		return true;

	m_sensor_hal->get_sensor_data(base_event.data);

	AUTOLOCK(m_mutex);
	AUTOLOCK(m_client_info_mutex);

	if (get_client_cnt(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME)) {
		base_event.sensor_id = get_id();
		base_event.event_type = ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME;
		raw_to_base(base_event.data);

                /* push() MUST be called in order to deliver a sensor event*/
		push(base_event);
	}

	return true;
}

bool accel_sensor::on_start(void)
{
        /* enable sensor hardware */
	if (!m_sensor_hal->enable()) {
		ERR("m_sensor_hal start fail\n");
		return false;
	}
        /* start_poll() starts a thread in physical sensor */
	return start_poll();
}

bool accel_sensor::on_stop(void)
{
        /* disable sensor hardware */
	if (!m_sensor_hal->disable()) {
		ERR("m_sensor_hal stop fail\n");
		return false;
	}
        /* stop_poll() stops a thread in physical sensor */
	return stop_poll();
}

bool accel_sensor::get_properties(sensor_properties_s &properties)
{
        /* fill properties */
	return m_sensor_hal->get_properties(properties);
}

int accel_sensor::get_sensor_data(unsigned int type, sensor_data_t &data)
{
	if (m_sensor_hal->get_sensor_data(data) < 0) {
		ERR("Failed to get sensor data");
		return -1;
	}

	if (type == ACCELEROMETER_BASE_DATA_SET)
                return -1;

	raw_to_base(data);
	return 0;
}

bool accel_sensor::set_interval(unsigned long interval)
{
	AUTOLOCK(m_mutex);

	m_interval = interval;

	INFO("Polling interval is set to %dms", interval);

	return m_sensor_hal->set_interval(interval);
}

void accel_sensor::raw_to_base(sensor_data_t &data)
{
	data.value_count = 3;
	data.values[0] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data.values[0] * m_raw_data_unit);
	data.values[1] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data.values[1] * m_raw_data_unit);
	data.values[2] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data.values[2] * m_raw_data_unit);
}

extern "C" sensor_module* create(void)
{
	accel_sensor *sensor;

	try {
		sensor = new(std::nothrow) accel_sensor;
	} catch (int err) {
		ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
		return NULL;
	}

	sensor_module *module = new(std::nothrow) sensor_module;
	retvm_if(!module || !sensor, NULL, "Failed to allocate memory");

	module->sensors.push_back(sensor);
	return module;
}
//! End of a file

Interface of physical_sensor

The physical_sensor interface provides the following functionality:

  • initializes plugin polling thread for getting sensor data from driver
  • pushes sensor event from the plugin to the server event queue.
#ifndef _PHYSICAL_SENSOR_H_
#define _PHYSICAL_SENSOR_H_

#include <sensor_base.h>
#include <sf_common.h>
#include <worker_thread.h>

class physical_sensor : public sensor_base
{
public:
	typedef worker_thread::trans_func_t working_func_t;

private:
	worker_thread m_sensor_data_poller;

protected:
	physical_sensor();
	virtual ~physical_sensor();

	bool push(sensor_event_t const &event);
	bool push(sensorhub_event_t const &event);

	void set_poller(working_func_t func, void *arg);
	bool start_poll(void);
	bool stop_poll(void);
};

Interface of sensor_hal

The sensor_hal interface connects with the sensor_base interface and provides the following functionality:

  • configuration of the sensor drivers
  • read raw sensor data from the sensor driver
  • control of the sensors through the driver
class sensor_hal
{
public:
	sensor_hal();
	virtual ~sensor_hal();

	virtual bool init(void *data = NULL);
	virtual string get_model_id(void) = 0;
	virtual sensor_type_t get_type(void) = 0;
	virtual bool enable(void) = 0;
	virtual bool disable(void) = 0;
	virtual bool set_interval(unsigned long val);
	virtual bool is_data_ready(bool wait) = 0;
	virtual bool get_properties(sensor_properties_s &properties) = 0;
	virtual int get_sensor_data(sensor_data_t &data);
	virtual int get_sensor_data(sensorhub_data_t &data);
	virtual long set_command(unsigned int cmd, long val);
	virtual int send_sensorhub_data(const char *data, int data_len);

protected:
	cmutex m_mutex;
	static cmutex m_shared_mutex;

	virtual bool set_enable_node(const string &node_path, bool sensorhub_controlled, bool enable, int enable_bit = 0);

	static unsigned long long get_timestamp(void);
	static unsigned long long get_timestamp(timeval *t);
	static bool find_model_id(const string &sensor_type, string &model_id);
	static bool is_sensorhub_controlled(const string &key);
	static bool get_node_info(const node_info_query &query, node_info &info);
	static void show_node_info(node_info &info);
	static bool set_node_value(const string &node_path, int value);
	static bool set_node_value(const string &node_path, unsigned long long value);
	static bool get_node_value(const string &node_path, int &value);
private:
	static bool get_event_num(const string &node_path, string &event_num);
	static bool get_input_method(const string &key, int &method, string &device_num);

	static bool get_iio_node_info(const string& enable_node_name, const string& device_num, node_info &info);
	static bool get_sensorhub_iio_node_info(const string &interval_node_name, const string& device_num, node_info &info);
	static bool get_input_event_node_info(const string& device_num, node_info &info);
	static bool get_sensorhub_input_event_node_info(const string &interval_node_name, const string& device_num, node_info &info);
};
Example sensor_hal interface for Accelerometer
#ifndef _ACCEL_SENSOR_HAL_H_
#define _ACCEL_SENSOR_HAL_H_

#include <sensor_hal.h>
#include <string>
#include <functional>

using std::string;

class accel_sensor_hal : public sensor_hal
{
public:
	accel_sensor_hal();
	virtual ~accel_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_s &properties);

private:
	int m_x;
	int m_y;
	int m_z;
	int m_node_handle;
	unsigned long m_polling_interval;
	unsigned long long m_fired_time;

	string m_model_id;
	string m_vendor;
	string m_chip_name;

	int m_resolution;
	float m_raw_data_unit;

	int m_method;
	string m_data_node;
	string m_enable_node;
	string m_interval_node;

	std::function<bool (bool)> update_value;

	bool m_sensorhub_controlled;

	cmutex m_value_mutex;

	bool update_value_input_event(bool wait);
};
#endif /*_ACCEL_SENSOR_HAL_CLASS_H_*/
Description of sensor_hal interface
Prototype Description Return Value
accel_sensor_hal() constructor, initializes all privite variables

Variables m_x, m_y, m_z store the acceleration values coming from the sensor

Variable m_node_handle stores the file descriptor from which the event inputs are read

Varaible m_polling_interval and m_fired_time store the polling interval and event timestamp respectively.

Uses sensor_hal::find_model_id(sensor_type, &model_id) for getting model_id

Uses sensor_hal::get_node_info(&query, &info) for getting node_info.

Uses csensor_config::get(...) for getting the element info for the sensor

Uses update_value_input_event(wait) for updating the input values from the sensor

NA
virtual ~accel_sensor_hal() Destructor, deallocates all variables

Uses close(handle) to close the handle (from which the events are read) for the sensor.

NA
string get_model_id(void) Returns the model id of the sensor Returns m_model_id
sensor_type_t get_type(void) Returns the type of sensor from enum sensor_type_t

In case it is new sensor and there is no type in sensord, please return UNKNOWN_SENSOR.

Return sensor_type_t
bool enable(void) Enables the Sensor by setting the enable bit to 1

Uses sensor_hal::set_enable_node(node_path, ...) to set thecorresponding enable bit for the sensor to 1

Uses accel_sensor_hal::set_interval(interval) to set polling interval

Success- True

Failure-False

bool disable(void) Disables the Sensor by setting the enable bit to 0

Uses sensor_hal::set_enable_node(node_path, ...) to set thecorresponding enable bit for the sensor to 0

Success- True

Failure-False

bool set_interval(unsigned long val) Sets the polling interval

Uses sensor_hal::set_node_value(node_path, value) to set the polling interval

Success- True

Failure-False

bool update_value_input_event(bool wait) Updates the values of the accel_sensor_hal with the input event

Reads for input from the node_handle, parses it and updates the appropriate private variables in the accel_sensor_hal

Updates the timestamp with the timestamp of the input event

Uses read(filedes, buffer, sizeof(buffer)) to read the input event from the sensor node_handle

Success- True

Failure-False

bool is_data_ready(bool wait) Calls accel_sensor_hal::update_value_input_event to find out if the data from event is ready or not

update_value_input_event(wait) updates the private variable of the accel_sensor_hal as per the input event.

Success- True

Failure-False

virtual int get_sensor_data(sensor_data_t &data) Updates the sensor_data_t object (data) with the details about the sensor

(accuracy, timestamp, values)

Success- 0
bool get_properties(sensor_properties_s &properties) Updates the sensor_properties_s object (properties) with the appropriate properties of the sensor.

(name, vendor, min_range, max_range, min_interval, resolution, fifo_count, max_batch_count)

Success- True
extern "C" sensor_module* create(void) You MUST write this interface for creating sensor module in sensord Success- sensor module instance
Example sensor_hal implementation for Accelerometer
#include <fcntl.h>
#include <sys/stat.h>
#include <linux/input.h>
#include <csensor_config.h>
#include <accel_sensor_hal.h>
#include <sys/poll.h>

using std::ifstream;

#define GRAVITY 9.80665
#define G_TO_MG 1000
#define RAW_DATA_TO_G_UNIT(X) (((float)(X))/((float)G_TO_MG))
#define RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(X) (GRAVITY * (RAW_DATA_TO_G_UNIT(X)))

#define MIN_RANGE(RES) (-((1 << (RES))/2))
#define MAX_RANGE(RES) (((1 << (RES))/2)-1)

#define SENSOR_TYPE_ACCEL		"ACCEL"
#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 INPUT_NAME	"accelerometer_sensor"
#define ACCEL_SENSORHUB_POLL_NODE_NAME "accel_poll_delay"

accel_sensor_hal::accel_sensor_hal()
: m_x(-1)
, m_y(-1)
, m_z(-1)
, m_node_handle(-1)
, m_polling_interval(POLL_1HZ_MS)
, m_fired_time(0)
{
	const string sensorhub_interval_node_name = "accel_poll_delay";
	csensor_config &config = csensor_config::get_instance();

	node_info_query query;
	node_info info;

	if (!find_model_id(SENSOR_TYPE_ACCEL, m_model_id)) {
		ERR("Failed to find model id");
		throw ENXIO;
	}

	query.sensorhub_controlled = m_sensorhub_controlled = is_sensorhub_controlled(sensorhub_interval_node_name);
	query.sensor_type = SENSOR_TYPE_ACCEL;
	query.key = "accelerometer_sensor";
	query.iio_enable_node_name = "accel_enable";
	query.sensorhub_interval_node_name = sensorhub_interval_node_name;

	if (!get_node_info(query, info)) {
		ERR("Failed to get node info");
		throw ENXIO;
	}

	show_node_info(info);

	m_method = info.method;
	m_data_node = info.data_node_path;
	m_enable_node = info.enable_node_path;
	m_interval_node = info.interval_node_path;

	if (!config.get(SENSOR_TYPE_ACCEL, 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_ACCEL, m_model_id, ELEMENT_NAME, m_chip_name)) {
		ERR("[NAME] is empty\n");
		throw ENXIO;
	}

	INFO("m_chip_name = %s\n",m_chip_name.c_str());

	long resolution;

	if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RESOLUTION, resolution)) {
		ERR("[RESOLUTION] is empty\n");
		throw ENXIO;
	}

	m_resolution = (int)resolution;

	INFO("m_resolution = %d\n",m_resolution);

	double raw_data_unit;

	if (!config.get(SENSOR_TYPE_ACCEL, 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_raw_data_unit = %f\n", m_raw_data_unit);

	if ((m_node_handle = open(m_data_node.c_str(), O_RDWR)) < 0) {
		ERR("accel handle open fail for accel processor, error:%s\n", strerror(errno));
		throw ENXIO;
	}

	if (m_method == INPUT_EVENT_METHOD) {
		int clockId = CLOCK_MONOTONIC;
		if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0)
			ERR("Fail to set monotonic timestamp for %s", m_data_node.c_str());

		update_value = [=](bool wait) {
			return this->update_value_input_event(wait);
		};
	} else {
		if (!info.buffer_length_node_path.empty())
			set_node_value(info.buffer_length_node_path, 480);

		if (!info.buffer_enable_node_path.empty())
			set_node_value(info.buffer_enable_node_path, 1);

		update_value = [=](bool wait) {
			return this->update_value_iio(wait);
		};
	}

	INFO("accel_sensor is created!\n");
}

accel_sensor_hal::~accel_sensor_hal()
{
	close(m_node_handle);
	m_node_handle = -1;

	INFO("accel_sensor is destroyed!\n");
}

string accel_sensor_hal::get_model_id(void)
{
	return m_model_id;
}

sensor_type_t accel_sensor_hal::get_type(void)
{
	return ACCELEROMETER_SENSOR;
}

bool accel_sensor_hal::enable(void)
{
	AUTOLOCK(m_mutex);

	set_enable_node(m_enable_node, m_sensorhub_controlled, true, SENSORHUB_ACCELEROMETER_ENABLE_BIT);
	set_interval(m_polling_interval);

	m_fired_time = 0;
	INFO("Accel sensor real starting");
	return true;
}

bool accel_sensor_hal::disable(void)
{
	AUTOLOCK(m_mutex);

	set_enable_node(m_enable_node, m_sensorhub_controlled, false, SENSORHUB_ACCELEROMETER_ENABLE_BIT);

	INFO("Accel sensor real stopping");
	return true;
}

bool accel_sensor_hal::set_interval(unsigned long val)
{
	unsigned long long polling_interval_ns;

	AUTOLOCK(m_mutex);

	polling_interval_ns = ((unsigned long long)(val) * 1000llu * 1000llu);

	if (!set_node_value(m_interval_node, polling_interval_ns)) {
		ERR("Failed to set polling resource: %s\n", m_interval_node.c_str());
		return false;
	}

	INFO("Interval is changed from %dms to %dms]", m_polling_interval, val);
	m_polling_interval = val;
	return true;
}


bool accel_sensor_hal::update_value_input_event(bool wait)
{
	int accel_raw[3] = {0,};
	bool x,y,z;
	int read_input_cnt = 0;
	const int INPUT_MAX_BEFORE_SYN = 10;
	unsigned long long fired_time = 0;
	bool syn = false;

	x = y = z = false;

	struct input_event accel_input;
	DBG("accel event detection!");

	while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) {
		int len = read(m_node_handle, &accel_input, sizeof(accel_input));
		if (len != sizeof(accel_input)) {
			ERR("accel_file read fail, read_len = %d\n",len);
			return false;
		}

		++read_input_cnt;

		if (accel_input.type == EV_REL) {
			switch (accel_input.code) {
			case REL_X:
				accel_raw[0] = (int)accel_input.value;
				x = true;
				break;
			case REL_Y:
				accel_raw[1] = (int)accel_input.value;
				y = true;
				break;
			case REL_Z:
				accel_raw[2] = (int)accel_input.value;
				z = true;
				break;
			default:
				ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
				return false;
				break;
			}
		} else if (accel_input.type == EV_SYN) {
			syn = true;
			fired_time = sensor_hal::get_timestamp(&accel_input.time);
		} else {
			ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code);
			return false;
		}
	}

	if (syn == false) {
		ERR("EV_SYN didn't come until %d inputs had come", read_input_cnt);
		return false;
	}

	AUTOLOCK(m_value_mutex);

	if (x)
		m_x =  accel_raw[0];
	if (y)
		m_y =  accel_raw[1];
	if (z)
		m_z =  accel_raw[2];

	m_fired_time = fired_time;

	DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time);

	return true;
}

bool accel_sensor_hal::is_data_ready(bool wait)
{
	bool ret;
	ret = update_value(wait);
	return ret;
}

int accel_sensor_hal::get_sensor_data(sensor_data_t &data)
{
	AUTOLOCK(m_value_mutex);

	data.accuracy = SENSOR_ACCURACY_GOOD;
	data.timestamp = m_fired_time;
	data.value_count = 3;
	data.values[0] = m_x;
	data.values[1] = m_y;
	data.values[2] = m_z;

	return 0;
}

bool accel_sensor_hal::get_properties(sensor_properties_s &properties)
{
	properties.name = m_chip_name;
	properties.vendor = m_vendor;
	properties.min_range = MIN_RANGE(m_resolution)* RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
	properties.max_range = MAX_RANGE(m_resolution)* RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
	properties.min_interval = 1;
	properties.resolution = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit);
	properties.fifo_count = 0;
	properties.max_batch_count = 0;
	return true;
}

extern "C" sensor_module* create(void)
{
	accel_sensor_hal *sensor;

	try {
		sensor = new(std::nothrow) accel_sensor_hal;
	} catch (int err) {
		ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
		return NULL;
	}

	sensor_module *module = new(std::nothrow) sensor_module;
	retvm_if(!module || !sensor, NULL, "Failed to allocate memory");

	module->sensors.push_back(sensor);
	return module;
}

Adding New Virtual Sensors

Virtual sensors are derived from one or more hardware sensors. New virtual sensors have to implement the virtual_sensor and sensor_base interface.

Interface of sensor_base

The sensor_base interface is the same as the explanation given for hardware sensors in the previous section.

Interface of virtual_sensor

The virtual_sensor interface provides functionality to synthesize virtual sensor events based on sensor events received from hardware sensors.

#ifndef _VIRTUAL_SENSOR_H_
#define _VIRTUAL_SENSOR_H_

#include <sensor_base.h>

class virtual_sensor : public sensor_base
{
public:
	virtual_sensor();
	virtual ~virtual_sensor();

	virtual void synthesize(const sensor_event_t &event, vector<sensor_event_t> &outs) = 0;
	virtual int get_sensor_data(const unsigned int event_type, sensor_data_t &data) = 0;
	bool is_virtual(void);

protected:
	cmutex m_fusion_mutex;

	bool activate(void);
	bool deactivate(void);

	bool push(sensor_event_t const &event);
};

#endif
Example virtual_sensor interface for Orientation Sensor
#ifndef _ORIENTATION_SENSOR_H_
#define _ORIENTATION_SENSOR_H_

#include <sensor_internal.h>
#include <virtual_sensor.h>
#include <orientation_filter.h>

class orientation_sensor : public virtual_sensor {
public:
	orientation_sensor();
	virtual ~orientation_sensor();

	bool init(void);

	void synthesize(const sensor_event_t &event, vector<sensor_event_t> &outs);

	bool add_interval(int client_id, unsigned int interval);
	bool delete_interval(int client_id);
	bool get_properties(sensor_properties_s &properties);
	sensor_type_t get_type(void);

	int get_sensor_data(const unsigned int data_id, sensor_data_t &data);

private:
	sensor_base *m_accel_sensor;
	sensor_base *m_gyro_sensor;
	sensor_base *m_magnetic_sensor;

	sensor_data<float> m_accel;
	sensor_data<float> m_gyro;
	sensor_data<float> m_magnetic;

	cmutex m_value_mutex;

	orientation_filter<float> m_orientation;

	unsigned int m_enable_orientation;

	float m_roll;
	float m_pitch;
	float m_azimuth;
	unsigned long long m_time;
	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
Description of virtual_sensor interface
Prototype Description Return Value
orientation_sensor() constructor, initializes all privite variables

Variables m_accel_sensor, m_gyro_sensor, m_magnetic_sensor store the input event values coming from the sensors

Uses sensor_base::register_supported_event(event) to register the event type

Uses csensor_config::get(...) for getting the element info for the sensors

NA
virtual ~orientation_sensor() Destructor, deallocates all variables NA
bool init(void) Initializes the orientation_sensor by initializing the m_accel_sensor, m_gyro_sensor and m_magnetic_sensor

Uses sensor_pluging_loader::get_instance() and sensor_plugin_loader::get_sensor() to get istances of all three sensors.

Success - true

Failure - false

sensor_type_t get_type(void) Returns the type of sensor from enum sensor_type_t

In case it is new sensor and there is no type in sensord, please return UNKNOWN_SENSOR.

Return sensor_type_t
bool on_start(void) Adds clients and intervals for all the sensors used in the virtual sensor.

(In this case accel, gyro and magnetic.)

Starts all three sensors. calls virtual_sensor::activate() for current virtual sensor.

Success- True
bool on_stop(void) Removes clients and intervals for all the sensors used in the virtual sensor.

(In this case accel, gyro and magnetic.)

Stops all three sensors. calls virtual_sensor::deactivate() for current virtual sensor.

Success- True
bool add_interval(int client_id, unsigned int interval) Adds interval for all the sensors (used in this virtual sensor) for the given client_id. Success- True

Failure - False

bool delete_interval(int client_id, unsigned int interval) Deletes interval for all the sensors (used in this virtual sensor) for the given client_id. Success- True

Failure - False

void synthesize(const sensor_event_t &event, vector<sensor_event_t> &outs) Uses the input events for the physical sensors (used in the current virtual sensor) to synthesize an input event for this virtual sensor (orientation).

Reads the input events from the relevant sensor_event, updates the corresponding values in the private vairables.

Using the updated values, creates an input event for orientation virtual sensor.

Pushes the orientation event [calls push(orienation_event)] for all clients listening for orientation sensor events.

NA
int get_sensor_data(const unsigned int event_type, sensor_data_t &data) Using data from the accelerometer, gyro and magnetic sensors updates the sensor_data_t struct (&data) Success- 0
bool get_properties(sensor_properties_s &properties) Updates the sensor_properties_s object (&properties) with the details about the sensor

(resolution, vendor, min_range, max_range, name, min_interval, fifo_count, batch_count)

Success- true
extern "C" sensor_module* create(void) You MUST write this interface for creating sensor module in sensord Success- sensor module instance
Example virtual_sensor implementation for Orientation Sensor
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <time.h>
#include <sys/types.h>
#include <dlfcn.h>
#include <common.h>
#include <sf_common.h>
#include <orientation_sensor.h>
#include <sensor_plugin_loader.h>
#include <orientation_filter.h>
#include <cvirtual_sensor_config.h>

#define SENSOR_NAME                     "ORIENTATION_SENSOR"
#define SENSOR_TYPE_ORIENTATION		"ORIENTATION"

#define ACCELEROMETER_ENABLED 0x01
#define GYROSCOPE_ENABLED 0x02
#define GEOMAGNETIC_ENABLED 0x04
#define ORIENTATION_ENABLED 7

#define INITIAL_VALUE -1

#define MS_TO_US 1000
#define MIN_DELIVERY_DIFF_FACTOR 0.75f

#define PI 3.141593
#define AZIMUTH_OFFSET_DEGREES 360
#define AZIMUTH_OFFSET_RADIANS (2 * PI)

#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<float> &data_out, const float *data_in, float *bias, int *sign, float scale)
{
	data_out.m_data.m_vec[0] = sign[0] * (data_in[0] - bias[0]) / scale;
	data_out.m_data.m_vec[1] = sign[1] * (data_in[1] - bias[1]) / scale;
	data_out.m_data.m_vec[2] = sign[2] * (data_in[2] - bias[2]) / scale;
}

orientation_sensor::orientation_sensor()
: m_accel_sensor(NULL)
, m_gyro_sensor(NULL)
, m_magnetic_sensor(NULL)
, m_roll(INITIAL_VALUE)
, m_pitch(INITIAL_VALUE)
, m_azimuth(INITIAL_VALUE)
, m_time(0)
{
	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_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()
{
	INFO("orientation_sensor is destroyed!\n");
}

bool orientation_sensor::init(void)
{
	m_accel_sensor = sensor_plugin_loader::get_instance().get_sensor(ACCELEROMETER_SENSOR);
	m_gyro_sensor = sensor_plugin_loader::get_instance().get_sensor(GYROSCOPE_SENSOR);
	m_magnetic_sensor = sensor_plugin_loader::get_instance().get_sensor(GEOMAGNETIC_SENSOR);

	if (!m_accel_sensor || !m_gyro_sensor || !m_magnetic_sensor) {
		ERR("Failed to load sensors,  accel: 0x%x, gyro: 0x%x, mag: 0x%x",
			m_accel_sensor, m_gyro_sensor, m_magnetic_sensor);
		return false;
	}

	INFO("%s is created!", sensor_base::get_name());
	return true;
}

sensor_type_t orientation_sensor::get_type(void)
{
	return ORIENTATION_SENSOR;
}

bool orientation_sensor::on_start(void)
{
	AUTOLOCK(m_mutex);

	m_accel_sensor->add_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME);
	m_accel_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
	m_accel_sensor->start();
	m_gyro_sensor->add_client(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME);
	m_gyro_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
	m_gyro_sensor->start();
	m_magnetic_sensor->add_client(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME);
	m_magnetic_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
	m_magnetic_sensor->start();

	activate();
	return true;
}

bool orientation_sensor::on_stop(void)
{
	AUTOLOCK(m_mutex);

	m_accel_sensor->delete_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME);
	m_accel_sensor->delete_interval((intptr_t)this, false);
	m_accel_sensor->stop();
	m_gyro_sensor->delete_client(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME);
	m_gyro_sensor->delete_interval((intptr_t)this, false);
	m_gyro_sensor->stop();
	m_magnetic_sensor->delete_client(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME);
	m_magnetic_sensor->delete_interval((intptr_t)this, false);
	m_magnetic_sensor->stop();

	deactivate();
	return true;
}

bool orientation_sensor::add_interval(int client_id, unsigned int interval)
{
	AUTOLOCK(m_mutex);

	m_accel_sensor->add_interval(client_id, interval, false);
	m_gyro_sensor->add_interval(client_id, interval, false);
	m_magnetic_sensor->add_interval(client_id, interval, false);

	return sensor_base::add_interval(client_id, interval, false);
}

bool orientation_sensor::delete_interval(int client_id)
{
	AUTOLOCK(m_mutex);

	m_accel_sensor->delete_interval(client_id, false);
	m_gyro_sensor->delete_interval(client_id, false);
	m_magnetic_sensor->delete_interval(client_id, false);

	return sensor_base::delete_interval(client_id, false);
}

void orientation_sensor::synthesize(const sensor_event_t &event, vector<sensor_event_t> &outs)
{
	unsigned long long diff_time;

	sensor_event_t orientation_event;
	euler_angles<float> euler_orientation;
	float azimuth_offset;

	if (event.event_type == ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME) {
		diff_time = event.data.timestamp - m_time;

		if (m_time && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR))
			return;

		pre_process_data(m_accel, event.data.values, m_accel_static_bias, m_accel_rotation_direction_compensation, m_accel_scale);

		m_accel.m_time_stamp = event.data.timestamp;

		m_enable_orientation |= ACCELEROMETER_ENABLED;
	}
	else if (event.event_type == GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME) {
		diff_time = event.data.timestamp - m_time;

		if (m_time && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR))
			return;

		pre_process_data(m_gyro, event.data.values, m_gyro_static_bias, m_gyro_rotation_direction_compensation, m_gyro_scale);

		m_gyro.m_time_stamp = event.data.timestamp;

		m_enable_orientation |= GYROSCOPE_ENABLED;
	}
	else if (event.event_type == GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME) {
		diff_time = event.data.timestamp - m_time;

		if (m_time && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR))
			return;

		pre_process_data(m_magnetic, event.data.values, m_geomagnetic_static_bias, m_geomagnetic_rotation_direction_compensation, m_geomagnetic_scale);

		m_magnetic.m_time_stamp = event.data.timestamp;

		m_enable_orientation |= GEOMAGNETIC_ENABLED;
	}

	if (m_enable_orientation == ORIENTATION_ENABLED) {
		m_enable_orientation = 0;

		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;

		{
			AUTOLOCK(m_fusion_mutex);
			euler_orientation = m_orientation.get_orientation(m_accel, m_gyro, m_magnetic);
		}

		if(m_raw_data_unit == "DEGREES") {
			euler_orientation = rad2deg(euler_orientation);
			azimuth_offset = AZIMUTH_OFFSET_DEGREES;
		}
		else {
			azimuth_offset = AZIMUTH_OFFSET_RADIANS;
		}

		orientation_event.sensor_id = get_id();
		orientation_event.event_type = ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME;
		orientation_event.data.accuracy = SENSOR_ACCURACY_GOOD;
		orientation_event.data.timestamp = get_timestamp();
		orientation_event.data.value_count = 3;
		orientation_event.data.values[1] = euler_orientation.m_ang.m_vec[0];
		orientation_event.data.values[2] = euler_orientation.m_ang.m_vec[1];
		if (euler_orientation.m_ang.m_vec[2] >= 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;

		{
			AUTOLOCK(m_value_mutex);
			m_time = orientation_event.data.timestamp;
			m_azimuth = orientation_event.data.values[0];
			m_pitch = orientation_event.data.values[1];
			m_roll = orientation_event.data.values[2];
		}

		push(orientation_event);
	}

	return;
}

int orientation_sensor::get_sensor_data(const unsigned int event_type, sensor_data_t &data)
{
	sensor_data<float> accel;
	sensor_data<float> gyro;
	sensor_data<float> magnetic;

	sensor_data_t accel_data;
	sensor_data_t gyro_data;
	sensor_data_t magnetic_data;

	euler_angles<float> euler_orientation;
	float azimuth_offset;

	if (event_type != ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME)
		return -1;

	m_accel_sensor->get_sensor_data(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME, accel_data);
	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, 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 = 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;

	{
		AUTOLOCK(m_fusion_mutex);
		euler_orientation = m_orientation.get_orientation(m_accel, m_gyro, m_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];
	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_s &properties)
{
	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 = m_vendor;
	properties.name = SENSOR_NAME;
	properties.min_interval = 1;
	properties.fifo_count = 0;
	properties.max_batch_count = 0;

	return true;
}

extern "C" sensor_module* create(void)
{
	orientation_sensor *sensor;

	try {
		sensor = new(std::nothrow) orientation_sensor;
	} catch (int err) {
		ERR("Failed to create module, err: %d, cause: %s", err, strerror(err));
		return NULL;
	}

	sensor_module *module = new(std::nothrow) sensor_module;
	retvm_if(!module || !sensor, NULL, "Failed to allocate memory");

	module->sensors.push_back(sensor);
	return module;
}

XML Based Sensor Configuration

Hardware Sensors Configuration

The Sensor Framework configuration file sensor_plugins.xml.in is used for loading of hardware sensors during boot. The configuration information for hardware sensors are entered by the user through the sensors.xml file.

Hardware Sensor XML Configuration File Description

The sensors.xml configuration file supports the following XML fields and values:

<SENSOR>                                         
    <ACCEL>                                      
        <MODEL id="lsm330dlc-accel">
            <NAME value="LSM330DLC"/>
            <VENDOR value="ST Microelectronics"/>
            <RAW_DATA_UNIT value="1" />
            <RESOLUTION value="12" />
        </MODEL>

        <MODEL id="K2HH">
            <NAME value="K2HH" />
            <VENDOR value="ST Microelectronics"/>
            <RAW_DATA_UNIT value="0.061"/>
            <RESOLUTION value="16"/>
        </MODEL>
    </ACCEL>
</SENSOR>
Configuration for Loading Hardware Sensor Plugins

The sensor_plugins.xml configuration file supports the following XML fields and values for sensor_hal and sensor_base plugins. The <HAL> tag is used to load sensor_hal plugin implementation for hardware sensors. The <SENSOR> tag is used for loading sensor_base plugin implementation for hardware sensors.

<PLUGIN>
    <HAL>
        <MODULE path = "/usr/lib/sensord/libaccel_sensor_hal.so"/>
    </HAL>                                                               
    <SENSOR>
        <MODULE path = "/usr/lib/sensord/libaccel_sensor.so"/>
    </SENSOR>
</PLUGIN>

Virtual Sensors Configuration

The configuration information for virtual sensors are entered by the user through the virtual_sensors.xml file.

Virtual Sensor XML Configuration File Description

The virtual_sensors.xml configuration file supports the following XML fields and values:

<VIRTUAL_SENSOR>
    <DEVICE type="Mobile-Emulator">
        <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>
    </DEVICE>
</VIRTUAL_SENSOR>
Configuration for Loading virtual_sensor Plugins

The sensor_plugins.xml configuration file supports the following XML fields and values for virtual_sensor.The <SENSOR> tag is used for loading sensor_base plugin implementation for virtual sensors.

<PLUGIN>                                                             
    <SENSOR>
        <MODULE path = "/usr/lib/sensord/liborientation_sensor.so"/>
    </SENSOR>
</PLUGIN>

New Sensor Definition

Any new sensor to be added has to be defined in the enumeration type sensor_type_t in the file sensord/src/shared/sensor_common.h.

typedef enum {
	ALL_SENSOR = -1,
	UNKNOWN_SENSOR = 0,
	ACCELEROMETER_SENSOR,
	GEOMAGNETIC_SENSOR,
	LIGHT_SENSOR,
	PROXIMITY_SENSOR,
	THERMOMETER_SENSOR,
	GYROSCOPE_SENSOR,
	PRESSURE_SENSOR,
	MOTION_SENSOR,
	FUSION_SENSOR,
	PEDOMETER_SENSOR,
	CONTEXT_SENSOR,
	FLAT_SENSOR,
	BIO_SENSOR,
	BIO_HRM_SENSOR,
	AUTO_ROTATION_SENSOR,
	GRAVITY_SENSOR,
	LINEAR_ACCEL_SENSOR,
	ROTATION_VECTOR_SENSOR,
	ORIENTATION_SENSOR,
	PIR_SENSOR,
	PIR_LONG_SENSOR,
	TEMPERATURE_SENSOR,
	HUMIDITY_SENSOR,
	ULTRAVIOLET_SENSOR,
	DUST_SENSOR,
	RV_RAW_SENSOR,
	UNCAL_GYROSCOPE_SENSOR,
	UNCAL_GEOMAGNETIC_SENSOR
} sensor_type_t;

New Sensor Event Definitions

Any new events for hardware or virtual sensor has to be defined as a separate header file in sensord/src/libsensord/ folder. For example the events to be registered for accelerometer sensor are defined in sensor_accel.h, the contents of which are shown below.

#ifndef __SENSOR_ACCEL_H__
#define __SENSOR_ACCEL_H__

//! Pre-defined events for the accelometer sensor
//! Sensor Plugin developer can add more event to their own headers

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @defgroup SENSOR_ACCEL Accelerometer Sensor
 * @ingroup SENSOR_FRAMEWORK
 *
 * These APIs are used to control the Accelerometer sensor.
 * @{
 */

enum accelerometer_data_id {
	ACCELEROMETER_BASE_DATA_SET 				= (ACCELEROMETER_SENSOR << 16) | 0x0001,
};

enum accelerometer_event_type {
	ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME		= (ACCELEROMETER_SENSOR << 16) | 0x0001,
	ACCELEROMETER_EVENT_UNPROCESSED_DATA_REPORT_ON_TIME	= (ACCELEROMETER_SENSOR << 16) | 0x0002,
};

/**
 * @}
 */

#ifdef __cplusplus
}
#endif

#endif

Updating Common Client Code

The client common code is available in the file sensord/src/libsensord/client_common.cpp file. Here any new sensor event information has to be entered as required, for the following reasons:

  • registering for log information
  • registering for on-time events
  • registering for panning events
  • registering for single state events
  • registering for calibration events
...
#define FILL_LOG_ELEMENT(ID, TYPE, CNT, PRINT_PER_CNT) {ID, TYPE, {#TYPE, CNT, PRINT_PER_CNT} }

log_element g_log_elements[] = {
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, UNKNOWN_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, ACCELEROMETER_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, GEOMAGNETIC_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, LIGHT_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, PROXIMITY_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, GYROSCOPE_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, PRESSURE_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, CONTEXT_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, AUTO_ROTATION_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, GRAVITY_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, LINEAR_ACCEL_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, ORIENTATION_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, TEMPERATURE_SENSOR, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, ROTATION_VECTOR_SENSOR, 0, 1),

	FILL_LOG_ELEMENT(LOG_ID_EVENT, GEOMAGNETIC_EVENT_CALIBRATION_NEEDED, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, PROXIMITY_EVENT_CHANGE_STATE, 0,1),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, LIGHT_EVENT_CHANGE_LEVEL, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, PROXIMITY_EVENT_STATE_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, CONTEXT_EVENT_REPORT, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, AUTO_ROTATION_EVENT_CHANGE_STATE, 0, 1),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, PRESSURE_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, PRESSURE_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, TEMPERATURE_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),
	FILL_LOG_ELEMENT(LOG_ID_EVENT, ROTATION_VECTOR_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10),

	FILL_LOG_ELEMENT(LOG_ID_DATA, ACCELEROMETER_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, GYRO_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, PROXIMITY_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, PROXIMITY_DISTANCE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, PRESSURE_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, GEOMAGNETIC_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, LIGHT_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, LIGHT_LUX_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, CONTEXT_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, AUTO_ROTATION_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, GRAVITY_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, LINEAR_ACCEL_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, ORIENTATION_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, PRESSURE_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, TEMPERATURE_BASE_DATA_SET, 0, 25),
	FILL_LOG_ELEMENT(LOG_ID_DATA, ROTATION_VECTOR_BASE_DATA_SET, 0, 25),
};

bool is_ontime_event(unsigned int event_type)
{
	switch (event_type ) {
	case ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME:
	case PROXIMITY_EVENT_STATE_REPORT_ON_TIME:
	case GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME:
	case LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME:
	case GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME:
	case LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME:
	case PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME:
	case GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME:
	case LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME:
	case ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME:
	case PRESSURE_EVENT_RAW_DATA_REPORT_ON_TIME:
		return true;
		break;
	}

	return false;
}

bool is_panning_event(unsigned int event_type)
{
	return false;
}

bool is_single_state_event(unsigned int event_type)
{
	switch (event_type) {
	case GEOMAGNETIC_EVENT_CALIBRATION_NEEDED:
	case LIGHT_EVENT_CHANGE_LEVEL:
	case PROXIMITY_EVENT_CHANGE_STATE:
	case AUTO_ROTATION_EVENT_CHANGE_STATE:
		return true;
		break;
	}

	return false;
}

unsigned int get_calibration_event_type(unsigned int event_type)
{
	sensor_type_t sensor;

	sensor = (sensor_type_t)(event_type >> SENSOR_TYPE_SHIFT);

	switch (sensor) {
	case GEOMAGNETIC_SENSOR:
		return GEOMAGNETIC_EVENT_CALIBRATION_NEEDED;
	case ROTATION_VECTOR_SENSOR:
		return ROTATION_VECTOR_EVENT_CALIBRATION_NEEDED;
	case ORIENTATION_SENSOR:
		return ORIENTATION_EVENT_CALIBRATION_NEEDED;
	default:
		return 0;
	}
}
...


New Features for Tizen 2.4 Release

  • add sensors
  • support n sensor from 1 sensor plugin.
  • strengthen the security for health-info.


Reference