Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 50 additions & 48 deletions lib/src/managers/open_earable_sensor_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,54 +79,56 @@ class OpenEarableSensorHandler extends SensorHandler<OpenEarableSensorConfig> {
.listen(
(data) async {
if (data.isNotEmpty && data[0] == sensorId) {
Map<String, dynamic> parsedData = await _parseData(data);
if (sensorId == imuID) {
int timestamp = parsedData["timestamp"];
double ax = parsedData["ACC"]["X"];
double ay = parsedData["ACC"]["Y"];
double az = parsedData["ACC"]["Z"];

double gx = parsedData["GYRO"]["X"];
double gy = parsedData["GYRO"]["Y"];
double gz = parsedData["GYRO"]["Z"];

double dt = (timestamp - lastTimestamp) / 1000.0;

// x, y, z was changed in firmware to -x, z, y
_mahonyAHRS.update(
ax,
ay,
az,
gx,
gy,
gz,
dt,
);

lastTimestamp = timestamp;
List<double> q = _mahonyAHRS.quaternion;
double yaw = -atan2(
2 * (q[0] * q[3] + q[1] * q[2]),
1 - 2 * (q[2] * q[2] + q[3] * q[3]),
);

// Pitch (around Y-axis)
double pitch = -asin(2 * (q[0] * q[2] - q[3] * q[1]));

// Roll (around X-axis)
double roll = -atan2(
2 * (q[0] * q[1] + q[2] * q[3]),
1 - 2 * (q[1] * q[1] + q[2] * q[2]),
);

parsedData["EULER"] = {};
parsedData["EULER"]["YAW"] = yaw;
parsedData["EULER"]["PITCH"] = pitch;
parsedData["EULER"]["ROLL"] = roll;
parsedData["EULER"]
["units"] = {"YAW": "rad", "PITCH": "rad", "ROLL": "rad"};
List<Map<String, dynamic>> parsedDataList = await _parseData(data);
for (var parsedData in parsedDataList) {
if (sensorId == imuID) {
int timestamp = parsedData["timestamp"];
double ax = parsedData["ACC"]["X"];
double ay = parsedData["ACC"]["Y"];
double az = parsedData["ACC"]["Z"];

double gx = parsedData["GYRO"]["X"];
double gy = parsedData["GYRO"]["Y"];
double gz = parsedData["GYRO"]["Z"];

double dt = (timestamp - lastTimestamp) / 1000.0;

// x, y, z was changed in firmware to -x, z, y
_mahonyAHRS.update(
ax,
ay,
az,
gx,
gy,
gz,
dt,
);

lastTimestamp = timestamp;
List<double> q = _mahonyAHRS.quaternion;
double yaw = -atan2(
2 * (q[0] * q[3] + q[1] * q[2]),
1 - 2 * (q[2] * q[2] + q[3] * q[3]),
);

// Pitch (around Y-axis)
double pitch = -asin(2 * (q[0] * q[2] - q[3] * q[1]));

// Roll (around X-axis)
double roll = -atan2(
2 * (q[0] * q[1] + q[2] * q[3]),
1 - 2 * (q[1] * q[1] + q[2] * q[2]),
);

parsedData["EULER"] = {};
parsedData["EULER"]["YAW"] = yaw;
parsedData["EULER"]["PITCH"] = pitch;
parsedData["EULER"]["ROLL"] = roll;
parsedData["EULER"]
["units"] = {"YAW": "rad", "PITCH": "rad", "ROLL": "rad"};
}
streamController.add(parsedData);
}
streamController.add(parsedData);
}
},
onError: (error) {},
Expand All @@ -136,7 +138,7 @@ class OpenEarableSensorHandler extends SensorHandler<OpenEarableSensorConfig> {
}

/// Parses raw sensor data bytes into a [Map] of sensor values.
Future<Map<String, dynamic>> _parseData(data) async {
Future<List<Map<String, dynamic>>> _parseData(data) async {
ByteData byteData = ByteData.sublistView(Uint8List.fromList(data));

return _sensorValueParser.parse(byteData, _sensorSchemes!);
Expand Down
8 changes: 5 additions & 3 deletions lib/src/managers/v2_sensor_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ class V2SensorHandler extends SensorHandler<V2SensorConfig> {
.listen(
(data) async {
if (data.isNotEmpty && data[0] == sensorId) {
Map<String, dynamic> parsedData = await _parseData(data);
streamController.add(parsedData);
List<Map<String, dynamic>> parsedData = await _parseData(data);
for (var d in parsedData) {
streamController.add(d);
}
}
},
onError: (error) {
Expand Down Expand Up @@ -78,7 +80,7 @@ class V2SensorHandler extends SensorHandler<V2SensorConfig> {
}

/// Parses raw sensor data bytes into a [Map] of sensor values.
Future<Map<String, dynamic>> _parseData(data) async {
Future<List<Map<String, dynamic>>> _parseData(data) async {
ByteData byteData = ByteData.sublistView(Uint8List.fromList(data));

if (_sensorSchemes == null) {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/models/devices/open_earable_v2.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ const String _audioModeCharacteristicUuid =
const String _buttonServiceUuid = "29c10bdc-4773-11ee-be56-0242ac120002";
const String _buttonCharacteristicUuid = "29c10f38-4773-11ee-be56-0242ac120002";

final VersionNumber _maxVersionSupported = VersionNumber.parse("2.1.5");
final VersionNumber _minVersionSupported = VersionNumber.parse("2.0.0");
final VersionNumber _maxVersionSupported = VersionNumber.parse("2.1.6");
final VersionNumber _minVersionSupported = VersionNumber.parse("2.1.6");

// MARK: OpenEarableV2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class EdgeMlSensorSchemeReader extends SensorSchemeReader {
currentIndex += unitNameLength;

Component component =
Component(componentType, groupName, componentName, unitName);
Component(ParseType.fromInt(componentType), groupName, componentName, unitName);
sensorScheme.components.add(component);
}

Expand Down
38 changes: 36 additions & 2 deletions lib/src/utils/sensor_scheme_parser/sensor_scheme_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ abstract class SensorSchemeReader {

/// Represents a sensor component with its type, group name, component name, and unit name.
class Component {
int type;
ParseType type;
String groupName;
String componentName;
String unitName;
Expand Down Expand Up @@ -36,7 +36,41 @@ class SensorScheme {
}
}

enum ParseType { int8, uint8, int16, uint16, int32, uint32, float, double }
enum ParseType {
int8,
uint8,
int16,
uint16,
int32,
uint32,
float,
double;

/// Constructs a [ParseType] from an integer value.
static ParseType fromInt(int value) {
if (value < 0 || value >= ParseType.values.length) {
throw ArgumentError('Invalid ParseType value: $value');
}
return ParseType.values[value];
}

int size() {
switch (this) {
case ParseType.int8:
case ParseType.uint8:
return 1;
case ParseType.int16:
case ParseType.uint16:
return 2;
case ParseType.int32:
case ParseType.uint32:
case ParseType.float:
return 4;
case ParseType.double:
return 8;
}
}
}

enum SensorConfigFeatures {
streaming(0x01),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class V2SensorSchemeReader extends SensorSchemeReader {
currentIndex += unitNameLength;

Component component =
Component(componentType, groupName, componentName, unitName);
Component(ParseType.fromInt(componentType), groupName, componentName, unitName);
sensorScheme.components.add(component);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'sensor_value_parser.dart';

class EdgeMlSensorValueParser extends SensorValueParser {
@override
Map<String, dynamic> parse(ByteData data, List<SensorScheme> sensorSchemes) {
List<Map<String, dynamic>> parse(ByteData data, List<SensorScheme> sensorSchemes) {
var byteIndex = 0;
final sensorId = data.getUint8(byteIndex);
byteIndex += 2; // skip one byte because of size byte that is not used
Expand All @@ -26,7 +26,7 @@ class EdgeMlSensorValueParser extends SensorValueParser {
parsedData[component.groupName]["units"] = {};
}
final dynamic parsedValue;
switch (ParseType.values[component.type]) {
switch (component.type) {
case ParseType.int8:
parsedValue = data.getInt8(byteIndex);
byteIndex += 1;
Expand Down Expand Up @@ -64,6 +64,6 @@ class EdgeMlSensorValueParser extends SensorValueParser {
parsedData[component.groupName]["units"][component.componentName] =
component.unitName;
}
return parsedData;
return [parsedData];
}
}
3 changes: 2 additions & 1 deletion lib/src/utils/sensor_value_parser/sensor_value_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import 'dart:typed_data';
import '../sensor_scheme_parser/sensor_scheme_reader.dart';

abstract class SensorValueParser {
Map<String, dynamic> parse(ByteData data, List<SensorScheme> sensorSchemes);
/// Parses raw sensor data bytes into a list of [Map]s of sensor values.
List<Map<String, dynamic>> parse(ByteData data, List<SensorScheme> sensorSchemes);
}
Loading