blood_sugar.dart 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:vitalapp/managers/device_controller_manager.dart';
  4. import 'package:vitalapp/pages/medical/widgets/device_status_position.dart';
  5. import 'package:vnote_device_plugin/consts/types.dart';
  6. import 'package:vnote_device_plugin/devices/sugar.dart';
  7. import 'package:vnote_device_plugin/models/exams/error.dart';
  8. import 'package:vnote_device_plugin/models/exams/sugar.dart';
  9. import 'package:vitalapp/managers/interfaces/models/device.dart';
  10. import 'package:vitalapp/pages/medical/widgets/exam_card.dart';
  11. import 'package:vitalapp/components/dialog_number.dart';
  12. import 'package:vitalapp/pages/medical/controller.dart';
  13. import 'package:vitalapp/pages/medical/models/worker.dart';
  14. import 'package:vitalapp/pages/medical/widgets/device_status.dart';
  15. import 'package:fis_common/logger/logger.dart';
  16. // ignore: must_be_immutable
  17. class BloodSugar extends StatefulWidget {
  18. const BloodSugar({
  19. super.key,
  20. });
  21. @override
  22. State<BloodSugar> createState() => _ExamBloodSugarState();
  23. }
  24. class _ExamBloodSugarState extends State<BloodSugar> {
  25. var controller = Get.find<MedicalController>();
  26. DeviceControllerManager? sugar;
  27. SugarDeviceWorker? worker;
  28. bool isConnectFail = false;
  29. WorkerStatus _connectStatus = WorkerStatus.connecting;
  30. int errorCount = 0;
  31. String _bloodStatus = '';
  32. late String _value = controller.diagnosisDataValue['GLU']?['sugar'] ?? '';
  33. @override
  34. void initState() {
  35. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  36. initSugar();
  37. });
  38. super.initState();
  39. }
  40. void loadListeners() {
  41. worker!.successEvent.addListener(_onSuccess);
  42. worker!.connectErrorEvent.addListener(_onConnectFail);
  43. worker!.connectedEvent.addListener(_onConnectSuccess);
  44. worker!.disconnectedEvent.addListener(_onDisconnected);
  45. worker!.warnEvent.addListener(_onWarn);
  46. worker!.statusEvent.addListener(_onstatus);
  47. }
  48. Future<void> currentDevice() async {
  49. DeviceModel? device = await controller.getDevice(DeviceTypes.SUGAR);
  50. if (device == null) {
  51. _connectStatus = WorkerStatus.unboundDevice;
  52. worker = null;
  53. setState(() {});
  54. return;
  55. }
  56. sugar =
  57. DeviceControllerManager(DeviceTypes.SUGAR, device.model, device.mac);
  58. worker = sugar!.worker as SugarDeviceWorker?;
  59. _connectStatus = sugar!.connectStatus;
  60. loadListeners();
  61. connect();
  62. }
  63. /// 尝试重连
  64. Future<void> tryReconnect() async {
  65. if (worker != null) {
  66. await disconnect();
  67. await connect();
  68. }
  69. }
  70. Future<void> initSugar() async {
  71. currentDevice();
  72. await initData();
  73. }
  74. Future<void> initData() async {
  75. _value = controller.diagnosisDataValue['GLU']?['sugar'] ?? '';
  76. logger.i('_ExamBloodSugarState initData sugar:$_value');
  77. setState(() {});
  78. }
  79. Future<void> disconnect() async {
  80. if (worker != null) {
  81. await worker!.disconnect();
  82. }
  83. }
  84. Future<void> connect() async {
  85. if (worker != null) {
  86. await worker!.connect();
  87. }
  88. }
  89. void releaseListeners() {
  90. worker!.connectErrorEvent.removeListener(_onConnectFail);
  91. worker!.connectedEvent.removeListener(_onConnectSuccess);
  92. worker!.successEvent.removeListener(_onSuccess);
  93. worker!.disconnectedEvent.removeListener(_onDisconnected);
  94. worker!.warnEvent.removeListener(_onWarn);
  95. worker!.statusEvent.removeListener(_onstatus);
  96. }
  97. @override
  98. void dispose() {
  99. sugar?.dispose();
  100. sugar = null;
  101. releaseListeners();
  102. disconnect();
  103. worker?.dispose();
  104. super.dispose();
  105. }
  106. void _onWarn(_, ExamError e) {
  107. _bloodStatus = e.message ?? '';
  108. logger.i("BloodSugar - warn: $_bloodStatus.");
  109. setState(() {});
  110. }
  111. void _onstatus(_, ExamError e) {
  112. _bloodStatus = e.message ?? '';
  113. logger.i("BloodSugar - status: $_bloodStatus.");
  114. setState(() {});
  115. }
  116. void _onSuccess(_, SugarExamData e) {
  117. logger.i("BloodSugar - value callback: ${e.sugar}.");
  118. setState(() {
  119. _value = e.sugar.toString();
  120. controller.diagnosisDataValue['GLU'] = {'sugar': _value};
  121. controller.saveCachedRecord();
  122. _connectStatus = WorkerStatus.connected;
  123. });
  124. }
  125. void _onConnectFail(sender, e) {
  126. logger.i("BloodSugar - connect fail.");
  127. if (errorCount < 3) {
  128. errorCount++;
  129. tryReconnect();
  130. } else {
  131. isConnectFail = true;
  132. }
  133. _bloodStatus = '';
  134. _connectStatus = WorkerStatus.connectionFailed;
  135. setState(() {});
  136. }
  137. void _onConnectSuccess(sender, e) {
  138. logger.i("BloodSugar - connect success.");
  139. _connectStatus = WorkerStatus.connected;
  140. errorCount = 0;
  141. _bloodStatus = '';
  142. isConnectFail = false;
  143. setState(() {});
  144. }
  145. void _onDisconnected(sender, e) {
  146. logger.i("BloodSugar - disconnected.");
  147. errorCount = 0;
  148. tryReconnect();
  149. _bloodStatus = '';
  150. _connectStatus = WorkerStatus.disconnected;
  151. setState(() {});
  152. }
  153. @override
  154. Widget build(BuildContext context) {
  155. return Stack(
  156. children: [
  157. _buildSugar(),
  158. if (!isConnectFail)
  159. DeviceStatusPosition(
  160. deviceStatus: DeviceStatus(connectStatus: _connectStatus),
  161. )
  162. else
  163. _buildErrorButton(),
  164. Positioned(
  165. right: 10,
  166. top: 60,
  167. child: Text(
  168. _bloodStatus,
  169. style: const TextStyle(
  170. fontSize: 18,
  171. ),
  172. ),
  173. ),
  174. ],
  175. );
  176. }
  177. /// 需要封装一下
  178. Widget _buildErrorButton() {
  179. return DeviceStatusPosition(
  180. deviceStatus: Row(
  181. children: [
  182. const Text(
  183. '请确认设备是否启动',
  184. style: TextStyle(fontSize: 24, color: Colors.red),
  185. ),
  186. IconButton(
  187. onPressed: () {
  188. tryReconnect();
  189. setState(() {
  190. _connectStatus = WorkerStatus.connecting;
  191. isConnectFail = false;
  192. });
  193. },
  194. icon: const Icon(Icons.refresh),
  195. iconSize: 32,
  196. ),
  197. ],
  198. ),
  199. );
  200. }
  201. Widget _buildSugar() {
  202. return ExamCard(
  203. title: '',
  204. clickCard: () {
  205. _inputSugar();
  206. },
  207. content: Row(
  208. children: [
  209. const SizedBox(
  210. width: 25,
  211. ),
  212. const Text(
  213. '血糖',
  214. style: TextStyle(fontSize: 25),
  215. ),
  216. const Expanded(
  217. child: SizedBox(),
  218. ),
  219. SizedBox(
  220. height: 100,
  221. child: FittedBox(
  222. child: Row(
  223. mainAxisAlignment: MainAxisAlignment.end,
  224. crossAxisAlignment: CrossAxisAlignment.center,
  225. children: [
  226. Text(
  227. _value.isEmpty ? '--' : _value,
  228. style: const TextStyle(
  229. fontSize: 60,
  230. color: Colors.black,
  231. ),
  232. ),
  233. const Text(
  234. ' mmol/L',
  235. style: TextStyle(fontSize: 25),
  236. ),
  237. const SizedBox(
  238. width: 15,
  239. )
  240. ],
  241. ),
  242. ),
  243. ),
  244. ],
  245. ),
  246. );
  247. }
  248. Future<void> _inputSugar() async {
  249. String? result = await VDialogNumber(
  250. title: '血糖',
  251. initialValue: _value,
  252. ).show();
  253. if (result?.isNotEmpty ?? false) {
  254. _value = result ?? '';
  255. controller.diagnosisDataValue['GLU'] = {'sugar': _value};
  256. controller.saveCachedRecord();
  257. }
  258. setState(() {});
  259. }
  260. }