123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- import 'dart:async';
- import 'dart:convert';
- import 'dart:math';
- 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<HeartRate> createState() => _HeartRateState();
- }
- class _HeartRateState extends State<HeartRate> {
- var controller = Get.find<MedicalController>();
- late HeartDeviceController heart;
- late HeartDeviceWorker worker;
- WorkerStatus _connectStatus = WorkerStatus.connecting;
- List<int> 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();
- // mockECG();
- super.initState();
- }
- void mockECG() {
- Random random = Random();
- int min = -125;
- int max = 125;
- int time = 1;
- int duration = 500 + random.nextInt(501); // 生成500到1000之间的随机持续时间
- Timer.periodic(Duration(milliseconds: duration), (timer) {
- if (time > 1) {
- timer.cancel(); // 取消定时器
- } else {
- time++;
- List<int> data = [];
- for (int i = 0; i < 160; i++) {
- int value = min + random.nextInt(max - min + 1); // 生成125到200之间的随机整数
- data.add(value);
- }
- try {
- EcgViewController ecgViewController = Get.find<EcgViewController>();
- ecgViewController.addData(data);
- } catch (e) {
- print(e);
- }
- }
- });
- }
- Future<void> connect() async {
- await worker.connect();
- }
- Future<void> 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<void> 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<void> initHeart() async {
- currentDevice();
- await initData();
- }
- Future<void> 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<int> e) {
- try {
- EcgViewController ecgViewController = Get.find<EcgViewController>();
- 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<String> createEcgImageBase64(List<int> 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: '',
- // ),
- ],
- ));
- }
- }
|