Data Signal

Data signals are an abstract representation of the data produced by the sensors. The API treats them as an event that contains data and represents them with the MblMwDataSignal struct. They can be safely typecasted to a MblMwEvent

Data Handling

Signal data is encapsulated by the MblMwData struct. The struct contains a:

  • Timestamp of when the data was created
  • Pointer to the data
  • Data type id indicating how to cast the pointer

An enumeration of data types is defined by the MblMwDataTypeId enum and structs wrapping non basic data types are defined in the types.h header file.

#include "metawear/core/data.h"

#include <chrono>
#include <iomanip>

using std::chrono::duration_cast;
using std::chrono::milliseconds;
using std::chrono::system_clock;
using std::chrono::time_point;

void data_printer(const MblMwData* data) {
    // Print data as 2 digit hex values
    uint8_t* data_bytes = (uint8_t*) data->value;
    string bytes_str("{");
    char buffer[5];
    for (uint8_t i = 0; i < data->length; i++) {
        if (i) {
            bytes_str += ", ";
        }
        sprintf(buffer, "0x%02x", data_bytes[i]);
        bytes_str += buffer;
    }
    bytes_str += "}";

    // Format time as YYYYMMDD-HH:MM:SS.LL
    time_point<system_clock> then(milliseconds(data->epoch));
    auto time_c = system_clock::to_time_t(then);
    auto rem_ms= data->epoch % 1000;

    cout << "{timestamp: " << put_time(localtime(&time_c), "%Y%m%d-%T") << "." << rem_ms << ", "
        << "type_id: " << data->type_id << ", "
        << "bytes: " << bytes_str.c_str() << "}"
        << endl;
}

Streaming

To stream data live to your device, call mbl_mw_datasignal_subscribe with the desired data signal and a callback function for handling the received data. Terminating the live stream is done by calling mbl_mw_datasignal_unsubscribe.

#include "metawear/core/datasignal.h"

#include "metawear/sensor/switch.h"

void subscribe_switch(MblMwMetaWearBoard* board) {
    static auto data_handler = [](const MblMwData* data) -> void {
        if (*((uint32_t*)data->value)) {
            cout << "Switch Pressed" << endl;
        } else {
            cout << "Switch Released" << endl;
        }
    };

    auto switch_signal = mbl_mw_switch_get_state_data_signal(board);
    mbl_mw_datasignal_subscribe(switch_signal, data_handler);
}

Logging

Alternatively, data can be logged and retrieved at a later time using the functions outlined in the Logging section. To direct your signal data to the logger, call mbl_mw_datasignal_log. This function is asynchronous and will alert the caller when it is completed via the 2nd callback function. Removing your signal from the logger is done by calling mbl_mw_datasignal_remove_logger.

#include "metawear/core/datasignal.h"
#include "metawear/sensor/multichanneltemperature.h"

void log_temperature(MblMwMetaWearBoard* board) {
    static auto data_handler = [](const MblMwData* data) -> void {
        printf("temperature= %.3fC\n", *((float*) data->value));
    };
    static auto logger_ready = [](void) -> void {
        printf("logger ready\n");
    };

    auto temp_signal = mbl_mw_multi_chnl_temp_get_temperature_data_signal(board, 0);
    mbl_mw_datasignal_log(temp_signal, data_handler, logger_ready);
}

Data Processing

Data signals can be fed through the on-board data processors to filter and/or transform the data in the firmware. By performing computations on the MetaWear side, you can reduce the amount of data that is sent over the radio and the amount of postprocessing that is done on your mobile device. Data processors can also be chained together to perform more complex tasks, such as using the rss, average, and threshold processors to determine if the board is in freefall based on the XYZ acceleration data.

See the Data Processor section for more details on the data processing system.

#include "metawear/core/dataprocessor_fwd.h"
#include "metawear/processor/rss.h"
#include "metawear/sensor/accelerometer.h"

void rss_accelerometer(MblMwMetaWearBoard* board) {
    static auto data_handler = [](const MblMwData* data) -> void {
        printf("acc rss= %.3fg\n", (float*) data->value);
    };
    static auto rss_ready = [](MblMwDataProcessor* processor) -> void {
        // subscribe to the rss processor
        mbl_mw_datasignal_subscribe((MblMwDataSignal*) processor, data_handler);
    };

    // Create an rss processor to transform the XYZ values into vector magnitude
    // Do not need to compute rss on your device and less data is transmitted
    auto acc_signal = mbl_mw_acc_get_acceleration_data_signal(board);
    mbl_mw_dataprocessor_rss_create(acc_signal, rss_ready);
}