api.dart 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import 'dart:async';
  2. import 'dart:typed_data';
  3. import 'package:common_pub/model/game_map.dart';
  4. import 'package:get/get.dart';
  5. import 'package:grpc/grpc.dart';
  6. import '../logger.dart';
  7. import 'app.dart';
  8. import '../global_var.dart';
  9. import 'package:common_pub/pb.dart' as pb;
  10. export 'package:common_pub/pb.dart';
  11. typedef SmsType = pb.SmsType;
  12. class ApiService extends GetxService{
  13. static ApiService get to => Get.find();
  14. AppService get app => AppService.to;
  15. ClientChannel? channel;
  16. String get _appVersion => app.appVersion;
  17. Future<ApiService> init()async{
  18. channel = _newChannel();
  19. await syncTime();
  20. return this;
  21. }
  22. String? get token {
  23. final out = app.userProfile.token.val;
  24. if (out.isEmpty) {
  25. return null;
  26. }
  27. return out;
  28. }
  29. set token(String? v) {
  30. app.userProfile.token.val = v ?? '';
  31. }
  32. ClientChannel _newChannel(){
  33. return ClientChannel(
  34. GlobalVar.apiHost,
  35. port: GlobalVar.apiPort,
  36. options: const ChannelOptions(credentials:
  37. ChannelCredentials.secure()
  38. // ChannelCredentials.insecure()
  39. ),
  40. );
  41. }
  42. pb.ApiToAppClient _newStub({Duration? timeout, ClientChannel? channel}){
  43. if (this.channel == null) {
  44. throw Exception('$runtimeType 未初始化');
  45. }
  46. final metadata = <String, String>{
  47. 'source': "${pb.LoginSource.ToApp.value}"
  48. };
  49. metadata['version'] = _appVersion;
  50. if (token != null) {
  51. metadata['token'] = token!;
  52. }
  53. // debug("token: $token");
  54. return pb.ApiToAppClient(channel??this.channel!,
  55. options: CallOptions(
  56. metadata: metadata,
  57. timeout: timeout,
  58. ));
  59. }
  60. pb.ApiToAppClient get stub {
  61. return _newStub(timeout: 10.seconds);
  62. }
  63. // 获取系统时间
  64. Future<DateTime> serverTime() async {
  65. final begin = DateTime.now();
  66. final r = await stub.toGetServerTime(pb.DefaultRequest());
  67. final cost = DateTime.now().difference(begin);
  68. final serverNow = DateTime.fromMillisecondsSinceEpoch(
  69. r.millisecondStamp.toInt(),
  70. isUtc: true)
  71. .toLocal();
  72. return serverNow.add(cost);
  73. }
  74. Future<void> syncTime()async{
  75. try {
  76. final serverNow = await serverTime();
  77. app.correctByServerNow(serverNow);
  78. info('服务器时间:${app.now}');
  79. } catch(e){
  80. warn("获取服务器时间失败: ", e);
  81. }
  82. }
  83. // 获取短信验证码
  84. Future<void> authSendCodeToPhone(String phone, SmsType smsType)async{
  85. info('authSendCodeToPhone [$phone]');
  86. await stub.toSendCodeToPhoneV2(pb.ToSendCodeToPhoneRequestV2()
  87. ..phone= phone
  88. ..smsType= smsType
  89. );
  90. }
  91. // 场控端_登录
  92. Future<void> signIn(String userCode, String password, String ip) async {
  93. final r = await stub.toSignInV2(pb.ToSignInRequestV2()
  94. ..userCode = userCode
  95. ..password = password
  96. ..ip = ip
  97. );
  98. token = r.token;
  99. debug('sign in success: $token');
  100. }
  101. // 场控端_登出
  102. void signOut(){
  103. stub.toSignOutV2(pb.DefaultRequest());
  104. token = null;
  105. }
  106. Future<Duration> getSmsSendLeftTime(String phone)async{
  107. final r = await stub.toGetSmsSendLeftTimeV2(pb.GetSmsSendLeftTimeRequest()..phone= phone);
  108. info('getSmsSendLeftTime: $phone - ${r.second}s');
  109. return r.second.seconds;
  110. }
  111. Future<BinReader> getBinReaderByMd5(Uint8List md5) async {
  112. final stream = stub.toGetBinaryByMd5(pb.ToGetBinaryByMd5Request()..md5=md5);
  113. final controller = StreamController<List<int>>();
  114. controller.onCancel = (){
  115. stream.cancel();
  116. };
  117. Future<void> rcv()async{
  118. try{
  119. await for(final one in stream){
  120. controller.add(one.data);
  121. }
  122. }finally{
  123. controller.close();
  124. stream.cancel();
  125. }
  126. }
  127. rcv();
  128. stream.headers.then((value) => debug(value));
  129. final headers = await stream.headers;
  130. final lenStr = headers['all-length']!;
  131. final length = int.parse(lenStr);
  132. final nonce = headers['nonce']!;
  133. final ext = headers['ext']!;
  134. return BinReader(
  135. data: controller.stream,
  136. length: length,
  137. ext: ext,
  138. nonce: nonce
  139. );
  140. }
  141. }
  142. extension NetImageExt on pb.NetImage{
  143. GameMap toGameMap(){
  144. final md5Data = Uint8List.fromList(md5);
  145. return GameMap()
  146. ..url = url
  147. ..md5 = md5Data
  148. ..readerBuilder = ()=> ApiService.to.getBinReaderByMd5(md5Data);
  149. }
  150. }