Telematics SDK - User Guide  v1.46.62
Using Sensor APIs to configure and acquire sensor data

Using Sensor APIs to configure and acquire sensor data

Please follow below steps as a guide to configure and acquire sensor data

1. Get sensor factory

auto &sensorFactory = telux::sensor::SensorFactory::getInstance();

2. Prepare a callback that is invoked when the sensor sub-system initialization is complete

std::promise<telux::common::ServiceStatus> p;
auto initCb = [&p](telux::common::ServiceStatus status) {
std::cout << "Received service status: " << static_cast<int>(status) << std::endl;
p.set_value(status);
};

3. Get the sensor manager. If initialization fails, perform necessary error handling

std::shared_ptr<telux::sensor::ISensorManager> sensorManager
= sensorFactory.getSensorManager(initCb);
if (sensorManager == nullptr) {
std::cout << "sensor manager is nullptr" << std::endl;
exit(1);
}
std::cout << "obtained sensor manager" << std::endl;

4. Wait until initialization is complete

p.get_future().get();
if (sensorManager->getServiceStatus() != telux::common::ServiceStatus::SERVICE_AVAILABLE) {
std::cout << "Sensor service not available" << std::endl;
exit(1);
}

5. Get information regarding available sensors in the system

std::cout << "Sensor service is now available" << std::endl;
std::vector<telux::sensor::SensorInfo> sensorInfo;
telux::common::Status status = sensorManager->getAvailableSensorInfo(sensorInfo);
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to get information on available sensors" << static_cast<int>(status)
<< std::endl;
exit(1);
}
std::cout << "Received sensor information" << std::endl;
for (auto info : sensorInfo) {
printSensorInfo(info);
}

6. Request the ISensorManager for the desired sensor

std::shared_ptr<telux::sensor::ISensor> sensor;
std::cout << "Getting sensor: " << name << std::endl;
status = sensorManager->getSensor(sensor, name);
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to get sensor: " << name << std::endl;
exit(1);
}

7. Create and register a sensor event listener for configuration updates and sensor events

The event listener extends the ISensorEventListener to receive notification about configuration and sensor events.
class SensorEventListener : public telux::sensor::ISensorEventListener {
public:
SensorEventListener(std::shared_ptr<telux::sensor::ISensor> sensor)
: sensor_(sensor)
, totalBatches_(0) {
}
// [11] Receive sensor events. This notification is received every time the configured batch
// count is available with the sensor framework
virtual void onEvent(
std::shared_ptr<std::vector<telux::sensor::SensorEvent>> events) override {
PRINT_NOTIFICATION << ": Received " << events->size()
<< " events from sensor: "
<< sensor_->getSensorInfo().name << std::endl;
// I/O intense operations such as below should be avoided since this thread should avoid
// any time consuming operations
for (telux::sensor::SensorEvent s : *(events.get())) {
printSensorEvent(s);
}
++totalBatches_;
// [11.1] If we have received expected number of batches and want to reconfigure the sensor
// we will spawn the request to deactivate, configure and activate on a different thread
// since we are not allowed to invoke the sensor APIs from this thread context
if (totalBatches_ > TOTAL_BATCHES_REQUIRED) {
totalBatches_ = 0;
std::thread t([&] {
sensor_->deactivate();
sensor_->configure(sensor_->getConfiguration());
sensor_->activate();
});
// Be sure to detach the thread
t.detach();
}
}
// [9] Receive configuration updates
virtual void onConfigurationUpdate(
telux::sensor::SensorConfiguration configuration) override {
PRINT_NOTIFICATION
<< ": Received configuration update from sensor: " << sensor_->getSensorInfo().name
<< ": [" << configuration.samplingRate << ", " << configuration.batchCount << " ]"
<< std::endl;
}
private:
bool isUncalibratedSensor(telux::sensor::SensorType type) {
return ((type == telux::sensor::SensorType::GYROSCOPE_UNCALIBRATED)
|| (type == telux::sensor::SensorType::ACCELEROMETER_UNCALIBRATED));
}
void printSensorEvent(telux::sensor::SensorEvent &s) {
telux::sensor::SensorInfo info = sensor_->getSensorInfo();
if (isUncalibratedSensor(sensor_->getSensorInfo().type)) {
PRINT_NOTIFICATION << ": " << sensor_->getSensorInfo().name << ": " << s.timestamp
<< ", " << s.uncalibrated.data.x << ", " << s.uncalibrated.data.y
<< ", " << s.uncalibrated.data.z << ", " << s.uncalibrated.bias.x
<< ", " << s.uncalibrated.bias.y << ", " << s.uncalibrated.bias.z
<< std::endl;
} else {
PRINT_NOTIFICATION << ": " << sensor_->getSensorInfo().name << ": " << s.timestamp
<< ", " << s.calibrated.x << ", " << s.calibrated.y << ", "
<< s.calibrated.z << std::endl;
}
}
std::shared_ptr<telux::sensor::ISensor> sensor_;
uint32_t totalBatches_;
};
Create a event listener and register it with the sensor.
std::shared_ptr<SensorEventListener> sensorEventListener
= std::make_shared<SensorEventListener>(sensor->getSensorInfo());
sensor->registerListener(sensorEventListener);

