LiveData retrieved from native layer

dev_3.3_BLE
haroon amjad 2 years ago
parent b137f4b09a
commit 68b83e5f98

@ -32,6 +32,7 @@ import com.lepu.blepro.ext.BleServiceHelper
import com.lepu.blepro.ext.er2.DeviceInfo
import com.lepu.blepro.ext.er2.Er2EcgFile
import com.lepu.blepro.ext.er2.Er2File
import com.lepu.blepro.ext.er2.RtData
import com.lepu.blepro.ext.pc60fw.RtParam
import com.lepu.blepro.objs.Bluetooth
import com.lepu.blepro.objs.BluetoothController
@ -130,6 +131,9 @@ class BleBridge(
private var rtHandler = Handler()
private var rtTask = RtTask()
private var ecgRTHandler = Handler()
private var ecgRTTask = ECGRtTask()
inner class RtTask : Runnable {
override fun run() {
rtHandler.postDelayed(rtTask, 1000)
@ -137,6 +141,13 @@ class BleBridge(
}
}
inner class ECGRtTask : Runnable {
override fun run() {
ecgRTHandler.postDelayed(rtTask, 1000)
BleServiceHelper.BleServiceHelper.startRtTask(model)
}
}
@SuppressLint("NewApi")
fun create() {
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
@ -244,6 +255,7 @@ class BleBridge(
println("EventEr2SetTime")
// Get Device Info
BleServiceHelper.BleServiceHelper.er2GetInfo(model)
ecgRTTask.run()
}
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.ER2.EventEr2ReadFileComplete)
.observe(this.mainActivity) {
@ -259,9 +271,30 @@ class BleBridge(
ecgData.startTime = startTime
val returnData =
mapOf("type" to "fileDetail", "data" to gson.toJson(ecgData))
// val output = gson.toJson(returnData)
eventSink?.success(returnData)
}
LiveEventBus.get<InterfaceEvent>(InterfaceEvent.ER2.EventEr2RtData)
.observe(this.mainActivity) {
val data = it.data as RtData
println("EventEr2RtData")
val returnData =
mapOf("type" to "realtimeDataECG", "data" to gson.toJson(data))
println(returnData)
eventSink?.success(returnData)
// DataController.receive(data.wave.ecgFloats)
// hr.text = "${data.param.hr}"
// data_log.text = "${data.param}"
// sampling rate125HZ
// mV = n * 0.002467data.wave.ecgFloats = data.wave.ecgShorts * 0.002467
// data.param.batteryState0no charge1charging2charging complete3low battery
// data.param.battery0-100
// data.param.recordTimeunits
// data.param.curStatus0idle1preparing2measuring3saving file4saving succeed
// 5less than 30s, file not saved66 retests7lead off
}
}
if (deviceName == "O2M 1670") {

@ -0,0 +1,78 @@
class EKGRealTimeDataResponseModel {
Param param;
Wave wave;
EKGRealTimeDataResponseModel({this.param, this.wave});
EKGRealTimeDataResponseModel.fromJson(Map<String, dynamic> json) {
param = json['param'] != null ? new Param.fromJson(json['param']) : null;
wave = json['wave'] != null ? new Wave.fromJson(json['wave']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.param != null) {
data['param'] = this.param.toJson();
}
if (this.wave != null) {
data['wave'] = this.wave.toJson();
}
return data;
}
}
class Param {
num battery;
num batteryState;
num curStatus;
num hr;
bool poorSignal;
bool rSignal;
num recordTime;
Param({this.battery, this.batteryState, this.curStatus, this.hr, this.poorSignal, this.rSignal, this.recordTime});
Param.fromJson(Map<String, dynamic> json) {
battery = json['battery'];
batteryState = json['batteryState'];
curStatus = json['curStatus'];
hr = json['hr'];
poorSignal = json['poorSignal'];
rSignal = json['rSignal'];
recordTime = json['recordTime'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['battery'] = this.battery;
data['batteryState'] = this.batteryState;
data['curStatus'] = this.curStatus;
data['hr'] = this.hr;
data['poorSignal'] = this.poorSignal;
data['rSignal'] = this.rSignal;
data['recordTime'] = this.recordTime;
return data;
}
}
class Wave {
List<int> ecgBytes;
List<num> ecgFloats;
List<num> ecgShorts;
Wave({this.ecgBytes, this.ecgFloats, this.ecgShorts});
Wave.fromJson(Map<String, dynamic> json) {
ecgBytes = json['ecgBytes'].cast<int>();
ecgFloats = json['ecgFloats'].cast<double>();
ecgShorts = json['ecgShorts'].cast<int>();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ecgBytes'] = this.ecgBytes;
data['ecgFloats'] = this.ecgFloats;
data['ecgShorts'] = this.ecgShorts;
return data;
}
}

@ -2,15 +2,20 @@ import 'dart:async';
import 'dart:convert';
import 'package:diplomaticquarterapp/models/ble_devices/viatom_devices/ekg_file_detail_response_model.dart';
import 'package:diplomaticquarterapp/models/ble_devices/viatom_devices/ekg_realtime_data_response.dart';
import 'package:diplomaticquarterapp/pages/medical/my_trackers/viatom_devices/ekg_chart_view.dart';
import 'package:diplomaticquarterapp/uitl/utils_new.dart';
import 'package:diplomaticquarterapp/viatom_ble/ble_connect.dart';
import 'package:diplomaticquarterapp/widgets/buttons/defaultButton.dart';
import 'package:diplomaticquarterapp/widgets/others/app_scaffold_widget.dart';
import 'package:diplomaticquarterapp/widgets/transitions/fade_page.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'dart:math' as math;
class EKG_BLE extends StatefulWidget {
const EKG_BLE();
@ -22,36 +27,101 @@ class _EKG_BLEState extends State<EKG_BLE> {
EventChannel eventChannel = EventChannel('BLE-Platform-Bridge-Event');
String receivedData = '';
// final ekgValueNotifier = ValueNotifier<Map<String, dynamic>>;
final ekgValueNotifier = ValueNotifier<String>("start");
List<String> ekgFilesList = [];
List<double> ecgData = [];
EKGFileDetailResponseModel ekgFileDetailResponseModel;
EKGRealTimeDataResponseModel ekgRealTimeDataResponseModel;
List<int> ecgBytesAllDataList = [];
Timer timer;
List<_ChartData> chartData;
int count;
ChartSeriesController _chartSeriesController;
@override
void dispose() {
// ekgValueNotifier.dispose();
ekgValueNotifier.dispose();
super.dispose();
BleChannel.disconnect();
timer?.cancel();
chartData.clear();
_chartSeriesController = null;
}
@override
void initState() {
// TODO: implement initState
count = 19;
chartData = <_ChartData>[
_ChartData(0, 42),
_ChartData(1, 47),
_ChartData(2, 33),
_ChartData(3, 49),
_ChartData(4, 54),
_ChartData(5, 41),
_ChartData(6, 58),
_ChartData(7, 51),
_ChartData(8, 98),
_ChartData(9, 41),
_ChartData(10, 53),
_ChartData(11, 72),
_ChartData(12, 86),
_ChartData(13, 52),
_ChartData(14, 94),
_ChartData(15, 92),
_ChartData(16, 86),
_ChartData(17, 72),
_ChartData(18, 94),
];
timer = Timer.periodic(const Duration(milliseconds: 1000), _updateDataSource);
super.initState();
}
SfCartesianChart _buildLiveLineChart() {
return SfCartesianChart(
plotAreaBorderWidth: 0,
primaryXAxis: NumericAxis(majorGridLines: const MajorGridLines(width: 0)),
primaryYAxis: NumericAxis(axisLine: const AxisLine(width: 0), majorTickLines: const MajorTickLines(size: 0)),
// Simulate live ECG data (replace this with your actual data source)
timer = Timer.periodic(Duration(milliseconds: 500), (Timer t) {
setState(() {
ecgData.add((10.0 * (1 - 2 * (ecgData.length % 2).toDouble())).toDouble());
if (ecgData.length > 10) {
ecgData.removeAt(0);
}
});
});
series: <LineSeries<_ChartData, int>>[
LineSeries<_ChartData, int>(
onRendererCreated: (ChartSeriesController controller) {
_chartSeriesController = controller;
},
dataSource: chartData,
color: const Color.fromRGBO(192, 108, 132, 1),
xValueMapper: (_ChartData sales, _) => sales.country,
yValueMapper: (_ChartData sales, _) => sales.sales,
animationDuration: 2000.0)
]);
}
void _updateDataSource(Timer timer) {
// if (isCardView != null) {
chartData.add(_ChartData(count, _getRandomInt(10, 100)));
if (chartData.length == 20) {
chartData.removeAt(0);
_chartSeriesController?.updateDataSource(
addedDataIndexes: <int>[chartData.length - 1],
removedDataIndexes: <int>[0],
);
} else {
_chartSeriesController?.updateDataSource(
addedDataIndexes: <int>[chartData.length - 1],
);
}
count = count + 1;
// }
}
///Get the random data
int _getRandomInt(int min, int max) {
final math.Random random = math.Random();
return min + random.nextInt(max - min);
}
@override
@ -88,6 +158,10 @@ class _EKG_BLEState extends State<EKG_BLE> {
print(event['data']);
parseEKGFileDetailObject(event['data']);
}
if (event['type'] == "realtimeDataECG") {
ekgValueNotifier.value = event['data'];
parseEKGRealTimeDataObject(event['data']);
}
});
await BleChannel.getScanningResult(["oximeter", "ekg"]);
},
@ -106,16 +180,76 @@ class _EKG_BLEState extends State<EKG_BLE> {
),
],
),
mHeight(50.0),
ValueListenableBuilder(
valueListenable: ekgValueNotifier,
builder: (context, value, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text(value), mHeight(24.0), getFilesListWidget()],
);
},
),
mHeight(20.0),
_buildLiveLineChart()
// ValueListenableBuilder(
// valueListenable: ekgValueNotifier,
// builder: (context, value, _) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// value,
// style: TextStyle(fontSize: 9.0),
// ),
// mHeight(24.0),
// getFilesListWidget(),
// mHeight(20.0),
// // SizedBox(
// // height: 150.0,
// // width: MediaQuery.of(context).size.width,
// // child: (ekgRealTimeDataResponseModel != null && ekgRealTimeDataResponseModel.wave != null)
// // ? LineChart(
// // LineChartData(
// // lineTouchData: LineTouchData(handleBuiltInTouches: false),
// // gridData: FlGridData(
// // show: true,
// // verticalInterval: 30,
// // horizontalInterval: 30,
// // getDrawingVerticalLine: (value) {
// // return FlLine(
// // color: Colors.red[300],
// // strokeWidth: 0.4,
// // );
// // },
// // getDrawingHorizontalLine: (value) {
// // return FlLine(
// // color: Colors.red[300],
// // strokeWidth: 0.4,
// // );
// // },
// // ),
// // titlesData: FlTitlesData(show: true),
// // borderData: FlBorderData(
// // show: false,
// // border: Border.all(color: const Color(0xff37434d), width: 1),
// // ),
// // minX: 0,
// // // maxX: (ekgRealTimeDataResponseModel.wave.ecgBytes.length.toDouble() - 1),
// // maxX: ecgBytesAllDataList.length.toDouble(),
// // minY: ekgRealTimeDataResponseModel.wave.ecgBytes.reduce((value, element) => value < element ? value : element).toDouble(),
// // maxY: ekgRealTimeDataResponseModel.wave.ecgBytes.reduce((value, element) => value > element ? value : element).toDouble(),
// // lineBarsData: [
// // LineChartBarData(
// // isCurved: false,
// // preventCurveOverShooting: true,
// // barWidth: 0.5,
// // dotData: FlDotData(show: false),
// // // spots: getDataList(ekgRealTimeDataResponseModel.wave.ecgBytes),
// // spots: getDataList(ekgRealTimeDataResponseModel.wave.ecgBytes),
// // colors: [Colors.grey[800]],
// // isStrokeCapRound: true,
// // belowBarData: BarAreaData(show: false),
// // ),
// // ],
// // ),
// // )
// // : Container(),
// // ),
// ],
// );
// },
// ),
],
),
),
@ -130,6 +264,21 @@ class _EKG_BLEState extends State<EKG_BLE> {
ekgValueNotifier.value = ekgFilesList.toString();
}
List<FlSpot> getDataList(List<int> list) {
ecgBytesAllDataList.add(list[0]);
// ecgBytesAllDataList.addAll(list[0]);
// if(ecgBytesAllDataList.length >= 1250) {
// ecgBytesAllDataList.removeRange(0, 1200);
// }
List<FlSpot> spotsList = [];
for (int i = 0; i < ecgBytesAllDataList.length; i++) {
spotsList.add(FlSpot(i.toDouble(), ecgBytesAllDataList[i].toDouble()));
}
return spotsList;
}
Widget getFilesListWidget() {
return ListView.separated(
shrinkWrap: true,
@ -153,7 +302,19 @@ class _EKG_BLEState extends State<EKG_BLE> {
}
void parseEKGFileDetailObject(dynamic returnData) {
EKGFileDetailResponseModel ekgFileDetailResponseModel = EKGFileDetailResponseModel.fromJson(json.decode(returnData));
ekgFileDetailResponseModel = EKGFileDetailResponseModel.fromJson(json.decode(returnData));
Navigator.push(context, FadePage(page: EKGChartView(ekgFileDetailResponseModel: ekgFileDetailResponseModel)));
}
String parseEKGRealTimeDataObject(dynamic returnData) {
ekgRealTimeDataResponseModel = EKGRealTimeDataResponseModel.fromJson(json.decode(returnData));
return "HeartRate: ${ekgRealTimeDataResponseModel.param.hr} - Current State: ${ekgRealTimeDataResponseModel.param.curStatus}";
}
}
class _ChartData {
_ChartData(this.country, this.sales);
final int country;
final num sales;
}

@ -107,6 +107,9 @@ dependencies:
# Calendar
syncfusion_flutter_calendar: ^19.3.55
#Charts for Live ECG View
syncfusion_flutter_charts: ^19.3.55
# SVG Images
# flutter_svg: ^0.23.0+1

Loading…
Cancel
Save