exam_blood_sugar.dart 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. import 'package:flutter/material.dart';
  2. import 'package:get/get.dart';
  3. import 'package:vnote_device_plugin/devices/sugar.dart';
  4. import 'package:vnote_device_plugin/models/exams/sugar.dart';
  5. import 'package:vnoteapp/components/alert_dialog.dart';
  6. import 'package:vnoteapp/components/button.dart';
  7. import 'package:vnoteapp/managers/interfaces/permission.dart';
  8. import 'package:vnoteapp/pages/check/models/form.dart';
  9. import 'package:vnoteapp/pages/check/widgets/exam_configurable/exam_card.dart';
  10. class ExamBloodSugar extends StatefulWidget {
  11. const ExamBloodSugar({
  12. super.key,
  13. required this.currentFormObject,
  14. required this.currentInputValue,
  15. this.specialInput,
  16. });
  17. final FormObject currentFormObject;
  18. final String currentInputValue;
  19. final Function(String value)? specialInput;
  20. @override
  21. State<ExamBloodSugar> createState() => _ExamBloodSugarState();
  22. }
  23. class _ExamBloodSugarState extends State<ExamBloodSugar> {
  24. var permissionManager = Get.find<IPermissionManager>();
  25. @override
  26. void initState() {
  27. getPermission();
  28. super.initState();
  29. }
  30. Future<void> getPermission() async {
  31. await permissionManager.requestLocationPermission();
  32. await permissionManager.requestBluetoothConnectPermission();
  33. await permissionManager.requestBluetoothAdvertisePermission();
  34. await permissionManager.requestBluetoothScanPermission();
  35. }
  36. @override
  37. Widget build(BuildContext context) {
  38. return ExamCard(
  39. title: widget.currentFormObject.label ?? '',
  40. clickCard: () {
  41. _buildTempertureInput(widget.currentFormObject);
  42. },
  43. content: Container(
  44. alignment: Alignment.bottomRight,
  45. padding: const EdgeInsets.only(
  46. bottom: 20,
  47. right: 30,
  48. left: 40,
  49. ),
  50. constraints: const BoxConstraints(minHeight: 150),
  51. child: FittedBox(
  52. child: Row(
  53. mainAxisAlignment: MainAxisAlignment.end,
  54. crossAxisAlignment: CrossAxisAlignment.end,
  55. children: [
  56. RichText(
  57. text: TextSpan(
  58. text: widget.currentInputValue,
  59. style: const TextStyle(
  60. fontSize: 80,
  61. color: Colors.black,
  62. ),
  63. children: [
  64. TextSpan(
  65. text: widget.currentFormObject.append ?? '',
  66. style: const TextStyle(fontSize: 25),
  67. )
  68. ],
  69. ),
  70. ),
  71. ],
  72. ),
  73. ),
  74. ),
  75. );
  76. }
  77. Future<void> _buildTempertureInput(FormObject currentFormObject) async {
  78. // Future.delayed(const Duration(milliseconds: 3000), () {
  79. // specialInputController.text = generateRandomNumber().toString();
  80. // widget.specialInput?.call(specialInputController.text);
  81. // setState(() {});
  82. // });
  83. final result = await Get.dialog(
  84. BloodSugar(
  85. currentFormObject: widget.currentFormObject,
  86. bloodSugar: widget.currentInputValue,
  87. ),
  88. barrierDismissible: false,
  89. );
  90. widget.specialInput?.call(result);
  91. print(result);
  92. }
  93. }
  94. class BloodSugar extends StatefulWidget {
  95. const BloodSugar({
  96. super.key,
  97. required this.currentFormObject,
  98. this.bloodSugar,
  99. });
  100. final FormObject currentFormObject;
  101. final String? bloodSugar;
  102. @override
  103. State<BloodSugar> createState() => _BloodSugarState();
  104. }
  105. class _BloodSugarState extends State<BloodSugar> {
  106. late final SugarDeviceWorker worker = SugarDeviceWorker(
  107. mac: '60:98:66:C4:0E:51',
  108. model: 'i-sens630',
  109. );
  110. late TextEditingController specialInputController =
  111. TextEditingController(text: widget.bloodSugar ?? '00.0');
  112. bool connectFailState = false;
  113. bool connectSuccessState = false;
  114. bool isConnect = false;
  115. @override
  116. void initState() {
  117. connect();
  118. worker.successEvent.addListener(_onSuccess);
  119. worker.connectErrorEvent.addListener(_onConnectFail);
  120. worker.connectedEvent.addListener(_onConnectSuccess);
  121. super.initState();
  122. }
  123. Future<void> connect() async {
  124. connectFailState = false;
  125. isConnect = true;
  126. connectSuccessState = false;
  127. setState(() {});
  128. await worker.connect();
  129. }
  130. Future<void> disconnect() async {
  131. worker.connectErrorEvent.removeListener(_onConnectFail);
  132. worker.connectedEvent.removeListener(_onConnectSuccess);
  133. await worker.disconnect();
  134. }
  135. @override
  136. void dispose() {
  137. super.dispose();
  138. }
  139. void _onSuccess(_, SugarExamData e) {
  140. setState(() {
  141. specialInputController.text = e.sugar.toString();
  142. // connectFailState = false;
  143. // connectSuccessState = false;
  144. isConnect = false;
  145. // disconnect();
  146. });
  147. }
  148. void _onConnectFail(sender, e) {
  149. print('连接设备失败');
  150. connectFailState = true;
  151. connectSuccessState = false;
  152. isConnect = false;
  153. disconnect();
  154. setState(() {});
  155. }
  156. void _onConnectSuccess(sender, e) {
  157. connectSuccessState = true;
  158. connectFailState = false;
  159. isConnect = false;
  160. setState(() {});
  161. }
  162. @override
  163. Widget build(BuildContext context) {
  164. return VAlertDialog(
  165. title: widget.currentFormObject.label ?? '',
  166. width: 600,
  167. contentPadding: const EdgeInsets.symmetric(vertical: 12, horizontal: 24),
  168. content: buildMainWidget(),
  169. showCancel: true,
  170. onConfirm: () {
  171. disconnect();
  172. Get.back(result: specialInputController.text);
  173. },
  174. onCanceled: () {
  175. disconnect();
  176. },
  177. );
  178. }
  179. Widget buildInputField() {
  180. return Container(
  181. width: 350,
  182. padding: const EdgeInsets.only(left: 15),
  183. child: TextFormField(
  184. keyboardType: TextInputType.number,
  185. style: const TextStyle(
  186. fontSize: 100,
  187. ),
  188. showCursor: false,
  189. controller: specialInputController,
  190. decoration: const InputDecoration(
  191. labelStyle: TextStyle(
  192. fontSize: 100,
  193. ),
  194. ),
  195. ),
  196. );
  197. }
  198. Widget buildConnectFailText() {
  199. return const Text(
  200. '设备连接失败',
  201. style: TextStyle(
  202. color: Colors.red,
  203. fontSize: 25,
  204. ),
  205. textAlign: TextAlign.left,
  206. );
  207. }
  208. Widget buildConnectSuccessText() {
  209. return const Text(
  210. '设备连接成功',
  211. style: TextStyle(
  212. color: Colors.green,
  213. fontSize: 25,
  214. ),
  215. textAlign: TextAlign.left,
  216. );
  217. }
  218. Widget buildConnectingText() {
  219. return const Row(
  220. children: [
  221. Expanded(
  222. child: Text(
  223. '设备连接中',
  224. style: TextStyle(
  225. fontSize: 40,
  226. color: Colors.blue,
  227. ),
  228. ),
  229. ),
  230. CircularProgressIndicator(
  231. valueColor: AlwaysStoppedAnimation(
  232. Colors.blue,
  233. ),
  234. ),
  235. SizedBox(
  236. width: 20,
  237. ),
  238. ],
  239. );
  240. }
  241. Widget buildReconnectButton() {
  242. return Container(
  243. margin: const EdgeInsets.only(top: 4),
  244. width: 134,
  245. child: VButton(
  246. onTap: () async {
  247. /// TODO
  248. await connect();
  249. worker.connectErrorEvent.addListener(_onConnectFail);
  250. worker.connectedEvent.addListener(_onConnectSuccess);
  251. /// TODO 后面需要改,这边暂时演示用
  252. Future.delayed(const Duration(milliseconds: 8000), () {
  253. if (!connectSuccessState) {
  254. connectFailState = true;
  255. }
  256. });
  257. },
  258. child: const Row(
  259. mainAxisAlignment: MainAxisAlignment.center,
  260. children: [
  261. Icon(Icons.connected_tv_rounded, size: 24),
  262. SizedBox(
  263. width: 8,
  264. ),
  265. Text("重连", style: TextStyle(fontSize: 20)),
  266. ],
  267. ),
  268. ),
  269. );
  270. }
  271. Widget buildConnectStateWidgets() {
  272. return Column(
  273. children: [
  274. if (connectFailState) buildConnectFailText(),
  275. if (connectSuccessState) buildConnectSuccessText(),
  276. if (isConnect)
  277. buildConnectingText()
  278. else if (connectFailState)
  279. buildReconnectButton(),
  280. ],
  281. );
  282. }
  283. Widget buildMainWidget() {
  284. return SizedBox(
  285. height: 100,
  286. child: Row(
  287. children: [
  288. buildInputField(),
  289. Expanded(
  290. child: buildConnectStateWidgets(),
  291. ),
  292. ],
  293. ),
  294. );
  295. }
  296. }