healthrian_uart_support 1.0.19 copy "healthrian_uart_support: ^1.0.19" to clipboard
healthrian_uart_support: ^1.0.19 copied to clipboard

Healthrian library for supporting UART connector manager

example/lib/main.dart

import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:file_picker/file_picker.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:healthrian_common_support/healthrian_common_support.dart';
import 'package:healthrian_uart_support/healthrian_uart_support.dart';
import 'package:intl/intl.dart';
import 'package:screenshot/screenshot.dart';

final uart = UartConnectorManager();

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await filter.waitForCompletion();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  StreamSubscription? _listener;
  DateTime? _recordedTime;
  String? _selectedDirectory;

  DataFilter _dataFilter = DataFilter(2)
    ..samplingRate = SamplingRate.freq500hz
    ..impulseType = ImpulseType.fir
    ..highPass = HighPass.hpf05
    ..lowPass = LowPass.lpf40;

  final _l1Raw = <double>[];
  final _l1 = <double>[];
  final _l2 = <double>[];
  final _l3 = <double>[];
  final _aVR = <double>[];
  final _aVL = <double>[];
  final _aVF = <double>[];

  void _clear() {
    _l1Raw.clear();
    _l1.clear();
    _l2.clear();
    _l3.clear();
    _aVR.clear();
    _aVL.clear();
    _aVF.clear();
  }

  void _add(double l1, double l2) {
    _l1Raw.add(l1);
    l1 = _dataFilter.applyFilter(0, l1);
    l2 = _dataFilter.applyFilter(1, l2);
    _l1.add(l1);
    _l2.add(l2);
    _l3.add(l2 - l1);
    _aVR.add(-l2 / 2 - l1 / 2);
    _aVL.add(l1 - l2 / 2);
    _aVF.add(l2 - l1 / 2);
  }

  @override
  void dispose() {
    super.dispose();
    _listener?.cancel();
    _clear();

    uart.closePort();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Column(
          children: <Widget>[
            const Text('PACKET'),
            StreamBuilder(
              stream: uart.outStream,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            const Divider(),
            const Text('LA, RA, LL, CABLE'),
            StreamBuilder(
              stream: uart.la,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.ra,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.ll,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.cable,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            const Divider(),
            const Text('ADC'),
            StreamBuilder(
              stream: uart.adc,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            const Divider(),
            const Text('L1, L2, L3, AVR, AVL, AVF'),
            StreamBuilder(
              stream: uart.l1,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.l2,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.l3,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.aVR,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.aVL,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            StreamBuilder(
              stream: uart.aVF,
              builder: (context, snapshot) => Text(snapshot.data.toString()),
            ),
            const Divider(),
          ],
        ),
        floatingActionButton: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            FloatingActionButton(
              onPressed: uart.turnOn,
              child: const Icon(Icons.power),
            ),
            FloatingActionButton(
              onPressed: uart.closePort,
              child: const Icon(Icons.power_off),
            ),
            FloatingActionButton(
              onPressed: uart.start,
              child: const Icon(Icons.play_arrow),
            ),
            FloatingActionButton(
              onPressed: uart.stop,
              child: const Icon(Icons.stop),
            ),
            if (_listener == null)
              FloatingActionButton(
                onPressed: () async {
                  if (_selectedDirectory == null) {
                    await FilePicker.platform.getDirectoryPath().then((path) => _selectedDirectory = path);
                  }
                  if (_selectedDirectory == null) return;

                  _listener?.cancel();
                  _clear();

                  _dataFilter = DataFilter(2)
                    ..samplingRate = SamplingRate.freq500hz
                    ..impulseType = ImpulseType.fir
                    ..highPass = HighPass.hpf05
                    ..lowPass = LowPass.lpf40;

                  _recordedTime = DateTime.now();
                  _listener = uart.all.listen((x) => _add(x.$1, x.$2));
                  setState(() {});
                },
                tooltip: 'start record',
                child: const Icon(Icons.emergency_recording),
              ),
            if (_listener != null)
              FloatingActionButton(
                onPressed: () {
                  _listener?.cancel();
                  _listener = null;
                  setState(() {});

                  if (_selectedDirectory == null) return;
                  if (_recordedTime == null) return;

                  final recordedTimeText = DateFormat('yyyy-MM-dd_hh-mm-ss').format(_recordedTime!);
                  final totalStep = (_l1.length / 5000).ceil();

                  final rawFile = File('$_selectedDirectory/$recordedTimeText.txt');
                  rawFile.writeAsStringSync(_l1Raw.toString());

                  for (var step = 0; step < totalStep; step++) {
                    final file = File('$_selectedDirectory/${recordedTimeText}_$step.png');
                    ScreenshotController()
                        .captureFromWidget(
                          CapturedScreen(
                            size: Size(1000, 720),
                            l1: _l1,
                            l2: _l2,
                            l3: _l3,
                            aVR: _aVR,
                            aVL: _aVL,
                            aVF: _aVF,
                            samplingRate: 500,
                            gridColor: Colors.red,
                            strokeWidth: 1.5,
                            step: step,
                          ),
                          context: context,
                          targetSize: Size(1000, 720),
                        )
                        .then((bytes) async => await file.writeAsBytes(bytes));
                  }
                },
                tooltip: 'stop record',
                child: const Icon(Icons.emergency_recording, color: Colors.red),
              ),
            FloatingActionButton(
              onPressed: () => uart.updateLatestWithPassword(String.fromEnvironment('PASSWORD')),
              child: const Text('FW\nUpdate', style: TextStyle(color: Colors.red)),
            ),
            FloatingActionButton(
              onPressed: () async {
                final fwVersion = await uart.getFirmwareVersion();
                if (!context.mounted) return;
                showDialog(
                  context: context,
                  builder: (context) => Dialog(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(fwVersion),
                    ),
                  ),
                );
              },
              child: const Text('FW\nVersion', style: TextStyle(color: Colors.green)),
            ),
            FloatingActionButton(
              onPressed: () async {
                final serialNumber = await uart.getSerialNumber();
                if (!context.mounted) return;
                showDialog(
                  context: context,
                  builder: (context) => Dialog(
                    child: Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Text(serialNumber),
                    ),
                  ),
                );
              },
              child: const Text('Serial\nNo.', style: TextStyle(color: Colors.green)),
            ),
            FloatingActionButton(
              onPressed: () => uart.enableReadLogger = !uart.enableReadLogger,
              child: const Text('Read\nLogger'),
            ),
          ],
        ),
      ),
    );
  }
}

