api.dart 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import 'dart:async';
  2. import 'dart:core';
  3. import 'dart:typed_data';
  4. import 'package:app_business/app_config.dart';
  5. import 'package:app_business/generated/base.pb.dart' as pb;
  6. import 'package:app_business/generated/google/protobuf/duration.pb.dart' as pb;
  7. import 'package:app_business/generated/google/protobuf/timestamp.pb.dart' as pb;
  8. import 'package:app_business/generated/track_offical.pbgrpc.dart' as pb;
  9. import 'package:app_business/service/app.dart';
  10. import 'package:grpc/grpc.dart';
  11. import 'package:track_common/model.dart';
  12. import 'package:track_common/track_common.dart';
  13. import 'abase.dart';
  14. export 'package:app_business/generated/google/protobuf/timestamp.pb.dart';
  15. export 'package:app_business/generated/track_offical.pbgrpc.dart'
  16. show ToMatchRegusterAddRequest, ToMatchRegusterListRequest;
  17. export 'package:fixnum/fixnum.dart' show Int64;
  18. typedef SmsType = pb.SmsType;
  19. typedef IdRequest = pb.IdRequest;
  20. extension _ImageExt on pb.NetImage {
  21. NetImage toModel() {
  22. return NetImage(url, md5);
  23. }
  24. }
  25. extension DateTimeExt on DateTime? {
  26. pb.Timestamp toPb() {
  27. if (this != null) {
  28. return pb.Timestamp.fromDateTime(this!.toUtc());
  29. } else {
  30. return pb.Timestamp();
  31. }
  32. }
  33. }
  34. extension TSExt on pb.Timestamp {
  35. DateTime toModel() {
  36. return toDateTime(toLocal: true);
  37. }
  38. }
  39. extension DurationExt on pb.Duration {
  40. Duration toModel() {
  41. final microseconds = hasNanos() ? nanos / 1000 : 0;
  42. return Duration(
  43. seconds: seconds.toInt(), microseconds: microseconds.toInt());
  44. }
  45. }
  46. extension PositionExt on pb.Position {
  47. Position toModel() {
  48. return Position(latitude: latitude, longitude: longitude)
  49. ..altitude = altitude;
  50. }
  51. }
  52. extension PBToControlPointExt on pb.ToControlPoint {
  53. ControlPoint toModel() {
  54. final one = ControlPoint()
  55. ..areaId = sn
  56. ..intId = id
  57. ..isSuccess = isCheckSuccess
  58. ..sn = orderNo.toString()
  59. ..checkAfterPrev = checkAfterLast.toModel()
  60. ..checkAfterStart = checkAfterStart.toModel()
  61. ..checkDistanceAfterPrev = disAfterLast.meter
  62. ..distanceStraightToPrev = disStraightAfterLast.meter
  63. ..paceAfterPrev = Pace.perKm(paceAfterLast.seconds)
  64. ..paceAfterStart = Pace.perKm(paceAfterStart.seconds)
  65. ..position = ciPosition.toModel();
  66. if (cType == pb.CType.BeginType) {
  67. one.isStart = true;
  68. }
  69. if (cType == pb.CType.EndType) {
  70. one.isFinish = true;
  71. }
  72. return one;
  73. }
  74. }
  75. class ApiService extends IService {
  76. ClientChannel? channel;
  77. @override
  78. Future<void> init() async {
  79. channel = _newChannel();
  80. }
  81. ClientChannel _newChannel() {
  82. return ClientChannel(
  83. AppConfig.apiHost,
  84. port: AppConfig.apiPort,
  85. options: const ChannelOptions(credentials: ChannelCredentials.secure()
  86. // ChannelCredentials.insecure()
  87. ),
  88. );
  89. }
  90. pb.ApiToClient get stub {
  91. return _newStub(timeout: 10.seconds);
  92. }
  93. pb.ApiToClient _newStub({Duration? timeout, ClientChannel? channel}) {
  94. if (this.channel == null) {
  95. throw Exception('$runtimeType 未初始化');
  96. }
  97. final metadata = <String, String>{};
  98. metadata['version'] = _appVersion;
  99. if (token != null) {
  100. metadata['token'] = token!;
  101. }
  102. // debug("token: $token");
  103. return pb.ApiToClient(channel ?? this.channel!,
  104. options: CallOptions(
  105. metadata: metadata,
  106. timeout: timeout,
  107. ));
  108. }
  109. String get _appVersion => Get.find<AppService>().appVersion;
  110. set token(String? v) {
  111. Get.find<AppService>().token.val = v ?? '';
  112. }
  113. String? get token {
  114. final app = Get.find<AppService>();
  115. final token = app.token.val;
  116. if (token.isEmpty) {
  117. return null;
  118. }
  119. return token;
  120. }
  121. // 获取短信验证码
  122. Future<void> authSendCodeToPhone(String phone, SmsType smsType) async {
  123. info('authSendCodeToPhone [$phone]');
  124. await stub.toSendCodeToPhoneV2(pb.ToSendCodeToPhoneRequestV2()
  125. ..phone = phone
  126. ..smsType = smsType);
  127. }
  128. // 场控端_登录
  129. Future<void> signIn(String userCode, String password, String ip) async {
  130. final r = await stub.toSignInV2(pb.ToSignInRequestV2()
  131. ..userCode = userCode
  132. ..password = password
  133. ..ip = ip);
  134. token = r.token;
  135. debug('sign in success: $token');
  136. }
  137. // 场控端_登出
  138. void signOut() {
  139. stub.toSignOutV2(pb.DefaultRequest());
  140. token = null;
  141. }
  142. Future<Duration> getSmsSendLeftTime(String phone) async {
  143. final r = await stub
  144. .toGetSmsSendLeftTimeV2(pb.GetSmsSendLeftTimeRequest()..phone = phone);
  145. info('getSmsSendLeftTime: $phone - ${r.second}s');
  146. return r.second.seconds;
  147. }
  148. Future<List<MapInfo>> getMapList(int limit, int offset) async {
  149. final r = await stub.toMapListV2(pb.MapListRequestV2()
  150. ..limit = limit
  151. ..offset = offset);
  152. return r.list
  153. .map((e) => MapInfo(e.mapId, e.name, e.distance.meter, e.description,
  154. e.mapScaleNumber, e.image.toModel()))
  155. .toList();
  156. }
  157. Future<BinReader> getBinReaderByMd5(Uint8List md5) async {
  158. final stream =
  159. stub.toGetBinaryByMd5(pb.ToGetBinaryByMd5Request()..md5 = md5);
  160. final controller = StreamController<List<int>>();
  161. controller.onCancel = () {
  162. stream.cancel();
  163. };
  164. Future<void> rcv() async {
  165. try {
  166. await for (final one in stream) {
  167. controller.add(one.data);
  168. }
  169. } finally {
  170. controller.close();
  171. stream.cancel();
  172. }
  173. }
  174. rcv();
  175. stream.headers.then((value) => debug(value));
  176. final headers = await stream.headers;
  177. final lenStr = headers['all-length']!;
  178. final length = int.parse(lenStr);
  179. final nonce = headers['nonce']!;
  180. final ext = headers['ext']!;
  181. return BinReader(
  182. data: controller.stream, length: length, ext: ext, nonce: nonce);
  183. }
  184. Future<void> eventEdit(int id, EventRegisterInfo event) async {
  185. await stub.toMatchRegusterEdit(pb.ToMatchRegusterEditRequest()
  186. ..id = id
  187. ..regName = event.name
  188. ..startAt = event.startAt.toPb()
  189. ..stopAt = event.stopAt.toPb()
  190. ..isQueryPwd = event.password != null
  191. ..queryPasswd = event.password ?? '');
  192. }
  193. }
  194. class EventRegisterInfo {
  195. var id = 0;
  196. var name = '';
  197. var startAt = DateTime.now();
  198. var stopAt = DateTime.now();
  199. String? password;
  200. }