| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import 'dart:async';
- import 'package:grpc/grpc.dart';
- import 'package:trackoffical_app/logger.dart';
- import 'package:trackoffical_app/service/api.dart';
- import 'package:trackoffical_app/service/app.dart';
- import 'package:trackoffical_app/service/game/game_model.dart';
- import 'package:trackoffical_app/utils.dart';
- import 'package:simple_kalman/simple_kalman.dart';
- import '../../model/game_map.dart';
- import '../../model/m_position.dart';
- import 'plug.dart';
- import 'package:get/get.dart';
- import 'package:trackoffical_app/pb.dart' as pb;
- class PlugLocation extends Plug {
- StreamSubscription<MPosition>? _locationSubscription;
- final GameModel _model = Get.find();
- final GameMap _gameMap;
- final kalmanLat = SimpleKalman(errorMeasure: 360, errorEstimate: 150, q: 0.9);
- final kalmanLon = SimpleKalman(errorMeasure: 360, errorEstimate: 150, q: 0.9);
- final _toUpload = <MPosition>[];
- PlugLocation({
- required GameMap gameMap,
- required List<pb.GameGpsInfo> lastInfo,
- }) : _gameMap = gameMap
- {
- if(lastInfo.isNotEmpty){
- for(var one in lastInfo){
- var p = MPosition();
- p.latitude = one.latitude;
- p.longitude = one.longitude;
- p.directionRadian = one.directionRadian;
- p.timestamp = one.gpsTime.toModel();
- _addOnePosition(p);
- }
- }
- }
- final ApiService _api = Get.find();
- var _lastPositionTime = DateTime(2000);
- final _app = App.to;
- @override
- Future<void> init() async {
- // await setLocationSettings(
- // askForGooglePlayServices: false,
- // askForPermission: true,
- // useGooglePlayServices: false,
- // accuracy: LocationAccuracy.high,
- // interval: 500,
- // askForGPS: true
- // );
- //
- // final locationStream = onLocationChanged();
- final locationStream = _app.locationStream;
- _app.locationStart(500.milliseconds, 0);
- _locationSubscription?.cancel();
- _locationSubscription = locationStream.listen((event) {
- onRcvPosition(event);
- // final lat = event.latitude;
- // final lon = event.longitude;
- // if (lat != null && lon != null) {
- // final p = MPosition(latitude: lat, longitude: lon);
- // p.timestamp = _app.now;
- // onRcvPosition(p);
- // }
- });
- final lastPosition = _model.myPosition.value;
- if (lastPosition != null) {
- _gameMap
- .worldToPixel(lastPosition)
- .then((value) => _model.myPositionOnMap.value = value);
- }
- loopUploadPosition();
- }
- void _addOnePosition(MPosition p){
- if (_model.myPositionHistory.isNotEmpty) {
- final lastP = _model.myPositionHistory.last;
- final dis = p.distance(lastP);
- _model.myPositionHistoryLen.value += dis;
- }
- _model.myPositionHistory.add(p);
- }
- void onRcvPosition(MPosition p) {
- p.directionRadian = -_model.compassRadiansFused.value;
- // // 卡尔曼
- // if(_isFirstP){
- // for(var i = 0; i<10; i++){
- // p.latitude = kalmanLat.filtered(p.latitude);
- // p.longitude = kalmanLon.filtered(p.longitude);
- // }
- // _isFirstP=false;
- // }
- //
- // p.latitude = kalmanLat.filtered(p.latitude);
- // p.longitude = kalmanLon.filtered(p.longitude);
- // info('${p.latitude} ${p.longitude}');
- _model.myPosition.value = p;
- _model.myPositionHistoryTmp.add(p);
- if(_model.myPositionHistoryTmp.length>=20){
- _model.myPositionHistoryTmp.removeAt(0);
- }
- _toUpload.add(p);
- _gameMap
- .worldToPixel(p)
- .then((value) => _model.myPositionOnMap.value = value);
- // final pTest = MPosition( latitude: 36.649713,
- // longitude:117.052860,);
- _gameMap.mapPackage?.isInHotZone(p).then((value) =>
- _model.zone.value=value
- );
- if (_model.isStarted && (!_model.isFinish)) {
- final now = DateTime.now();
- if (now.difference(_lastPositionTime) > 1.seconds) {
- _addOnePosition(p);
- _model.gameSrcState.value.pbGameSave.gameGpsInfos.add(p.toPb2());
- _lastPositionTime = now;
- }
- }
- }
- Future<void> loopUploadPosition() async {
- while (isActive) {
- await Future.delayed(1.seconds);
- await uploadPosition();
- }
- }
- Future<void> uploadPosition() async {
- final gameId = _model.gameSrcState.value.pbGameData.gameId;
- final data = <MPosition>[];
- final distanceMeter = _model.myPositionHistoryLen.value.m;
- final paceSecondKm = _model.paceSecondKm;
- if(_toUpload.isNotEmpty){
- data.addAll(_toUpload);
- try {
- await _api.gameGpsUpload(
- gameId, data, distanceMeter.round(), paceSecondKm.value.inSeconds);
- _toUpload.clear();
- } catch (e) {
- warn('GameId[$gameId]上传位置失败: $e');
- }
- }
- }
- Future<void> _makeSureUploadAll() async {
- while (true) {
- try {
- await uploadPosition();
- return;
- } on GrpcError catch (e) {
- if (e.code != StatusCode.unavailable) {
- return;
- }
- error(e);
- } catch (e) {
- error(e);
- return;
- }
- await Future.delayed(100.milliseconds);
- }
- }
- @override
- Future<void> close() async {
- await _makeSureUploadAll();
- super.close();
- _app.locationStop();
- _locationSubscription?.cancel();
- _locationSubscription = null;
- debug('[位置插件]已关闭');
- }
- }
|