summaryrefslogtreecommitdiff
path: root/lib/utils/esense_input.dart
blob: b738664e12d8e7014b024470de08a14b71905503 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import 'dart:async';
import 'dart:io';

import 'package:esense_flutter/esense.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:sense_the_rhythm/models/arrow_direction.dart';
import 'package:sense_the_rhythm/models/input_direction.dart';

class ESenseInput {
  static final instance = ESenseInput._();

  ESenseManager eSenseManager = ESenseManager('unknown');
  ValueNotifier<String> deviceStatus = ValueNotifier('Disconnected');
  StreamSubscription? subscription;

  String eSenseDeviceName = '';
  bool connected = false;
  bool sampling = false;

  int sampleRate = 20;

  InputDirection inputDirection = InputDirection();
  int x = 0;
  int y = 0;
  int z = 0;

  ESenseInput._() {
    _listenToESense();
  }

  Future<bool> _askForPermissions() async {
    if (!Platform.isAndroid && !Platform.isIOS) return false;
    if (!await Permission.bluetooth.serviceStatus.isEnabled) {
      deviceStatus.value = "Bluetooth is disabled!";
      return false;
    }
    if (!(await Permission.bluetoothScan.request().isGranted &&
        await Permission.bluetoothConnect.request().isGranted &&
        await Permission.bluetooth.request().isGranted)) {
      print(
          'WARNING - no permission to use Bluetooth granted. Cannot access eSense device.');
      deviceStatus.value = "Insufficiant Permissions";
      return false;
    }
    // for some strange reason, Android requires permission to location for Bluetooth to work.....?
    if (Platform.isAndroid) {
      if (!(await Permission.locationWhenInUse.request().isGranted)) {
        print(
            'WARNING - no permission to access location granted. Cannot access eSense device.');
        deviceStatus.value = "Insufficiant Permissions";
        return false;
      }
    }
    return true;
  }

  void _listenToESense() {
    // if you want to get the connection events when connecting,
    // set up the listener BEFORE connecting...
    eSenseManager.connectionEvents.listen((event) {
      print('CONNECTION event: $event');

      // when we're connected to the eSense device, we can start listening to events from it
      // if (event.type == ConnectionType.connected) _listenToESenseEvents();

      connected = false;
      switch (event.type) {
        case ConnectionType.connected:
          deviceStatus.value = 'Connected';
          connected = true;
          _startListenToSensorEvents();
          break;
        case ConnectionType.unknown:
          deviceStatus.value = 'Unknown';
          break;
        case ConnectionType.disconnected:
          deviceStatus.value = 'Disconnected';
          sampling = false;
          _pauseListenToSensorEvents();
          break;
        case ConnectionType.device_found:
          deviceStatus.value = 'Device_found';
          break;
        case ConnectionType.device_not_found:
          deviceStatus.value = 'Device_not_found';
          break;
      }
    });
  }

  Stream<ButtonEventChanged> buttonEvents() {
    return eSenseManager.eSenseEvents
        .where((event) => event.runtimeType == ButtonEventChanged)
        .cast();
  }

  void _startListenToSensorEvents() async {
    // // any changes to the sampling frequency must be done BEFORE listening to sensor events
    print('setting sampling frequency...');
    bool successs = await eSenseManager.setSamplingRate(sampleRate);
    if (successs) {
      print('setSamplingRate success');
    } else {
      print('setSamplingRate fail');
    }

    // subscribe to sensor event from the eSense device
    subscription = eSenseManager.sensorEvents.listen((event) {
      // print('SENSOR event: $event');
      if (event.gyro != null) {
        _parseGyroData(event.gyro!);
      }
    });
    sampling = true;
  }

  void _pauseListenToSensorEvents() async {
    subscription?.cancel();
    sampling = false;
  }

  void _parseGyroData(List<int> data) {
    // Float value in deg/s = Gyro value / Gyro scale factor
    // The default configuration is +- 500deg/s for the gyroscope.
    x = (x + (15 * data[0] ~/ (500 * sampleRate))) % 360;
    y = (y + (15 * data[1] ~/ (500 * sampleRate))) % 360;
    z = (z + (15 * data[2] ~/ (500 * sampleRate))) % 360;
    print('$x, $y, $z');
    // print('${(z.toDouble() / 500.0 * (1.0 / sampleRate.toDouble())) * 7.5}');
    // print('${z.toDouble() / 500.0 * (1.0 / 10.0)}');
  }

  void resetAngles() {
    inputDirection.reset();
    x = 0;
    y = 0;
    z = 0;
  }

  InputDirection getInputDirection(ArrowDirection expect) {
    inputDirection.up = z > 180 && z < 340;
    inputDirection.down = z > 20 && z < 180;
    inputDirection.left = y > 0 && y < 180;
    inputDirection.right = y > 180 && y < 360;

    if (expect == ArrowDirection.up && inputDirection.up ||
        expect == ArrowDirection.down && inputDirection.down) {
      y = 0;
      print("ehit");
    }
    if (expect == ArrowDirection.left && inputDirection.left ||
        expect == ArrowDirection.right && inputDirection.right) {
      z = 0;
      print("ehit");
    }

    return inputDirection;
  }

  Future<void> connectToESense(String deviceName) async {
    if (!connected) {
      bool permissionSuccessfull = await _askForPermissions();
      if (!permissionSuccessfull) return;
      print('Trying to connect to eSense device namend \'$deviceName\'');
      eSenseDeviceName = deviceName;
      eSenseManager.deviceName = deviceName;
      bool connecting = await eSenseManager.connect();
      print(
          'Trying to connect to eSense device namend \'${eSenseManager.deviceName}\'');

      deviceStatus.value = connecting ? 'connecting...' : 'connection failed';
      print(deviceStatus.value);
    }
  }
}