sensor.dart 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. import 'dart:async';
  2. import 'package:flutter/services.dart';
  3. import 'package:permission_handler/permission_handler.dart';
  4. import 'messages.dart' as msg;
  5. class Sensor {
  6. static final msg.SensorApi api = msg.SensorApi();
  7. static const _eventChannelLocation = EventChannel("com.beswell.sensor.event/location");
  8. static const _eventChannelOrientation = EventChannel("com.beswell.sensor.event/orientation");
  9. static const _eventChannelHRM = EventChannel("com.beswell.sensor.event/HRM");
  10. /// 类型List<Map<String, dynamic>>,每个Map中包括
  11. /// String address;
  12. /// String name;
  13. /// int rssi;
  14. static const _eventChannelSportWearScanResult = EventChannel("com.beswell.sensor.event/SportWearScanResult");
  15. /// 类型List<Map<String, dynamic>>,每个Map中包括
  16. /// String address;
  17. /// String name;
  18. /// int rssi;
  19. static const _eventChannelSportWearConnected = EventChannel("com.beswell.sensor.event/SportWearConnected");
  20. static Stream<dynamic>? _locationStream;
  21. static Stream<Position> get locationStream {
  22. _locationStream ??= _eventChannelLocation.receiveBroadcastStream();
  23. return _locationStream!.map((event) {
  24. final p0 = msg.Position.decode(event);
  25. return Position()
  26. ..longitude=p0.longitude??0
  27. ..latitude=p0.latitude??0
  28. ..altitude=p0.altitude??0
  29. ..speed=p0.speed??0
  30. ..accuracy=p0.accuracy??0
  31. ..bearing=p0.bearing??0
  32. ..tsMs=p0.timeMs??0
  33. ;
  34. } );
  35. }
  36. static Stream<dynamic>? _orientationStream;
  37. static Stream<Orientation> get orientationStream {
  38. _orientationStream??=_eventChannelOrientation.receiveBroadcastStream();
  39. return _orientationStream!.map((event) {
  40. final r = msg.Orientation.decode(event);
  41. return Orientation()
  42. ..x = r.x ?? 0
  43. ..y = r.y ?? 0
  44. ..z = r.z ?? 0;
  45. } );
  46. }
  47. static Future<Position> getCurrentPosition({bool force = false}) async {
  48. final r = await api.getCurrentPosition(force);
  49. return Position()
  50. ..longitude = r.longitude ?? 0
  51. ..latitude = r.latitude ?? 0
  52. ..altitude = r.altitude ?? 0;
  53. }
  54. static Future<bool> isLocationServiceOpen()async {
  55. return api.isLocationServiceOpen();
  56. }
  57. static Stream<List<SportWear>> get sportWearScanResultStream {
  58. return _eventChannelSportWearScanResult.receiveBroadcastStream().map((event) {
  59. final l = event as List<dynamic>;
  60. return l.map((e){
  61. final m = e as Map<dynamic, dynamic>;
  62. return SportWear()
  63. ..name=m['name']
  64. ..address=m['address']
  65. ..rssi=m['rssi']
  66. ;
  67. }
  68. ).toList();
  69. } );
  70. }
  71. static Future<void> sportWearScanStart() async{
  72. var status = await Permission.bluetoothScan.status ;
  73. if (status.isDenied){
  74. if(await Permission.bluetoothScan.request().isDenied){
  75. throw Exception('无扫描权限');
  76. }
  77. }
  78. status = await Permission.bluetooth.status ;
  79. if (status.isDenied){
  80. if(await Permission.bluetooth.request().isDenied){
  81. throw Exception('无蓝牙权限');
  82. }
  83. }
  84. status = await Permission.bluetoothConnect.status ;
  85. if (status.isDenied){
  86. if(await Permission.bluetoothConnect.request().isDenied){
  87. throw Exception('无蓝牙权限');
  88. }
  89. }
  90. status = await Permission.location.status ;
  91. if (status.isDenied){
  92. if(await Permission.location.request().isDenied){
  93. throw Exception('无定位权限');
  94. }
  95. }
  96. if (await api.askEnableBluetooth()){
  97. api.sportWearScanStart();
  98. }else{
  99. throw Exception('未开启蓝牙');
  100. }
  101. }
  102. static Future<void> sportWearScanStop() async{
  103. await api.sportWearScanStop();
  104. }
  105. static Future<void> sportWearConnect(SportWear wear)async{
  106. await api.sportWearConnect(msg.SportWear()..address=wear.address);
  107. }
  108. static Future<void> sportWearDisconnect(SportWear wear)async{
  109. await api.sportWearDisconnect(msg.SportWear()..address=wear.address);
  110. }
  111. static Stream<List<SportWear>> get sportWearConnectedStream {
  112. return _eventChannelSportWearConnected.receiveBroadcastStream().map((event) {
  113. final l = event as List<dynamic>;
  114. return l.map((e){
  115. final m = e as Map<dynamic, dynamic>;
  116. return SportWear()
  117. ..name=m.containsKey('name')?m['name']:''
  118. ..address=m['address']
  119. ..rssi=m.containsKey('rssi')?m['rssi']:0
  120. ;
  121. }
  122. ).toList();
  123. });
  124. }
  125. static Stream<HeartRateMeasurement> get sportWearHeartRateMeasurementStream {
  126. return _eventChannelHRM.receiveBroadcastStream().map((event) {
  127. try{
  128. final e = msg.HeartRateMeasurement.decode(event);
  129. return HeartRateMeasurement()
  130. ..sportWearAddress=e.deviceMac ??''
  131. ..heartRate=e.heartRate??0
  132. ..contactDetected=e.contactDetected??true
  133. ..rrIntervals=e.rrIntervals?.map((rr) => rr??0).toList()??List.empty()
  134. ..timestamp= DateTime.fromMillisecondsSinceEpoch(
  135. e.timestampMill?? DateTime.now().millisecondsSinceEpoch);
  136. }catch(e){
  137. print('心率接收错误:$e');
  138. return HeartRateMeasurement();
  139. }
  140. } );
  141. }
  142. static Future<void> locationStart(Duration minTime, double minDistanceM) async {
  143. var status = await Permission.location.status ;
  144. if (status.isDenied){
  145. if(await Permission.location.request().isDenied){
  146. throw Exception('无定位权限');
  147. }
  148. }
  149. await api.locationStart(minTime.inMilliseconds, minDistanceM);
  150. }
  151. }
  152. class Orientation {
  153. double x = 0;
  154. double y = 0;
  155. double z = 0;
  156. }
  157. class Position {
  158. double latitude = 0;
  159. double longitude = 0;
  160. double altitude = 0;
  161. double speed=0;
  162. double accuracy=0;
  163. double bearing=0;
  164. int tsMs=0;
  165. }
  166. class SportWear{
  167. String address='';
  168. String name='';
  169. int rssi=0;
  170. }
  171. class HeartRateMeasurement{
  172. String sportWearAddress='';
  173. int heartRate=0;
  174. /// 是否已检测到传感器接触信息
  175. bool contactDetected=false;
  176. /// RR间隔的可选列表,每个间隔为1/1024秒
  177. List<int> rrIntervals=List.empty();
  178. DateTime timestamp=DateTime.now();
  179. }