import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vitalapp/managers/device_controller_manager.dart'; import 'package:vitalapp/pages/medical/widgets/device_status_position.dart'; import 'package:vnote_device_plugin/consts/types.dart'; import 'package:vnote_device_plugin/devices/weight_height.dart'; import 'package:vitalapp/managers/interfaces/models/device.dart'; import 'package:vitalapp/pages/medical/widgets/exam_card.dart'; import 'package:vitalapp/components/dialog_number.dart'; import 'package:vitalapp/pages/medical/controller.dart'; import 'package:vitalapp/pages/medical/models/worker.dart'; import 'package:vitalapp/pages/medical/widgets/device_status.dart'; import 'package:vitalapp/pages/medical/widgets/side_bar.dart'; import 'package:fis_common/logger/logger.dart'; import 'package:vnote_device_plugin/models/exams/weight_height.dart'; class BodyWeightHeight extends StatefulWidget { const BodyWeightHeight({ super.key, }); @override State createState() => _ExamBodyWeightState(); } class _ExamBodyWeightState extends State { var controller = Get.find(); DeviceControllerManager? bmi; WeightHeightDeviceWorker? worker; bool isConnectFail = false; int errorCount = 0; WorkerStatus _connectStatus = WorkerStatus.connecting; late String _weight = controller.diagnosisDataValue['BMI']?['Weight'] ?? ''; late String _height = controller.diagnosisDataValue['BMI']?['Height'] ?? ''; late String _bmi = controller.diagnosisDataValue['BMI']?['Bmi'] ?? ''; @override void initState() { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { initBmi(); }); super.initState(); } Future connect() async { await worker!.connect(); } /// 尝试重连 Future tryReconnect() async { if (worker != null) { await disconnect(); await connect(); } } Future disconnect() async { if (worker != null) { await worker!.disconnect(); } } void releaseListeners() { worker!.connectErrorEvent.removeListener(_onConnectFail); worker!.connectedEvent.removeListener(_onConnectSuccess); worker!.successEvent.removeListener(_onSuccess); worker!.disconnectedEvent.removeListener(_onDisconnected); } @override void dispose() { bmi?.dispose(); bmi = null; releaseListeners(); disconnect(); worker?.dispose(); super.dispose(); } void loadListeners() { worker!.successEvent.addListener(_onSuccess); worker!.connectErrorEvent.addListener(_onConnectFail); worker!.connectedEvent.addListener(_onConnectSuccess); worker!.disconnectedEvent.addListener(_onDisconnected); } Future currentDevice() async { DeviceModel? device = await controller.getDevice(DeviceTypes.WEIGHTHEIGHT); if (device == null) { _connectStatus = WorkerStatus.unboundDevice; worker = null; setState(() {}); return; } bmi = DeviceControllerManager( DeviceTypes.WEIGHTHEIGHT, device.model, device.mac); worker = bmi!.worker as WeightHeightDeviceWorker; _connectStatus = bmi!.connectStatus; loadListeners(); connect(); } Future initBmi() async { currentDevice(); await initData(); } Future initData() async { _weight = controller.diagnosisDataValue['BMI']?['Weight'] ?? ''; _height = controller.diagnosisDataValue['BMI']?['Height'] ?? ''; _bmi = controller.diagnosisDataValue['BMI']?['Bmi'] ?? ''; logger.i( '_ExamBodyWeightState initData _weight:$_weight _height:$_height _bmi:$_bmi'); setState(() {}); } void _onSuccess(_, WeightHeightExamData e) { _weight = double.parse(e.weight.toStringAsFixed(1)).toString(); _height = double.parse(e.height.toStringAsFixed(1)).toString(); if (_height.isNotEmpty && _weight.isNotEmpty) { getBmi(); controller.diagnosisDataValue['BMI'] = { 'Bmi': _bmi, 'Weight': _weight, 'Height': _height, }; } else { controller.diagnosisDataValue['BMI'] = { 'Weight': _weight, }; } controller.saveCachedRecord(); _connectStatus = WorkerStatus.connected; setState(() {}); } void _onConnectFail(sender, e) { print('连接设备失败'); logger.i("连接设备失败:${worker!.mac}"); if (errorCount < 3) { errorCount++; tryReconnect(); } else { isConnectFail = true; } _connectStatus = WorkerStatus.connectionFailed; setState(() {}); } void _onDisconnected(sender, e) { print('设备连接中断'); logger.i("设备连接中断:${worker!.mac}"); tryReconnect(); errorCount = 0; _connectStatus = WorkerStatus.disconnected; setState(() {}); } void _onConnectSuccess(sender, e) { logger.i("设备连接成功:${worker!.mac}"); isConnectFail = false; errorCount = 0; _connectStatus = WorkerStatus.connected; setState(() {}); } @override Widget build(BuildContext context) { return ExamCard( titleText: const SizedBox(), // clickCard: () {}, content: Stack( children: [ if (!isConnectFail) DeviceStatusPosition( deviceStatus: DeviceStatus(connectStatus: _connectStatus), ) else _buildErrorButton(), Column( mainAxisAlignment: MainAxisAlignment.start, children: [ SizedBox( height: 45, ), SideBar( title: '身高', value: _height.isEmpty ? '--' : _height, unit: 'cm', onTap: _inputHeight, ), const Divider(indent: 30), SideBar( title: '体重', value: _weight.isEmpty ? '--' : _weight, hasDevice: true, unit: 'kg', onTap: _inputWeight, ), const Divider(indent: 30), SideBar( title: 'BMI', value: _bmi.isEmpty ? '--' : _bmi, unit: 'kg/m²', ), ], ), ], )); } /// 需要封装一下 Widget _buildErrorButton() { return DeviceStatusPosition( deviceStatus: Row( children: [ const Text( '请确认设备是否启动', style: TextStyle(fontSize: 24, color: Colors.red), ), IconButton( onPressed: () { tryReconnect(); setState(() { _connectStatus = WorkerStatus.connecting; isConnectFail = false; }); }, icon: const Icon(Icons.refresh), iconSize: 32, ), ], ), ); } Future _inputWeight() async { String? result = await VDialogNumber( title: '体重', initialValue: _weight, ).show(); if (result?.isNotEmpty ?? false) { _weight = result ?? ''; if (_height.isNotEmpty) { getBmi(); } controller.diagnosisDataValue['BMI'] = { 'Height': _height, 'Bmi': _bmi, 'Weight': _weight, }; controller.saveCachedRecord(); } setState(() {}); } void getBmi() { if (_weight.isNotEmpty && _height.isNotEmpty) { final w = double.parse(_weight); final h = double.parse(_height) / 100.0; if (h == 0) { // 0不能被除 _bmi = "0"; } else { _bmi = (w / math.pow(h, 2)).toStringAsFixed(1); } controller.saveCachedRecord(); } } Future _inputHeight() async { String? result = await VDialogNumber( title: '身高', initialValue: _height, ).show(); if (result?.isNotEmpty ?? false) { _height = result ?? ''; if (_weight.isNotEmpty) { getBmi(); } controller.diagnosisDataValue['BMI'] = { 'Height': _height, 'Bmi': _bmi, 'Weight': _weight, }; controller.saveCachedRecord(); } setState(() {}); } }