首页 > 解决方案 > Movesense 传感器数据记录

问题描述

我使用 Flutter 并希望记录和存储传感器模型的收集数据:OP174。我正在使用加速度计、陀螺仪、磁力计和温度计。

我在 Movesense.swift 中看到有一个 Logbook_path 和一个 Datalogger_config_path 但我不知道如何让它保存收集的数据,它尝试了我在下面发布的另一个解决方案。

我如何将这些数据存储在 CSV 文件中并自动包含时间戳?

获取陀螺仪数据

int _gyroSubscription;
  String _gyroscopeData = "";
  String get gyroscopeData => _gyroscopeData;
  bool get gyroscopeSubscribed => _gyroSubscription != null;

void subscribeToGyroscope() {
    _gyroscopeData = "";
    _gyroSubscription = Mds.subscribe(
        Mds.createSubscriptionUri(_serial, "/Meas/Gyro/104"),
        "{}",
        (d, c) => {},
        (e, c) => {},
        (data) => _onNewGyroscopeData(data),
        (e, c) => {});
    notifyListeners();
  }

  void _onNewGyroscopeData(String data) {
    Map<String, dynamic> gyroData = jsonDecode(data);
    Map<String, dynamic> body = gyroData["Body"];
    List<dynamic> gyroArry = body["ArrayGyro"];
    dynamic gyro = gyroArry.last;
    _gyroscopeData = "x: " +
        gyro["x"].toStringAsFixed(2) +
        "\ny: " +
        gyro["y"].toStringAsFixed(2) +
        "\nz: " +
        gyro["z"].toStringAsFixed(2);
    notifyListeners();
  }

试图保存数据

Future<String> getFilePath() async {
    Directory appDocumentsDirectory = await getExternalStorageDirectory();
    List<FileSystemEntity> directory = appDocumentsDirectory.listSync();
    directory.forEach((x) => debugPrint(x.path));
    String appDocumentsPath = appDocumentsDirectory.path;
    String filePath = '$appDocumentsPath/recording.csv';

    return filePath;
  }

  void saveFile(DeviceModel deviceModel) async {
    File file = File(await getFilePath());
    file.writeAsString(deviceModel.gyroscopeData);
  }

新代码编辑

import 'dart:convert';

import 'package:csv/csv.dart';
import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';
import 'package:mdsflutter/Mds.dart';
import 'dart:io';

import 'package:path_provider/path_provider.dart';

import 'dart:developer' as developer;

class DeviceModel extends ChangeNotifier {
  String _serial;
  String _name;

  bool _skipAccelerometer = false;
  bool _skipGyroscope = false;
  bool _skipMagneto = false;

  set skipAccelerometer(bool x) {
    _skipAccelerometer = x;
  }

  bool get skipAccelerometer => _skipAccelerometer;

  set skipGyroscope(bool x) {
    _skipGyroscope = x;
  }

  bool get skipGyroscope => _skipGyroscope;

  set skipMagneto(bool x) {
    _skipMagneto = x;
  }

  bool get skipMagneto => _skipMagneto;

  List<List<dynamic>> _accelerometerList = new List<List<dynamic>>();
  List<List<dynamic>> _gyroscopeList = new List<List<dynamic>>();
  List<List<dynamic>> _magnetoList = new List<List<dynamic>>();

  String get name => _name;

  String get serial => _serial;

  int _accSubscription;
  String _accelerometerData = "";

  String get accelerometerData => _accelerometerData;

  bool get accelerometerSubscribed => _accSubscription != null;

  int _gyroSubscription;
  String _gyroscopeData = "";

  String get gyroscopeData => _gyroscopeData;

  bool get gyroscopeSubscribed => _gyroSubscription != null;

  int _magnSubscription;
  String _magnetoData = "";

  String get magnetoData => _magnetoData;

  bool get magnetoSubscribed => _magnSubscription != null;

  int _hrSubscription;
  String _hrData = "";

  String get hrData => _hrData;

  bool get hrSubscribed => _hrSubscription != null;

  bool _ledStatus = false;

  bool get ledStatus => _ledStatus;

  String _temperature = "";

  String get temperature => _temperature;

  DeviceModel(this._name, this._serial);

  void subscribeToAccelerometer() {
    _accelerometerData = "";
    _accSubscription = Mds.subscribe(
        Mds.createSubscriptionUri(_serial, "/Meas/Acc/104"),
        "{}",
        (d, c) => {},
        (e, c) => {},
        (data) => _onNewAccelerometerData(data),
        (e, c) => {});
    notifyListeners();
  }

