Untitled

mail@pastecode.io avatar
unknown
plain_text
7 months ago
5.6 kB
2
Indexable
Never
import 'dart:developer';
import 'dart:ffi';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:self_science_station/model/metric_model.dart';
import 'package:self_science_station/model/sensor_model.dart';
import 'package:self_science_station/sensor/sensorInstance.dart';
import 'package:self_science_station/utils/utils.dart';
import 'package:self_science_station/sensor/polar_api.dart';

import 'package:polar/polar.dart';

// TODO create a custom type that has fields:
// - SensorTypeModel
// - SensorState
// - Function handlers for state machine

/* State Machine (TODO create Figma flow chart for this for reference)
 * disconnected 
 * 
 * 
 * 
 */

class SensorProvider extends ChangeNotifier {
  // The list storing all the child instances
  final List<SensorInstance> sensorInstances = [];
  final List<SensorTypeModel> _sensorTypes = [];
  // List of the physical sensors we've found from scanning
  // Indexed by their the sensor type ID
  final Map<String, List<String>> physicalSensors = {};
  final Map<SensorTypeModel, dynamic> registeredScanSubscription = {};

  // // Lists of the Sensor Model details -- no need for this i believe
  // final List<SensorInstanceModel> _sensorInstances = [];

  // Constructor (without subclass-instance creation)
  SensorProvider();

  List<SensorTypeModel> getAllSensorTypes() => _sensorTypes;

  SensorTypeModel? getSensorType(String sensorTypeID) =>
      _sensorTypes.where((s) => s.id == sensorTypeID).firstOrNull;

  // TODO set third party respondent ID for current user
  SensorInstance getSensorFromType(String sensorTypeID) =>
      //_sensorTypes.firstWhere((s) => s.id == sensorTypeID);
      sensorInstances.firstWhere((s) => s.getTypeModel().id == sensorTypeID);

  SensorInstance? getSensorFromInstanceID(String sensorInstanceID) =>
      sensorInstances
          .where((s) => s.getSensorInstance().id == sensorInstanceID)
          .firstOrNull;

  SensorInstance? getSensorFromInstanceDeviceID(
          String sensorInstanceDeviceID) =>
      sensorInstances
          .where(
              (s) => s.getSensorInstance().deviceID == sensorInstanceDeviceID)
          .firstOrNull;

  List<SensorInstance> getAllSensorsOfType(String sensorTypeID) =>
      sensorInstances
          .where((s) => s.getTypeModel().id == sensorTypeID)
          .toList();

  // Gets you a sensor for a given type that is recording
  SensorInstance? getCurrentlyRecordingSensorOfType(String sensorTypeID) =>
      sensorInstances
          .where((s) =>
              s.getTypeModel().id == sensorTypeID &&
              (s.sState == SensorState.connected_acquiring ||
                  s.sState == SensorState.disconnected_acquiring))
          .firstOrNull;

  List<MetricModel> getMetricsFromSensorTypeIDs(List<String> sensorIDs) {
    final metrics = <MetricModel>[];

    for (final sensorID in sensorIDs) {
      final sensorInstance =
          sensorInstances.firstWhere((s) => s.getTypeModel().id == sensorID);
      final sensorType = sensorInstance.getTypeModel();
      for (final metric in sensorType.canRecord) {
        // Only add if we don't already have it
        if (!metrics.any((m) => m.id == metric.id)) {
          metrics.add(metric);
        }
      }
    }

    return metrics;
  }

  void updateEverything() {
    notifyListeners();
  }

  void resetEverything() {
    _sensorTypes.clear();
    physicalSensors.clear();
    for (final sub in registeredScanSubscription.values) {
      sub?.cancel();
    }
    registeredScanSubscription.clear();
    sensorInstances.clear();
    notifyListeners();
  }

  // will get the sensor types from the backend
  void setSensors(List<dynamic> sensors) {
    for (final sensor in sensors) {
      // TODO: do we even need to retrieve sensor instances on client side? -- I think so, for the sensors that connects to the edge-device (client?)
      try {
        final sensorType =
            SensorTypeModel.fromMap(sensor['sensors_id']['model']);
        final sensorDevice = SensorInstanceModel.fromMap(sensor['sensors_id']);

        if (_sensorTypes.any((s) => s.id == sensorType.id)) {
          // Find the study in the list and remove it
          _sensorTypes.removeWhere((s) => s.id == sensorType.id);
        }
        _sensorTypes.add(sensorType);

        final sensorInst =
            SensorInstance.create(this, sensorDevice, sensorType);

        // Register scan function to keep track of sensors we've physically encountered
        if (!registeredScanSubscription.containsKey(sensorType)) {
          registeredScanSubscription[sensorType] =
              sensorInst.scanForSensor((deviceID) {
            log('Device of type ${sensorType.id} found from scan: $deviceID');
            if (physicalSensors[sensorType.id] == null ||
                !physicalSensors[sensorType.id]!.contains(deviceID) &&
                    sensorInstances.any(
                        (s) => s.getSensorInstance().deviceID == deviceID)) {
              physicalSensors[sensorType.id] = [
                ...?physicalSensors[sensorType.id],
                deviceID
              ];
            }

            notifyListeners();
          });
        }

        // Create sensor instance and add to list of sensor instances
        sensorInstances.add(sensorInst);
      } catch (e) {
        log('Error parsing sensor: ${e.toString()}');
      }
    }

    notifyListeners();
  }

  // // A method to add a child instance to the list
  // static void addSensorInstanceToList(SensorInstance sensor) {
  //   sensorInstances.add(sensor);
  // }
}
Leave a Comment