class CapturedScreen extends StatelessWidget {
  const CapturedScreen({
    super.key,
    required this.size,
    required this.l1,
    required this.l2,
    required this.l3,
    required this.aVR,
    required this.aVL,
    required this.aVF,
    required this.samplingRate,
    required this.gridColor,
    required this.strokeWidth,
    required this.step,
  });

  final Size size;
  final List<double> l1;
  final List<double> l2;
  final List<double> l3;
  final List<double> aVR;
  final List<double> aVL;
  final List<double> aVF;
  final int samplingRate;
  final Color gridColor;
  final double strokeWidth;
  final int step;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: size.width,
      height: size.height,
      color: Colors.white,
      child: Column(
        children: [
          for (final list in [l1, l2, l3, aVR, aVL, aVF])
            Expanded(
              child: LineChart(
                LineChartData(
                  minX: 0,
                  maxX: 5000,
                  minY: -1.5,
                  maxY: 1.5,
                  lineTouchData: const LineTouchData(enabled: false),
                  titlesData: const FlTitlesData(show: false),
                  borderData: FlBorderData(show: false),
                  gridData: FlGridData(
                    show: true,
                    checkToShowVerticalLine: (x) => x % (samplingRate / 25) == 0,
                    verticalInterval: 10,
                    getDrawingVerticalLine: (x) {
                      if (x % (samplingRate / 5) == 0) {
                        return FlLine(color: gridColor, strokeWidth: strokeWidth / 2);
                      }
                      return FlLine(color: gridColor, strokeWidth: strokeWidth / 4);
                    },
                    horizontalInterval: 0.1,
                    getDrawingHorizontalLine: (y) {
                      if ((y * 10).round() % 5 == 0) {
                        return FlLine(color: gridColor, strokeWidth: strokeWidth / 2);
                      }
                      return FlLine(color: gridColor, strokeWidth: strokeWidth / 4);
                    },
                  ),
                  lineBarsData: [
                    LineChartBarData(
                      spots: [
                        ...list
                            .getRange(
                              step * 5000,
                              min(list.length, step * 5000 + 5000),
                            )
                            .indexed
                            .map((x) => FlSpot(x.$1.toDouble(), x.$2))
                      ],
                      color: Colors.black,
                      dotData: const FlDotData(show: false),
                    )
                  ],
                ),
              ),
            ),
        ],
      ),
    );
  }
}
1
likes
0
points
153
downloads

Publisher

unverified uploader

Weekly Downloads

Healthrian library for supporting UART connector manager

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

device_info_plus, encrypt, flutter, flutter_libserialport, healthrian_common_support, mobx

More

Packages that depend on healthrian_uart_support