8. Configure the sensor with required configuration setting the necessary validityMask

telux::sensor::SensorConfiguration config;
config.samplingRate = getMinimumSamplingRate(sensor->getSensorInfo());
config.batchCount = sensor->getSensorInfo().maxBatchCountSupported;
std::cout << "Configuring sensor with samplingRate, batchCount [" << config.samplingRate << ", "
<< config.batchCount << "]" << std::endl;
config.validityMask.set(telux::sensor::SensorConfigParams::SAMPLING_RATE);
config.validityMask.set(telux::sensor::SensorConfigParams::BATCH_COUNT);
status = sensor->configure(config);
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to configure sensor: " << name << std::endl;
exit(1);
}

9. Receive updates on sensor configuration

virtual void onConfigurationUpdate(telux::sensor::SensorConfiguration configuration) override {
PRINT_NOTIFICATION << ": Received configuration update from sensor: " << info_.name << ": ["
<< configuration.samplingRate << ", " << configuration.batchCount << " ]"
<< std::endl;
}

10. Activate the sensor to receive sensor data

status = sensor->activate();
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to activate sensor: " << name << std::endl;
exit(1);
}

11. Receive sensor data with the registered listener

Avoid any time consuming operation in this callback. This thread should be released back the SDK library to avoid latency.

If any sensor APIs need to be called in this method, they should be done on a different thread. One such method is to spawn a detached thread that invokes the required API.

virtual void onEvent(std::shared_ptr<std::vector<telux::sensor::SensorEvent>> events) override {
PRINT_NOTIFICATION << ": Received " << events->size()
<< " events from sensor: " << sensor_->getSensorInfo().name << std::endl;
// I/O intense operations such as below should be avoided since this thread should avoid
// any time consuming operations
for (telux::sensor::SensorEvent s : *(events.get())) {
printSensorEvent(s);
}
++totalBatches_;
// [11.1] If we have received expected number of batches and want to reconfigure the sensor
// we will spawn the request to deactivate, configure and activate on a different thread
// since we are not allowed to invoke the sensor APIs from this thread context
if (totalBatches_ > TOTAL_BATCHES_REQUIRED) {
totalBatches_ = 0;
std::thread t([&] {
sensor_->deactivate();
sensor_->configure(sensor_->getConfiguration());
sensor_->activate();
});
// Be sure to detach the thread
t.detach();
}
}

12. When data acquisition is no longer necessary, deactivate the sensor

status = sensor->deactivate();
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to deactivate sensor: " << name << std::endl;
exit(1);
}

13. Release the instance of ISensor if no longer required

sensor = nullptr;

14. Release the instance of ISensorManager to cleanup resources

sensorManager = nullptr;

Using Sensor APIs to initiate a self test and acquires the self test result

Please follow below steps as a guide to initiate a self test and acquires the self test result

1. Get sensor factory

auto &sensorFactory = telux::sensor::SensorFactory::getInstance();

2. Prepare a callback that is invoked when the sensor sub-system initialization is complete

std::promise<telux::common::ServiceStatus> p;
auto initCb = [&p](telux::common::ServiceStatus status) {
std::cout << "Received service status: " << static_cast<int>(status) << std::endl;
p.set_value(status);
};

3. Get the sensor manager. If initialization fails, perform necessary error handling

std::shared_ptr<telux::sensor::ISensorManager> sensorManager
= sensorFactory.getSensorManager(initCb);
if (sensorManager == nullptr) {
std::cout << "sensor manager is nullptr" << std::endl;
exit(1);
}
std::cout << "obtained sensor manager" << std::endl;

4. Wait until initialization is complete

p.get_future().get();
if (sensorManager->getServiceStatus() != telux::common::ServiceStatus::SERVICE_AVAILABLE) {
std::cout << "Sensor service not available" << std::endl;
exit(1);
}

5. Get information regarding available sensors in the system

std::cout << "Sensor service is now available" << std::endl;
std::vector<telux::sensor::SensorInfo> sensorInfo;
telux::common::Status status = sensorManager->getAvailableSensorInfo(sensorInfo);
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to get information on available sensors" << static_cast<int>(status)
<< std::endl;
exit(1);
}
std::cout << "Received sensor information" << std::endl;
for (auto info : sensorInfo) {
printSensorInfo(info);
}

6. Request the ISensorManager for the desired sensor

std::shared_ptr<telux::sensor::ISensor> sensor;
std::cout << "Getting sensor: " << name << std::endl;
status = sensorManager->getSensor(sensor, name);
if (status != telux::common::Status::SUCCESS) {
std::cout << "Failed to get sensor: " << name << std::endl;
exit(1);
}

7. Invoke the self test with the required self test type and provide the callback

status = sensor->selfTest(selfTestType, [](telux::common::ErrorCode result) {
PRINT_CB << "Received self test response: " << static_cast<int>(result) << std::endl;
});
if (status != telux::common::Status::SUCCESS) {
std::cout << "Self test request failed";
} else {
std::cout << "Self test request successful, waiting for callback" << std::endl;
}

8. Release the instance of ISensor if no longer required

sensor = nullptr;

9. Release the instance of ISensorManager to cleanup resources

sensorManager = nullptr;