  void _onNewAccelerometerData(String data) {
    Map<String, dynamic> accData = jsonDecode(data);
    Map<String, dynamic> body = accData["Body"];
    List<dynamic> accArray = body["ArrayAcc"];
    dynamic acc = accArray.last;
    _accelerometerData = "x: " +
        acc["x"].toStringAsFixed(2) +
        "\ny: " +
        acc["y"].toStringAsFixed(2) +
        "\nz: " +
        acc["z"].toStringAsFixed(2);

    //Option 1
    DateTime now = DateTime.now();
    var dateLocal = now.toLocal();
    var formattedDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateLocal);

    //Option 2
    //var formattedDate = DateTime.now().millisecondsSinceEpoch;

    List<dynamic> row = new List<dynamic>();
    row.add(formattedDate);
    row.add(acc["x"].toStringAsFixed(2));
    row.add(acc["y"].toStringAsFixed(2));
    row.add(acc["z"].toStringAsFixed(2));

    _accelerometerList.add(row);
    notifyListeners();
  }

  void unsubscribeFromAccelerometer() {
    Mds.unsubscribe(_accSubscription);
    _accSubscription = null;
    notifyListeners();
  }

  void subscribeToGyroscope() {
    _gyroscopeData = "";
    _gyroSubscription = Mds.subscribe(
        Mds.createSubscriptionUri(_serial, "/Meas/Gyro/26"),
        "{}",
        (d, c) => {},
        (e, c) => {},
        (data) => _onNewGyroscopeData(data),
        (e, c) => {});
    notifyListeners();
  }

  void _onNewGyroscopeData(String data) {
    Map<String, dynamic> gyroData = jsonDecode(data);
    Map<String, dynamic> body = gyroData["Body"];
    List<dynamic> gyroArry = body["ArrayGyro"];
    dynamic gyro = gyroArry.last;
    _gyroscopeData = "x: " +
        gyro["x"].toStringAsFixed(2) +
        "\ny: " +
        gyro["y"].toStringAsFixed(2) +
        "\nz: " +
        gyro["z"].toStringAsFixed(2);

    //Option 1
    DateTime now = DateTime.now();
    var dateLocal = now.toLocal();
    var formattedDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateLocal);

    //Option 2
    //var formattedDate = DateTime.now().millisecondsSinceEpoch;

    List<dynamic> row = new List<dynamic>();
    row.add(formattedDate);
    row.add(gyro["x"].toStringAsFixed(2));
    row.add(gyro["y"].toStringAsFixed(2));
    row.add(gyro["z"].toStringAsFixed(2));
    _gyroscopeList.add(row);
    notifyListeners();
  }

  void unsubscribeFromGyroscope() {
    Mds.unsubscribe(_gyroSubscription);
    _gyroSubscription = null;
    notifyListeners();
  }

  void subscribeToMagnetometer() {
    _magnetoData = "";
    _magnSubscription = Mds.subscribe(
        Mds.createSubscriptionUri(_serial, "/Meas/Magn/104"),
        "{}",
        (d, c) => {},
        (e, c) => {},
        (data) => _onNewMagnetometerData(data),
        (e, c) => {});
    notifyListeners();
  }

  // static int count = 0;

  void _onNewMagnetometerData(String data) {
    Map<String, dynamic> magnData = jsonDecode(data);
    Map<String, dynamic> body = magnData["Body"];
    List<dynamic> magnArry = body["ArrayMagn"];
    dynamic magn = magnArry.last;
    // int c = count++;
    _magnetoData = "x: " +
        magn["x"].toStringAsFixed(2) +
        "\ny: " +
        magn["y"].toStringAsFixed(2) +
        "\nz: " +
        magn["z"].toStringAsFixed(2);

    //Option 1
    DateTime now = DateTime.now();
    var dateLocal = now.toLocal();
    var formattedDate = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateLocal);

    //Option 2
    //var formattedDate = DateTime.now().millisecondsSinceEpoch;

    List<dynamic> row = new List<dynamic>();
    row.add(formattedDate);
    row.add(magn["x"].toStringAsFixed(2));
    row.add(magn["y"].toStringAsFixed(2));
    row.add(magn["z"].toStringAsFixed(2));
    // row.add(c.toString());

    _magnetoList.add(row);
    notifyListeners();
  }

  void unsubscribeFromMagnetometer() {
    Mds.unsubscribe(_magnSubscription);
    _magnSubscription = null;
    notifyListeners();
  }

  void subscribeToHr() {
    _hrData = "";
    _hrSubscription = Mds.subscribe(
        Mds.createSubscriptionUri(_serial, "/Meas/HR"),
        "{}",
        (d, c) => {},
        (e, c) => {},
        (data) => _onNewHrData(data),
        (e, c) => {});
    notifyListeners();
  }

  void _onNewHrData(String data) {
    Map<String, dynamic> hrData = jsonDecode(data);
    Map<String, dynamic> body = hrData["Body"];
    double hr = body["average"];
    _hrData = hr.toStringAsFixed(1) + " bpm";
    notifyListeners();
  }

  void unsubscribeFromHr() {
    Mds.unsubscribe(_hrSubscription);
    _hrSubscription = null;
    notifyListeners();
  }

  void switchLed() {
    Map<String, bool> contract = new Map<String, bool>();
    contract["isOn"] = !_ledStatus;
    Mds.put(
        Mds.createRequestUri(_serial, "/Component/Led"), jsonEncode(contract),
        (data, code) {
      _ledStatus = !_ledStatus;
      notifyListeners();
    }, (e, c) => {});
  }

  void getTemperature() {
    Mds.get(Mds.createRequestUri(_serial, "/Meas/Temp"), "{}", (data, code) {
      double kelvin = jsonDecode(data)["Content"]["Measurement"];
      double temperatureVal = kelvin - 274.15;
      _temperature = temperatureVal.toStringAsFixed(1) + " C";
      notifyListeners();
    }, (e, c) => {});
  }

  void startAccelerometerRecord() {
    _skipAccelerometer = false;
    _accelerometerList = new List<List<dynamic>>();
    List<dynamic> header = new List();
    header.add("timestamp");
    header.add("X");
    header.add("Y");
    header.add("Z");
    _accelerometerList.add(header);
  }

  void stopAccelerometerRecord() {
    _skipAccelerometer = true;
    writeToCsvAccelerometer();
  }

  void startGyroscopeRecord() {
    _skipGyroscope = false;
    _gyroscopeList = new List<List<dynamic>>();
    List<dynamic> header = new List();
    header.add("timestamp");
    header.add("X");
    header.add("Y");
    header.add("Z");
    _gyroscopeList.add(header);
  }

  void stopGyroscopeRecord() {
    _skipGyroscope = true;
    writeToCsvGyroscope();
  }

  void startMagnetoRecord() {
    _skipMagneto = false;
    _magnetoList = new List<List<dynamic>>();
    List<dynamic> header = new List();
    header.add("timestamp");
    header.add("X");
    header.add("Y");
    header.add("Z");
    _magnetoList.add(header);
  }

  void stopMagnetoRecord() {
    _skipMagneto = true;
    writeToCsvMagneto();
  }

  void writeToCsvAccelerometer() async {
    File file = File(await getFilePath("accelero"));
    String csv = const ListToCsvConverter().convert(_accelerometerList);
    file.writeAsString(csv);
  }

  void writeToCsvGyroscope() async {
    File file = File(await getFilePath("gyro"));
    String csv = const ListToCsvConverter().convert(_gyroscopeList);
    file.writeAsString(csv);
  }

  void writeToCsvMagneto() async {
    File file = File(await getFilePath("magneto"));
    String csv = const ListToCsvConverter().convert(_magnetoList);
    file.writeAsString(csv);
  }

  Future<String> getFilePath(String name) async {
    DateTime now = DateTime.now();
    var dateLocal = now.toLocal();
    var formattedDate = DateFormat('yyyy-MM-dd HH:mm').format(dateLocal);

    Directory appDocumentsDirectory;

    if (Platform.isAndroid) {
      appDocumentsDirectory = await getExternalStorageDirectory();
    } else if (Platform.isIOS) {
      appDocumentsDirectory = await getApplicationDocumentsDirectory();
    }
    List<FileSystemEntity> directory = appDocumentsDirectory.listSync();
    directory.forEach((x) => debugPrint(x.path));
    String appDocumentsPath = appDocumentsDirectory.path;
    String filePath = '$appDocumentsPath/' + name + '' + formattedDate + '.csv';

    return filePath;
  }
}

标签: flutterdartrecordmovesense

解决方案


要使用 DataLogger & Logbook,请参阅 Android 示例“DataLoggerSample”以及相关的API 文档

简而言之:

  1. PUT /Mem/DataLogger/Config 列出您要记录的路径。在您的情况下,它们将是/Meas/IMU9/104/Meas/Temp
  2. PUT /Mem/DataLogger/State to 3 (=LOGGING) -- 你可以在这里断开连接 --
  3. 你做你想要衡量的事情
  4. 重新连接到传感器
  5. 将 /Mem/DataLogger/State 设置为 2 (=READY)。这将停止录制。
  6. 在移动设备上获取“suunto:/MDS/Logbook/{serial}/Entries”以获取传感器数据存储器上的条目列表。LogID最大的就是你刚才记录的那个
  7. 在移动设备上获取“suunto:/MDS/Logbook/{serial}/byId/{LogId}/Data”以获取 JSON 格式的录音。

注意:您要记录的路径会很快填满数据存储器(< 100 秒)。当前传感器将数据内存视为环形缓冲区,并在旧数据已满时存储旧数据,因此您将获得最后约 90 秒的数据。

全面披露:我为 Movesense 团队工作


推荐阅读