import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vnote_device_plugin/consts/types.dart'; import 'package:vnote_device_plugin/devices/sp_o2.dart'; import 'package:vnote_device_plugin/models/exams/sp_o2.dart'; import 'package:vitalapp/managers/interfaces/models/device.dart'; import 'package:vitalapp/managers/interfaces/permission.dart'; import 'package:vitalapp/pages/check/widgets/device_controller.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_card.dart'; import 'package:vitalapp/pages/medical/models/worker.dart'; import 'package:vitalapp/pages/medical/widgets/device_status.dart'; // ignore: must_be_immutable class ExamBloodOxygen extends StatefulWidget { ExamBloodOxygen({ super.key, required this.currentValue, required this.bloodOxygenInput, }); Map currentValue; Function(Map) bloodOxygenInput; @override State createState() => _ExamBloodOxygenState(); } class _ExamBloodOxygenState extends State { var permissionManager = Get.find(); final controller = Get.find(); late SpO2DeviceWorker worker; bool isAccessTypeAuth = false; late WorkerStatus connectStatus = WorkerStatus.connecting; late String pulse = widget.currentValue['Pulse_Frequency'] ?? '0'; late String spO2 = widget.currentValue['Spo2'] ?? '0'; @override void initState() { getPermission(); currentDevice(); super.initState(); } Future currentDevice() async { DeviceModel? device = await controller.getDevice(DeviceTypes.SPO2); isAccessTypeAuth = await controller.isAccessTypeAuth(DeviceTypes.SPO2); if (device == null) { connectStatus = WorkerStatus.unboundDevice; setState(() {}); return; } worker = SpO2DeviceWorker( mac: device.mac, model: device.model, ); loadListeners(); } Future connect() async { setState(() {}); await worker.connect(); } void loadListeners() { worker.valueUpdateEvent.addListener(_onSuccess); worker.connectErrorEvent.addListener(_onConnectFail); worker.connectedEvent.addListener(_onConnectSuccess); worker.connect(); } Future disconnect() async { worker.connectErrorEvent.removeListener(_onConnectFail); worker.connectedEvent.removeListener(_onConnectSuccess); worker.valueUpdateEvent.removeListener(_onSuccess); worker.disconnectedEvent.removeListener(_onDisconnected); await worker.disconnect(); } @override void dispose() { disconnect(); super.dispose(); } void _onSuccess(_, SpO2ExamValue e) { setState(() { pulse = e.pulse.toString(); spO2 = e.spO2.toString(); // connectFailState = false; // connectSuccessState = false; widget.bloodOxygenInput.call({ 'Spo2': spO2, 'Pulse_Frequency': pulse, }); widget.currentValue = { 'Spo2': spO2, 'Pulse_Frequency': pulse, }; connectStatus = WorkerStatus.connected; // disconnect(); }); } void _onConnectFail(sender, e) { print('连接设备失败'); connectStatus = WorkerStatus.connectionFailed; setState(() {}); } void _onConnectSuccess(sender, e) { connectStatus = WorkerStatus.connected; setState(() {}); } void _onDisconnected(sender, e) { print('设备连接中断'); connectStatus = WorkerStatus.disconnected; setState(() {}); } Future getPermission() async { await permissionManager.requestLocationPermission(); await permissionManager.requestBluetoothConnectPermission(); await permissionManager.requestBluetoothAdvertisePermission(); await permissionManager.requestBluetoothScanPermission(); } @override Widget build(BuildContext context) { return Stack( children: [ ExamCard( // clickCard: () {}, content: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ const SizedBox( height: 40, ), _SideBar( title: '血氧饱和度', value: spO2, unit: '%', ), const Divider(indent: 30), const SizedBox( height: 32, ), _SideBar( title: '脉率', value: pulse, unit: 'bpm', ), ], )), if (isAccessTypeAuth) DeviceStatus(connectStatus: connectStatus), ], ); } } class _SideBar extends StatelessWidget { final String title; final String value; final String unit; const _SideBar({ required this.title, required this.value, required this.unit, }); @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 30), child: Text( title, style: const TextStyle( fontSize: 25, ), ), ), Container( alignment: Alignment.bottomRight, padding: const EdgeInsets.only( bottom: 20, right: 30, left: 40, ), child: FittedBox( child: Row( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end, children: [ RichText( text: TextSpan( text: value, style: const TextStyle( fontSize: 80, color: Colors.black, ), children: [ TextSpan( text: unit, style: const TextStyle(fontSize: 25), ) ], ), ), ], ), ), ), ], ); } }