Untitled
unknown
plain_text
a year ago
9.1 kB
4
Indexable
import 'dart:developer'; import 'dart:async'; import 'dart:io'; import 'package:meta/meta.dart'; 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/utils/utils.dart'; import 'package:self_science_station/sensor/polar_api.dart'; import 'package:self_science_station/provider/sensor_provider.dart'; import 'package:provider/provider.dart'; import 'package:polar/polar.dart'; // SensorInstance is the class for all sensor instances and parent-class for all mobile SDKs/APIs class SensorInstance { //final sp = Provider.of<SensorProvider>(context, listen: false); // // The list storing all the child instances // static List<SensorInstance> sensorInstances = []; // // Lists of the Sensor Model details -- no need for this i believe // final List<SensorInstanceModel> _sensorInstances = []; // final List<SensorTypeModel> _sensorTypes = []; bool isConnected = false; bool isConnecting = false; // InstanceModel and TypeModel are final because their values should not be change once the instance is created final SensorProvider sp; final SensorInstanceModel _sInstance; final SensorTypeModel _sType; // Allows for executing callbacks for a given sensor state final Map<SensorState, Function> _callbacks = {}; // SensorState and Availability will describe the accessibility of the sensor SensorState sState = SensorState.init; SensorAvailability sAvailability = SensorAvailability.init; // Constructor (without subclass-instance creation) SensorInstance(this.sp, this._sInstance, this._sType) { print("New Sensor created in SensorProvider without any subclass assigned"); print( "New sensor instance instance created: name ${_sType.vendor} ${_sType.name}: ${_sInstance.deviceID}"); _onSensorChange(); } // Factory constructor creating a subclass instance for the particular sensor factory SensorInstance.create(SensorProvider sProvider, SensorInstanceModel sInstance, SensorTypeModel sType) { // try { // // Add sensor type to the list of sensor types // if (_sensorTypes.any((s) => s.id == sType.id)) { // // Find the sensor in the list and remove it -- why is this step necessary? to sort list? // _sensorTypes.removeWhere((s) => s.id == sType.id); // } // _sensorTypes.add(sType); // // Add sensor instance to the list of sensor instances // if (_sensorInstances.any((s) => s.deviceID == sInstance.deviceID)) { // // Find the sensor in the list and remove it -- why is this step necessary? to sort list? // _sensorInstances.removeWhere((s) => s.deviceID == sInstance.deviceID); // } // _sensorInstances.add(sInstance); // } catch (e) { // log('Error parsing sensor: ${e.toString()}'); // } // Initialize sensor instance with state and device information SensorState sState = SensorState.disconnected; SensorAvailability sAvailability = SensorAvailability.available; String sVendor = sType.vendor; String sDeviceName = sType.name; String sDeviceID = sInstance.deviceID; // Create and return a child-instance for the particular sensor based on Vendor SensorInstance sDevice; switch (sVendor) { case "fitbit": // TODO: log("Fitbit Sensor"); log("Fitbit is webbased"); sDevice = SensorInstance(sProvider, sInstance, sType); break; case "withings": // TODO: log("Withings Sensor"); log("Withings is webbased"); sDevice = SensorInstance(sProvider, sInstance, sType); break; case "polar": log("Polar Sensor"); sDevice = PolarAPI( sProvider, sInstance, sType, sInstance.deviceID, sType.name); break; default: // TODO: log("This sensor has not been initialized correctly."); sDevice = SensorInstance(sProvider, sInstance, sType); break; } // // Add the new sensor instance to the static list of instances //SensorProvider.addSensorInstanceToList(sDevice); return sDevice; } // // A method to add a child instance to the list // static void addSensorInstanceToList(SensorInstance sensor) { // sensorInstances.add(sensor); // } void _onSensorChange() { sp.updateEverything(); } Future<bool> startRecording(String? recordingIdentifier) { print( "Recording from sensor ${_sInstance.id} with ID $recordingIdentifier"); onRecordingStarted(); return Future.value(true); } Future<bool> stopRecording() { print("Stopping recording from sensor ${_sInstance.id}"); onRecordingStopped(); return Future.value(true); } Future<void> emptyRecordings() async { print('Emptying recordings for sensor ${_sInstance.id}'); return Future.value(); } Future<bool> isRecording() { print("Checking if recording from sensor ${_sInstance.id}"); return Future.value(false); } Future<bool> connectSensor() async { print("Connecting sensor ${_sInstance.id}"); onConnected(); return Future.value(true); } // Tries to connect, waits for specified timeout, bails if hasn't connected yet void connectSensorWithTimeout(Duration timeout) async { print("Connecting sensor ${_sInstance.id} with timeout $timeout"); onConnecting(); Future.delayed(timeout, () { if (!isConnected) { onConnectFail(); } }); } Future<bool> disconnectSensor() { print("Disconnecting sensor ${_sInstance.id}"); onDisconnected(); return Future.value(true); } Future<void> resetSensor() { print("Resetting sensor ${_sInstance.id}"); return Future.value(); } StreamSubscription<dynamic> scanForSensor(Function onDeviceFound) { print("Scanning for sensor ${_sInstance.id}"); onDeviceFound(); return const Stream.empty().listen((event) {}); } @protected void onRecordingStarted() { print("Started recording from sensor ${_sInstance.id}"); final prevState = sState; if (sState == SensorState.connected_idle) { sState = SensorState.connected_acquiring; } else if (sState == SensorState.disconnected) { sState = SensorState.disconnected_acquiring; } handleStateChange(prevState, sState); } @protected void onRecordingStopped() { print("Stopped recording from sensor ${_sInstance.id}"); final prevState = sState; if (sState == SensorState.connected_acquiring) { sState = SensorState.connected_idle; } else if (sState == SensorState.disconnected_acquiring) { sState = SensorState.disconnected; } handleStateChange(prevState, sState); } @protected void onConnecting() { print("Connecting sensor ${_sInstance.id}"); isConnecting = true; isConnected = false; final prevState = sState; sState = SensorState.connecting; handleStateChange(prevState, sState); } @protected void onConnected() { print("Connected sensor ${_sInstance.id}"); isConnected = true; isConnecting = false; final prevState = sState; sState = SensorState.connected_idle; handleStateChange(prevState, sState); } @protected void onDisconnected() { print("Disconnected sensor ${_sInstance.id}"); isConnected = false; isConnecting = false; final prevState = sState; sState = SensorState.disconnected; handleStateChange(prevState, sState); } @protected void onConnectFail() { print("Failed to connect to sensor ${_sInstance.id}"); onDisconnected(); } @protected void onSensorError() { print("Error on sensor ${_sInstance.id}!"); isConnected = false; isConnecting = false; final prevState = sState; sState = SensorState.error; handleStateChange(prevState, sState); } void handleStateChange(SensorState prevState, SensorState newState) { // Call the callback for the new state if (_callbacks.containsKey(newState)) { _callbacks[newState]!(prevState, newState); } sp.updateEverything(); } // Trigger a runtime callback when the sensor enters any state in the list provided void registerCallback(List<SensorState> states, Function callback) { for (final state in states) { _callbacks[state] = callback; } } Future<List<int>> fetchData(String? recordingIdentifier) { print( 'Fetching from sensor ${_sInstance.id} for recording $recordingIdentifier'); return Future.value([]); } SensorInstanceModel getSensorInstance() { return _sInstance; } SensorTypeModel getTypeModel() { return _sType; } void checkSensorAvailability() { //TODO: print("Checking Sensor Availability"); } } // Structs enum SensorState { connecting, connected_idle, connected_acquiring, disconnected_acquiring, // offline acquisition disconnected, error, init } enum SensorAvailability { available, // ready for use unavailable, // in use faulty, // cannot be used init }
Editor is loading...
Leave a Comment