body_temperature.dart 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:vitalapp/architecture/app_parameters.dart';
  4. import 'package:vitalapp/managers/device_controller_manager.dart';
  5. import 'package:vitalapp/pages/medical/widgets/device_status_position.dart';
  6. import 'package:vnote_device_plugin/consts/types.dart';
  7. import 'package:vnote_device_plugin/devices/temp.dart';
  8. import 'package:vitalapp/components/dialog_number.dart';
  9. import 'package:vitalapp/managers/interfaces/models/device.dart';
  10. import 'package:vitalapp/pages/medical/widgets/exam_card.dart';
  11. import 'package:vitalapp/pages/medical/controller.dart';
  12. import 'package:vitalapp/pages/medical/models/worker.dart';
  13. import 'package:vitalapp/pages/medical/widgets/device_status.dart';
  14. import 'package:fis_common/logger/logger.dart';
  15. class BodyTemperature extends StatefulWidget {
  16. const BodyTemperature({
  17. super.key,
  18. });
  19. @override
  20. State<BodyTemperature> createState() => _ExamBodyTemperatureState();
  21. }
  22. class _ExamBodyTemperatureState extends State<BodyTemperature> {
  23. bool get isPureSoftwareMode => AppParameters.data.isPureSoftwareMode;
  24. var controller = Get.find<MedicalController>();
  25. DeviceControllerManager? temp;
  26. TempDeviceWorker? worker;
  27. WorkerStatus connectStatus = WorkerStatus.connecting;
  28. bool isConnectFail = false;
  29. int errorCount = 0;
  30. ///重试机制
  31. late String _value =
  32. controller.diagnosisDataValue['Temp']?['Temperature'] ?? '';
  33. @override
  34. void initState() {
  35. WidgetsBinding.instance.addPostFrameCallback(
  36. (timeStamp) {
  37. initTemperature();
  38. currentDevice();
  39. },
  40. );
  41. super.initState();
  42. }
  43. @override
  44. void didUpdateWidget(BodyTemperature oldWidget) {
  45. setState(() {});
  46. super.didUpdateWidget(oldWidget);
  47. }
  48. Future<void> currentDevice() async {
  49. DeviceModel? device = await controller.getDevice(DeviceTypes.TEMP);
  50. if (device == null) {
  51. connectStatus = WorkerStatus.unboundDevice;
  52. worker = null;
  53. return;
  54. }
  55. temp = DeviceControllerManager(DeviceTypes.TEMP, device.model, device.mac);
  56. worker = temp!.worker as TempDeviceWorker;
  57. connectStatus = temp!.connectStatus;
  58. loadListeners();
  59. connect();
  60. }
  61. Future<void> initTemperature() async {
  62. _value = controller.diagnosisDataValue['Temp']?['Temperature'] ?? '';
  63. /// 体检系统 基础检查的特殊处理
  64. if (controller.diagnosisDataValue['Temperature'] != null) {
  65. _value = controller.diagnosisDataValue['Temperature'] ?? '';
  66. logger.i('_ExamBloodSugarState initData Temperature:$_value');
  67. setState(() {});
  68. return;
  69. }
  70. logger.i('_ExamBloodSugarState initData Temperature:$_value');
  71. setState(() {});
  72. }
  73. void loadListeners() {
  74. worker!.successEvent.addListener(_onSuccess);
  75. worker!.connectErrorEvent.addListener(_onConnectFail);
  76. worker!.connectedEvent.addListener(_onConnectSuccess);
  77. worker!.disconnectedEvent.addListener(_onDisconnected);
  78. worker!.tempTooLowEvent.addListener(_onTempTooLowOrTooHeigh);
  79. worker!.tempTooHighEvent.addListener(_onTempTooLowOrTooHeigh);
  80. }
  81. Future<void> disconnect() async {
  82. if (worker != null) {
  83. await worker!.disconnect();
  84. }
  85. }
  86. Future<void> connect() async {
  87. if (worker != null) {
  88. await worker!.connect();
  89. }
  90. }
  91. void releaseListeners() {
  92. if (worker != null) {
  93. worker!.connectErrorEvent.removeListener(_onConnectFail);
  94. worker!.connectedEvent.removeListener(_onConnectSuccess);
  95. worker!.successEvent.removeListener(_onSuccess);
  96. worker!.disconnectedEvent.removeListener(_onDisconnected);
  97. worker!.tempTooLowEvent.removeListener(_onTempTooLowOrTooHeigh);
  98. worker!.tempTooHighEvent.removeListener(_onTempTooLowOrTooHeigh);
  99. }
  100. // controller.deviceCloseSuccessEvent.removeListener(_onDeviceCloseSuccess);
  101. }
  102. /// 尝试重连
  103. Future<void> tryReconnect() async {
  104. if (worker != null) {
  105. await disconnect();
  106. await connect();
  107. }
  108. }
  109. @override
  110. void dispose() {
  111. if (worker != null) {
  112. temp?.dispose();
  113. temp = null;
  114. }
  115. releaseListeners();
  116. disconnect();
  117. worker?.dispose();
  118. super.dispose();
  119. }
  120. void _onSuccess(_, double e) {
  121. setState(() {
  122. _value = e.toString();
  123. controller.diagnosisDataValue['Temp'] = {'Temperature': _value};
  124. controller.saveCachedRecord();
  125. connectStatus = WorkerStatus.connected;
  126. });
  127. }
  128. void _onTempTooLowOrTooHeigh(sender, e) {
  129. _value = e.toString();
  130. controller.diagnosisDataValue['Temp'] = {'Temperature': _value};
  131. controller.saveCachedRecord();
  132. connectStatus = WorkerStatus.connected;
  133. setState(() {});
  134. }
  135. void _onConnectFail(sender, e) {
  136. print('连接设备失败');
  137. logger.i("连接设备失败:${worker!.mac}");
  138. if (errorCount < 3) {
  139. errorCount++;
  140. tryReconnect();
  141. } else {
  142. isConnectFail = true;
  143. }
  144. connectStatus = WorkerStatus.connectionFailed;
  145. setState(() {});
  146. }
  147. void _onConnectSuccess(sender, e) {
  148. logger.i("设备连接成功:${worker!.mac}");
  149. connectStatus = WorkerStatus.connected;
  150. errorCount = 0;
  151. isConnectFail = false;
  152. setState(() {});
  153. }
  154. void _onDisconnected(sender, e) {
  155. print('设备连接中断');
  156. logger.i("设备连接中断:${worker!.mac}");
  157. errorCount = 0;
  158. tryReconnect();
  159. connectStatus = WorkerStatus.disconnected;
  160. setState(() {});
  161. }
  162. @override
  163. Widget build(BuildContext context) {
  164. return Stack(
  165. children: [
  166. _buildTemperature(),
  167. if (!isPureSoftwareMode) ...[
  168. if (!isConnectFail)
  169. DeviceStatusPosition(
  170. deviceStatus: DeviceStatus(connectStatus: connectStatus),
  171. )
  172. else
  173. _buildErrorButton(),
  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 _buildTemperature() {
  202. return ExamCard(
  203. title: '',
  204. clickCard: () {
  205. _inputTemperature();
  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(child: SizedBox()),
  217. Container(
  218. alignment: Alignment.bottomRight,
  219. height: 100,
  220. child: FittedBox(
  221. child: Row(
  222. mainAxisAlignment: MainAxisAlignment.end,
  223. crossAxisAlignment: CrossAxisAlignment.center,
  224. children: [
  225. Text(
  226. _value.isEmpty ? '--' : _value,
  227. style: const TextStyle(
  228. fontSize: 60,
  229. color: Colors.black,
  230. ),
  231. ),
  232. const Text(
  233. ' °C',
  234. style: TextStyle(fontSize: 25),
  235. ),
  236. const SizedBox(
  237. width: 30,
  238. )
  239. ],
  240. ),
  241. ),
  242. ),
  243. ],
  244. ),
  245. );
  246. }
  247. Future<void> _inputTemperature() async {
  248. String? result = await VDialogNumber(
  249. title: '体温',
  250. initialValue: _value,
  251. ).show();
  252. if (result?.isNotEmpty ?? false) {
  253. _value = result ?? '';
  254. controller.diagnosisDataValue['Temp'] = {'Temperature': _value};
  255. controller.saveCachedRecord();
  256. }
  257. setState(() {});
  258. }
  259. }