plug_location.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import 'dart:async';
  2. import 'package:get/get.dart';
  3. import 'package:grpc/grpc.dart';
  4. import 'package:trackoffical_app/service/api.dart';
  5. import 'package:trackoffical_app/service/app.dart';
  6. import 'package:trackoffical_app/utils.dart';
  7. import '../../../logger.dart';
  8. import '../plug.dart';
  9. import 'game_instance_std.dart';
  10. class PlugLocation extends Plug{
  11. PlugLocation(GameInstanceStd ins){
  12. instance=ins;
  13. final lastInfo = ins.model.gameSrcState.value.pbGameSave.gameGpsInfos;
  14. if(lastInfo.isNotEmpty){
  15. for(var one in lastInfo){
  16. var p = MPosition();
  17. p.latitude = one.latitude;
  18. p.longitude = one.longitude;
  19. p.directionRadian = one.directionRadian;
  20. p.timestamp = one.gpsTime.toModel();
  21. _addOnePosition(p, false);
  22. }
  23. }
  24. }
  25. GameInstanceStd? instance;
  26. final _app = App.to;
  27. final _api = ApiService.to;
  28. final _toUpload = <MPosition>[];
  29. bool get isEnableGPSTrack => _app.userProfile.gameSettingsGpsTrack.value;
  30. Future<void> uploadPosition() async {
  31. final ins = instance;
  32. if(ins!= null && isEnableGPSTrack){
  33. final model = ins.model;
  34. final gameId = model.gameSrcState.value.pbGameData.gameId;
  35. final data = <MPosition>[];
  36. final distanceMeter = model.myPositionHistoryLen.value.m;
  37. final paceSecondKm = model.paceSecondKm;
  38. if(_toUpload.isNotEmpty){
  39. data.addAll(_toUpload);
  40. try {
  41. await _api.gameGpsUpload(
  42. gameId, data, distanceMeter.round(), paceSecondKm.value.inSeconds);
  43. _toUpload.clear();
  44. } catch (e) {
  45. warn('GameId[$gameId]上传位置失败: $e');
  46. }
  47. }
  48. }
  49. }
  50. void onRcvPosition(MPosition p, GameInstanceStd ins) {
  51. p.directionRadian = -ins.compassRadiansFused.value;
  52. _toUpload.add(p);
  53. _addOnePosition(p, true);
  54. }
  55. void _addOnePosition(MPosition p, bool isSaveToDB){
  56. final ins = instance;
  57. if(ins==null){
  58. return;
  59. }
  60. MPosition? last;
  61. if (ins.model.myPositionHistory.isNotEmpty) {
  62. last = ins.model.myPositionHistory.last;
  63. }
  64. ins.model.myPositionHistory.add(p);
  65. ins.gameMapData.worldToPixel(p).then((offset){
  66. ins.model.myPositionOnMapHistory.add(offset);
  67. });
  68. ins.gameMapData.mapPackage?.isInHotZone(p).then((value) =>
  69. ins.model.zone.value=value
  70. );
  71. final startAt=ins.model.startAt;
  72. if(startAt==null){
  73. return;
  74. }
  75. final endAt = ins.model.endAt;
  76. if(endAt != null){
  77. if(p.timestamp.isAfter(endAt)){
  78. return;
  79. }
  80. }
  81. if(p.timestamp.isBefore(startAt)){
  82. return;
  83. }
  84. // 只记录开始点后
  85. if (last!=null) {
  86. final dis = p.distance(last);
  87. ins.model.myPositionHistoryLen.value += dis;
  88. }
  89. if(isSaveToDB){
  90. ins.model.gameSrcState.value.pbGameSave.gameGpsInfos.add(p.toPb2());
  91. }
  92. }
  93. Future<void> loopUploadPosition() async {
  94. while (isActive) {
  95. await Future.delayed(1.seconds);
  96. await uploadPosition();
  97. }
  98. }
  99. Future<void> _makeSureUploadAll() async {
  100. while (true) {
  101. try {
  102. await uploadPosition();
  103. return;
  104. } on GrpcError catch (e) {
  105. if (e.code != StatusCode.unavailable) {
  106. return;
  107. }
  108. error(e);
  109. } catch (e) {
  110. error(e);
  111. return;
  112. }
  113. await Future.delayed(100.milliseconds);
  114. }
  115. }
  116. @override
  117. Future<void> init() async{
  118. final locationStream = _app.locationStream;
  119. listenStream(locationStream, (p) {
  120. final ins = instance;
  121. if(ins!= null){
  122. onRcvPosition(p, ins);
  123. }
  124. });
  125. _app.locationStart(500.milliseconds, 1);
  126. _app.getPosition(timeout: 5.seconds).then((p) {
  127. final ins = instance;
  128. if(ins!= null){
  129. onRcvPosition(p, ins);
  130. }
  131. });
  132. loopUploadPosition();
  133. }
  134. @override
  135. Future<void> onClose() async{
  136. _app.locationStop();
  137. await _makeSureUploadAll();
  138. instance=null;
  139. }
  140. }