import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:vitalapp/managers/interfaces/models/device.dart'; import 'package:vitalapp/pages/medical/controllers/heart.dart'; import 'package:vitalapp/pages/medical/widgets/device_status.dart'; import 'package:vitalapp/pages/medical/widgets/ecg_view/index.dart'; import 'package:vnote_device_plugin/consts/types.dart'; import 'package:vnote_device_plugin/devices/heart.dart'; import 'package:vitalapp/pages/check/widgets/exam_configurable/exam_card.dart'; import 'package:vitalapp/pages/medical/controller.dart'; import 'package:vitalapp/pages/medical/models/worker.dart'; import 'package:vitalapp/pages/medical/widgets/side_bar.dart'; import 'dart:ui' as ui; import 'dart:typed_data'; import 'package:vnote_device_plugin/models/exams/heart.dart'; class HeartRate extends StatefulWidget { const HeartRate({ super.key, }); @override State createState() => _HeartRateState(); } class _HeartRateState extends State { var controller = Get.find(); late HeartDeviceController heart; late HeartDeviceWorker worker; WorkerStatus _connectStatus = WorkerStatus.connecting; List ecgPoint = []; late String _heart = controller.diagnosisDataValue['Heart']?['HEART'] ?? ''; late final String _assess = controller.diagnosisDataValue['Heart']?['ASSESS'] ?? ''; late final String _ecg = controller.diagnosisDataValue['Heart']?['ECG'] ?? ''; late final String _ecgPoint = controller.diagnosisDataValue['Heart']?['ECG_POINT'] ?? ''; @override void initState() { initHeart(); super.initState(); } Future connect() async { await worker.connect(); } Future disconnect() async { if (!worker.isNull) { await worker.disconnect(); releaseListeners(); } } void releaseListeners() { worker.connectErrorEvent.removeListener(_onConnectFail); worker.connectedEvent.removeListener(_onConnectSuccess); // worker.successEvent.removeListener(_onSuccess); worker.disconnectedEvent.removeListener(_onDisconnected); worker.hrValueUpdateEvent.removeListener(_onHrValueUpdate); worker.ecgValueUpdateEvent.removeListener(_onEcgValueUpdate); worker.resultReceivedEvent.removeListener(_onRCesultReceived); } @override void dispose() { disconnect(); super.dispose(); } void loadListeners() { // worker.successEvent.addListener(_onSuccess); worker.connectErrorEvent.addListener(_onConnectFail); worker.connectedEvent.addListener(_onConnectSuccess); worker.disconnectedEvent.addListener(_onDisconnected); worker.hrValueUpdateEvent.addListener(_onHrValueUpdate); worker.ecgValueUpdateEvent.addListener(_onEcgValueUpdate); worker.resultReceivedEvent.addListener(_onRCesultReceived); worker.connect(); } Future currentDevice() async { DeviceModel? device = await controller.getDevice(DeviceTypes.HEART); if (device.isNull) { _connectStatus = WorkerStatus.unboundDevice; setState(() {}); return; } heart = HeartDeviceController(device?.model ?? '', device?.mac ?? ''); worker = heart.worker; _connectStatus = heart.connectStatus; loadListeners(); } Future initHeart() async { currentDevice(); await initData(); } Future initData() async { await controller.readCachedRecord(); if (controller.diagnosisDataValue['Heart'] == null) { controller.diagnosisDataValue['Heart'] = {}; } setState(() {}); } void _onSuccess(_, double e) { setState(() { // _weight = e.toString(); _connectStatus = WorkerStatus.connected; }); } void _onHrValueUpdate(_, int e) { setState(() { _heart = e.toString(); }); } void _onRCesultReceived(_, HeartExamResult e) { setState(() async { print(ecgPoint.toString()); // _heart = e.toString(); controller.diagnosisDataValue['Heart']?['HEART'] = e.heartRate; controller.diagnosisDataValue['Heart']?['ASSESS'] = e.analysis.first; controller.diagnosisDataValue['Heart']?['ECG'] = await createEcgImageBase64(ecgPoint); controller.diagnosisDataValue['Heart']?['ECG_POINT'] = ecgPoint.toString(); print(controller.diagnosisDataValue); // late final String _assess = // controller.diagnosisDataValue['Heart']?['ASSESS'] ?? ''; // late final String _ecg = // controller.diagnosisDataValue['Heart']?['ECG'] ?? ''; // late final String _ecgPoint = // controller.diagnosisDataValue['Heart']?['ECG_POINT'] ?? ''; }); } void _onEcgValueUpdate(_, List e) { try { EcgViewController ecgViewController = Get.find(); ecgPoint.addAll(e); if (ecgPoint.length > 125 * 3) { ecgViewController.addData(e); } } catch (e) { print(e); } } void _onDeviceCloseSuccess(sender, e) { if (e) { connect(); } } 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 createEcgImageBase64(List points) async { final int width = points.length ~/ 2; const int height = 240; final ui.PictureRecorder recorder = ui.PictureRecorder(); final Canvas canvas = Canvas(recorder); final Path path = Path(); final Paint paint = Paint(); const double strokeWidth = 1.5; paint.color = Colors.green; paint.style = PaintingStyle.stroke; paint.isAntiAlias = true; paint.strokeWidth = strokeWidth; path.reset(); int pointCount = points.length; if (pointCount > 0) { path.moveTo(0, points[0].toDouble()); int i = 0; int j = pointCount ~/ 2; while (i < j) { path.lineTo(i.toDouble(), points[i].toDouble()); path.lineTo((i + 1).toDouble(), points[i + 1].toDouble()); i += 2; } canvas.drawPath(path, paint); } final ui.Picture picture = recorder.endRecording(); final ui.Image image = await picture.toImage(width, height); final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png); final Uint8List pngBytes = byteData!.buffer.asUint8List(); final String base64Image = base64Encode(pngBytes); return base64Image; } @override Widget build(BuildContext context) { return ExamCard( titleText: const SizedBox(), // clickCard: () {}, content: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(10), child: DeviceStatus(connectStatus: _connectStatus)), SideBar( title: '心率', value: _heart.isEmpty ? '--' : _heart, unit: '', ), SizedBox( height: 240, child: LayoutBuilder(builder: (context, constraints) { print(constraints.maxWidth); print(constraints.maxHeight); return EcgView( width: constraints.maxWidth, height: constraints.maxHeight, ); }), ) // CustomPaint( // painter: GridCanvasPainter(), // child: EcgPage( // points: ecgPoint, // ), // ), // const Divider(indent: 30), // Stack( // children: [ // SideBar( // title: '心率评估', // value: _assess.isEmpty ? '--' : _assess, // hasDevice: true, // unit: '', // ), // // DeviceStatus(connectStatus: _connectStatus), // ], // ), // const Divider(indent: 30), // MyWidget() // const EcgPage(), // SideBar( // title: '心电图', // value: _assess.isEmpty ? '--' : _assess, // unit: '', // ), ], )); } }