· 6 years ago · May 02, 2020, 02:24 PM
1import 'dart:async';
2import 'dart:convert';
3import 'dart:io';
4
5import 'package:flutter/material.dart';
6import 'package:flutter/services.dart';
7import 'package:health_gauge/apis/PostMeasurementData.dart';
8import 'package:health_gauge/apis/SignIn.dart';
9import 'package:health_gauge/models/measurement/EcgInfoReadingModel.dart';
10import 'package:health_gauge/models/measurement/MeasurementHistoryModel.dart';
11import 'package:health_gauge/models/measurement/PpgInfoReadingModel.dart';
12import 'package:health_gauge/screens/ConnectionScreen.dart';
13
14import 'package:health_gauge/utils/Connections.dart';
15import 'package:health_gauge/utils/Constants.dart';
16import 'package:health_gauge/utils/DatabaseHelper.dart';
17
18import 'package:health_gauge/widgets/Buttons.dart';
19import 'package:health_gauge/widgets/TextUtils.dart';
20import 'package:mp_chart/mp/chart/line_chart.dart';
21import 'package:mp_chart/mp/controller/line_chart_controller.dart';
22import 'package:mp_chart/mp/core/data/line_data.dart';
23import 'package:mp_chart/mp/core/data_set/line_data_set.dart';
24import 'package:mp_chart/mp/core/description.dart';
25import 'package:mp_chart/mp/core/entry/entry.dart';
26import 'package:mp_chart/mp/core/enums/mode.dart';
27import 'package:mp_chart/mp/core/utils/color_utils.dart';
28import 'package:shared_preferences/shared_preferences.dart';
29
30import 'package:flutter_screenutil/flutter_screenutil.dart';
31
32import '../main.dart';
33
34class MeasurementScreen extends StatefulWidget {
35 final MeasurementHistoryModel measurementHistoryModel;
36
37 const MeasurementScreen({Key key, this.measurementHistoryModel})
38 : super(key: key);
39
40 @override
41 MeasurementScreenState createState() => MeasurementScreenState();
42}
43
44class MeasurementScreenState extends State<MeasurementScreen> implements MeasurementListener {
45
46 bool isLoading;
47 bool isErrorInGetMessage = false;
48
49
50 //those are controller, value set and last value of ecg graph
51 LineChartController controllerForEcgGraph;
52 List<Entry> valuesForEcgGraph = List();
53 double ecgValueX = 0.0;
54 LineDataSet ecgDataSet;
55
56 //those are controller, value set and last value of ppg graph
57 LineChartController controllerForPpgGraph;
58 List<Entry> valuesForPpgGraph = List();
59 double ppgValueX = 0.0;
60
61 //connections utilities for start ans stop measurement
62 Connections connections;
63 bool isMeasuring = false;
64
65 //this are use is graph and measurement
66 EcgInfoReadingModel ecgInfoModel;
67 PpgInfoReadingModel ppgInfoModel;
68
69 //local storing method's variables
70 DatabaseHelper helper = DatabaseHelper.instance;
71 String userId;
72 SharedPreferences sharedPreferences;
73
74 List ecgPointList = new List();
75 List ppgPointList = new List();
76
77 //text edit controller for training param
78 TextEditingController hrTextEditController = new TextEditingController();
79 TextEditingController sdbTextEditController = new TextEditingController();
80 TextEditingController bdbTextEditController = new TextEditingController();
81
82 TextEditingController hrCalibrationTextEditController =
83 new TextEditingController();
84 TextEditingController sbpCalibrationTextEditController =
85 new TextEditingController();
86 TextEditingController dbpCalibrationTextEditController =
87 new TextEditingController();
88
89 var startTimeEcg;
90 var startTimePpg;
91 var endTimeEcg;
92 var endTimePpg;
93
94 List ecgElapsedList = new List();
95 List ppgElapsedList = new List();
96
97 Timer timer;
98
99 @override
100 void initState() {
101 getPreferences();
102 helper.database;
103 initGraphControllers();
104 setDefaultMeasurementForHistory();
105 timer = Timer.periodic(Duration(seconds: 5), (_)async{
106 if(connections == null) {
107 connections = new Connections(measurementListener: this);
108 bool isConnected = await connections.isConnected(isFromMeasurement: true);
109 }
110 });
111 super.initState();
112 }
113
114 @override
115 Widget build(BuildContext context) {
116 if (endTimePpg != null && endTimeEcg != null) {
117 if (endTimePpg > 0 && endTimeEcg > 0 && isMeasuring) {
118 isMeasuring = false;
119 Future.delayed(Duration(seconds: 1), () {
120 postMeasurementData();
121 });
122 }
123 }
124
125 return Container(
126 color: Colors.white,
127 child: SafeArea(
128 bottom: true,
129 top: false,
130 child: Scaffold(
131 appBar: AppBar(
132 centerTitle: true,
133 title: Text(strings.measurement),
134 actions: <Widget>[
135 IconButton(
136 icon: Icon(Icons.help_outline, size: 30.0),
137 onPressed: () {},
138 ),
139 IconButton(
140 icon: Icon(Icons.more_vert, size: 30.0),
141 onPressed: () {
142 showCalibrationDialog(onClickOk: () {
143 Navigator.of(context, rootNavigator: true).pop();
144 int hr = int.parse(hrCalibrationTextEditController.text);
145 int sbp = int.parse(sbpCalibrationTextEditController.text);
146 int dbp = int.parse(dbpCalibrationTextEditController.text);
147 if (connections == null) {
148 connections = new Connections(measurementListener: this);
149 }
150 connections.setCelebration(hr: hr, sbp: sbp, dbp: dbp);
151 });
152 },
153 ),
154 ],
155 ),
156 body: layoutMain(),
157 bottomNavigationBar: Padding(
158 padding: EdgeInsets.symmetric(horizontal: 20.0),
159 child: RaisedBtn(
160 onPressed: isMeasuring
161 ? () async {
162 await onClickStop(context);
163 }
164 : () async {
165 await onClickStart(context);
166 },
167 text: isMeasuring
168 ? strings.stopMeasurement.toUpperCase()
169 : strings.startMeasurement.toUpperCase(),
170 ),
171 ),
172 ),
173 ),
174 );
175 }
176
177 onClickStop(BuildContext context) {
178 startTimeEcg = null;
179 startTimePpg = null;
180 connections.stopMeasurement();
181 isMeasuring = false;
182 setState(() {});
183 }
184
185 Future onClickStart(BuildContext context) async {
186 connections = new Connections(measurementListener: this);
187 bool isConnected = await connections.isConnected(isFromMeasurement: true);
188 if (isConnected) {
189 ecgValueX = 0.0;
190 ppgValueX = 0.0;
191
192 ecgPointList.clear();
193 ppgPointList.clear();
194
195 valuesForPpgGraph.clear();
196 valuesForEcgGraph.clear();
197 connections.startMeasurement();
198 isMeasuring = true;
199 endTimeEcg = null;
200 endTimePpg = null;
201
202 showInitDialog();
203 setState(() {});
204 } else {
205 Constants.navigatePush(ConnectionScreen(), context);
206 }
207 }
208
209 Widget layoutMain() {
210 return dataLayout();
211 }
212
213 Widget dataLayout() {
214 return ListView(
215 shrinkWrap: true,
216 children: <Widget>[
217 measurementCard(),
218 ecgCard(),
219 ppgCard(),
220 ],
221 );
222 }
223
224 Widget measurementCard() {
225 String hr = "0";
226 String bp = "0";
227 String hrv = "0";
228 String countDown = "0";
229 if (ecgInfoModel != null) {
230 if (ecgInfoModel.approxHr != null) {
231 hr = "${ecgInfoModel.approxHr}";
232 }
233 if (ecgInfoModel.approxSBP != null && ecgInfoModel.approxDBP != null) {
234 bp = "${ecgInfoModel.approxSBP} / ${ecgInfoModel.approxDBP}";
235 }
236 if (ecgInfoModel.approxHr != null) {
237 hr = "${ecgInfoModel.approxHr}";
238 }
239 if (ecgInfoModel.hrv != null) {
240 hrv = "${ecgInfoModel.hrv}";
241 }
242 countDown = "${((Constants.maximumReadCount - ecgValueX) / 125).round()}";
243 }
244 return Card(
245 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
246 elevation: 4.0,
247 margin: EdgeInsets.only(top: 10.0.h, left: 20.0.w, right: 20.0.w),
248 child: Padding(
249 padding: const EdgeInsets.all(8.0),
250 child: Column(
251 children: <Widget>[
252 Row(
253 children: <Widget>[
254 Expanded(
255 child: Column(
256 children: <Widget>[
257 SubTitleText(text: "$hr"),
258 SizedBox(height: 5.0.h),
259 Body1Text(text: strings.hrBPM),
260 ],
261 ),
262 ),
263 Expanded(
264 child: Column(
265 children: <Widget>[
266 SubTitleText(text: "$bp"),
267 SizedBox(height: 5.0.h),
268 Body1Text(text: strings.bpMmHg),
269 ],
270 ),
271 ),
272 Expanded(
273 child: Column(
274 children: <Widget>[
275 SubTitleText(text: "$hrv"),
276 SizedBox(height: 5.0.h),
277 Body1Text(text: strings.hrv),
278 ],
279 ),
280 )
281 ],
282 ),
283 SizedBox(height: 5.0.h),
284 Body1Text(text: "${strings.countDown} $countDown")
285 ],
286 ),
287 ),
288 );
289 }
290
291 Widget ecgCard() {
292 return Card(
293 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
294 elevation: 4.0,
295 margin: EdgeInsets.only(top: 20.0.h, left: 20.0.w, right: 20.0.w),
296 child: Column(
297 children: <Widget>[
298 SizedBox(height: 10.0.h),
299 Body1Text(text: strings.ecg),
300 SizedBox(height: 10.0.h),
301 Container(
302 decoration: BoxDecoration(
303 border: Border(top: BorderSide(color: Colors.grey[100]))),
304 height: MediaQuery.of(context).size.height / 4,
305 width: MediaQuery.of(context).size.width,
306 child: ClipRRect(
307 borderRadius: BorderRadius.all(Radius.circular(20)),
308 child: LineChart(controllerForEcgGraph),
309 ),
310 ),
311 ],
312 ),
313 );
314 }
315
316 Widget ppgCard() {
317 return Card(
318 shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
319 elevation: 4.0,
320 margin: EdgeInsets.only(top: 20.0.h, left: 20.0.w, right: 20.0.w),
321 child: Column(
322 children: <Widget>[
323 SizedBox(height: 10.0.h),
324 Body1Text(text: strings.ppg),
325 SizedBox(height: 10.0.h),
326 Container(
327 height: MediaQuery.of(context).size.height / 4,
328 width: MediaQuery.of(context).size.width,
329 decoration: BoxDecoration(
330 border: Border(top: BorderSide(color: Colors.grey[100]))),
331 child: ClipRRect(
332 borderRadius: BorderRadius.all(Radius.circular(20)),
333 child: LineChart(controllerForPpgGraph),
334 ),
335 ),
336 ],
337 ),
338 );
339 }
340
341 showCalibrationDialog({GestureTapCallback onClickOk}) {
342 var dialog = AlertDialog(
343 title: Text(strings.calibration),
344 content: SingleChildScrollView(
345 child: Column(
346 mainAxisAlignment: MainAxisAlignment.start,
347 crossAxisAlignment: CrossAxisAlignment.stretch,
348 children: <Widget>[
349 Body1Text(text: strings.shortDescription, maxLine: 3),
350 SizedBox(height: 15.0.h),
351 TextFormField(
352 controller: hrCalibrationTextEditController,
353 decoration: InputDecoration(
354 border: OutlineInputBorder(),
355 hintText: strings.hr,
356 labelText: strings.hr,
357 ),
358 inputFormatters: <TextInputFormatter>[
359 WhitelistingTextInputFormatter.digitsOnly
360 ], // Only numbers
361 keyboardType: TextInputType.number,
362 ),
363 SizedBox(height: 15.0.h),
364 TextFormField(
365 controller: sbpCalibrationTextEditController,
366 decoration: InputDecoration(
367 hintText: strings.sbd,
368 labelText: strings.sbd,
369 border: OutlineInputBorder(),
370 ),
371
372 inputFormatters: <TextInputFormatter>[
373 WhitelistingTextInputFormatter.digitsOnly
374 ], // Only numbers
375 keyboardType: TextInputType.number,
376 ),
377 SizedBox(height: 15.0.h),
378 TextFormField(
379 controller: dbpCalibrationTextEditController,
380 decoration: InputDecoration(
381 hintText: strings.dbp,
382 labelText: strings.dbp,
383 border: OutlineInputBorder(),
384 ),
385
386 inputFormatters: <TextInputFormatter>[
387 WhitelistingTextInputFormatter.digitsOnly
388 ], // Only numbers
389 keyboardType: TextInputType.number,
390 ),
391 SizedBox(height: 10.0.h),
392 Row(
393 children: <Widget>[
394 Expanded(
395 child: RaisedBtn(
396 onPressed: () {
397 Navigator.of(context, rootNavigator: true).pop();
398 },
399 text: strings.cancel.toUpperCase(),
400 elevation: 0,
401 ),
402 ),
403 SizedBox(width: 10.0.w),
404 Expanded(
405 child: RaisedBtn(
406 onPressed: onClickOk,
407 text: strings.add.toUpperCase(),
408 elevation: 0,
409 ),
410 ),
411 ],
412 )
413 ],
414 ),
415 ),
416 );
417 showDialog(
418 context: context,
419 useRootNavigator: true,
420 builder: (context) => dialog,
421 barrierDismissible: false);
422 }
423
424 Future<void> callApi() async {
425 final Map result = await new SignIn().callApi("", "");
426 if (!result["isError"]) {
427 print(result["value"]);
428 } else {
429 isErrorInGetMessage = true;
430 }
431
432 isLoading = false;
433 setState(() {});
434 }
435
436 void initGraphControllers() {
437 var desc = Description()..enabled = false;
438 controllerForEcgGraph = LineChartController(
439 axisLeftSettingFunction: (axisLeft, controller) {
440 axisLeft.drawGridLines = (false);
441 },
442 axisRightSettingFunction: (axisRight, controller) {
443 axisRight.enabled = (false);
444 },
445 legendSettingFunction: (legend, controller) {
446 legend.enabled = (false);
447 },
448 xAxisSettingFunction: (xAxis, controller) {
449 xAxis
450 ..drawGridLines = (true)
451 ..drawAxisLine = (false);
452 },
453 drawGridBackground: true,
454 dragXEnabled: true,
455 dragYEnabled: true,
456 scaleXEnabled: true,
457 scaleYEnabled: false,
458 description: desc,
459 );
460 controllerForPpgGraph = LineChartController(
461 axisLeftSettingFunction: (axisLeft, controller) {
462 axisLeft.drawGridLines = (false);
463 },
464 axisRightSettingFunction: (axisRight, controller) {
465 axisRight.enabled = (false);
466 },
467 legendSettingFunction: (legend, controller) {
468 legend.enabled = (false);
469 },
470 xAxisSettingFunction: (xAxis, controller) {
471 xAxis
472 ..drawGridLines = (true)
473 ..drawAxisLine = (false);
474 },
475 drawGridBackground: true,
476 dragXEnabled: true,
477 dragYEnabled: true,
478 scaleXEnabled: true,
479 scaleYEnabled: false,
480 description: desc,
481 );
482 }
483
484 @override
485 void onGetEcg(EcgInfoReadingModel ecgInfoReadingModel) {
486 startTimeEcg = ecgInfoReadingModel.startTime;
487 if (((Constants.maximumReadCount - ecgValueX) / 125).round() == 0) {
488 endTimeEcg = ecgInfoReadingModel.endTime;
489 } else {
490 if (ecgInfoReadingModel != null &&
491 ecgInfoReadingModel.ecgPointY != null) {
492 ecgInfoModel = ecgInfoReadingModel;
493 ecgValueX++;
494 if (ecgValueX > 500) {
495 double y = ecgInfoReadingModel.ecgPointY;
496 if (!Platform.isIOS) {
497 y = y * -1;
498 }
499
500 ecgPointList.add(y);
501
502 Entry entry = new Entry(
503 x: ecgValueX,
504 y: y,
505 );
506 valuesForEcgGraph.add(entry);
507 setDataToEcgGraph();
508 controllerForEcgGraph.setVisibleXRangeMaximum(500);
509 controllerForEcgGraph.moveViewToX(ecgValueX - 700);
510 controllerForEcgGraph.axisLeft.enabled = false;
511 }
512 }
513 }
514 setState(() {});
515 }
516
517 @override
518 void onGetPpg(PpgInfoReadingModel ppgInfoReadingModel) {
519 startTimePpg = ppgInfoReadingModel.startTime;
520 if (((Constants.maximumReadCount - ppgValueX) / 125).round() == 0) {
521 endTimePpg = ppgInfoReadingModel.endTime;
522 } else {
523 if (ppgInfoReadingModel != null && ppgInfoReadingModel.point != null) {
524 ppgInfoModel = ppgInfoReadingModel;
525 ppgValueX++;
526 if (ppgValueX > 500) {
527 double y = ppgInfoReadingModel.point;
528 /*if (!Platform.isIOS) {
529 y = y * -1;
530 }*/
531 ppgPointList.add(y);
532
533 Entry entry = new Entry(
534 x: ppgValueX,
535 y: y,
536 );
537 valuesForPpgGraph.add(entry);
538 setDataToPpgGraph();
539 controllerForPpgGraph.setVisibleXRangeMaximum(500);
540 controllerForPpgGraph.moveViewToX(ppgValueX - 700);
541 }
542 }
543 }
544 setState(() {});
545 }
546
547 void setDataToPpgGraph() {
548 LineDataSet ppgDataSet = new LineDataSet(valuesForPpgGraph, "PpgDataSet 1");
549 ppgDataSet.setColor1(ColorUtils.BLACK);
550 ppgDataSet.setLineWidth(0.8);
551 ppgDataSet.setDrawValues(false);
552 ppgDataSet.setDrawCircles(false);
553 ppgDataSet.setMode(Mode.LINEAR);
554 ppgDataSet.setDrawFilled(false);
555
556 try {
557 if (ppgDataSet.values == null) {
558 ppgDataSet.setValues(valuesForPpgGraph);
559 }
560 } catch (e) {
561 print("Error $e");
562 }
563
564 controllerForPpgGraph.gridBackColor = Colors.green.withAlpha(50);
565 controllerForPpgGraph.drawMarkers = false;
566 controllerForPpgGraph.data = LineData.fromList(List()..add(ppgDataSet));
567 controllerForPpgGraph.axisLeft.enabled = false;
568
569 setState(() {});
570 }
571
572 void setDataToEcgGraph() {
573 ecgDataSet = new LineDataSet(valuesForEcgGraph, "EcgDataSet 1");
574 ecgDataSet.setColor1(ColorUtils.BLACK);
575 ecgDataSet.setLineWidth(0.8);
576 ecgDataSet.setDrawValues(false);
577 ecgDataSet.setDrawCircles(false);
578 ecgDataSet.setMode(Mode.LINEAR);
579 ecgDataSet.setDrawFilled(false);
580
581 try {
582 if (ecgDataSet.values == null) {
583 ecgDataSet.setValues(valuesForEcgGraph);
584 }
585 } catch (e) {
586 print("Error $e");
587 }
588
589 controllerForEcgGraph.gridBackColor = Colors.green.withAlpha(50);
590 controllerForEcgGraph.drawMarkers = false;
591 controllerForEcgGraph.data = LineData.fromList(List()..add(ecgDataSet));
592
593 setState(() {});
594 }
595
596 setDefaultMeasurementForHistory() {
597 if (controllerForEcgGraph == null) {
598 initGraphControllers();
599 }
600 Future.delayed(Duration(milliseconds: 500)).then((_) {
601 if (widget.measurementHistoryModel != null) {
602 List ppgList = widget.measurementHistoryModel.ppg;
603 List ecgList = widget.measurementHistoryModel.ecg;
604 for (int i = 0; i < ppgList.length; i++) {
605 ppgValueX = i + 0.0;
606 Entry entry = new Entry(
607 x: ppgValueX,
608 y: double.parse(ppgList[i]),
609 );
610 valuesForPpgGraph.add(entry);
611 }
612 for (int i = 0; i < ecgList.length; i++) {
613 ecgValueX = i + 0.0;
614
615 Entry entry = new Entry(
616 x: ecgValueX,
617 y: double.parse(ecgList[i]),
618 );
619 valuesForEcgGraph.add(entry);
620 }
621
622 setDataToPpgGraph();
623 controllerForPpgGraph.setVisibleXRangeMaximum(500);
624 controllerForPpgGraph.moveViewToX(ppgValueX - 700);
625 controllerForPpgGraph.axisLeft.enabled = false;
626
627 setDataToEcgGraph();
628 controllerForEcgGraph.setVisibleXRangeMaximum(500);
629 controllerForEcgGraph.moveViewToX(ecgValueX - 700);
630 controllerForEcgGraph.axisLeft.enabled = false;
631
632 //region set models
633 ecgInfoModel = new EcgInfoReadingModel();
634 ecgInfoModel.hrv = widget.measurementHistoryModel.hrv;
635 ecgInfoModel.approxHr = widget.measurementHistoryModel.hr;
636 ecgInfoModel.approxSBP = widget.measurementHistoryModel.sbp;
637 ecgInfoModel.approxDBP = widget.measurementHistoryModel.dbp;
638 ecgInfoModel.ecgPointY =
639 double.parse(widget.measurementHistoryModel.ecg.last);
640
641 ppgInfoModel = new PpgInfoReadingModel();
642 ppgInfoModel.point =
643 double.parse(widget.measurementHistoryModel.ppg.last);
644 //endregion
645
646 setState(() {});
647
648 Future.delayed(Duration(milliseconds: 500)).then((_) {
649 setZoom();
650 setState(() {});
651 });
652 }
653 });
654 }
655
656 setZoom() {
657 if (controllerForPpgGraph != null) {
658 controllerForPpgGraph.setVisibleXRangeMaximum(500);
659 controllerForPpgGraph.moveViewToX(ppgValueX - 700);
660 controllerForPpgGraph.axisLeft.enabled = false;
661 }
662 if (controllerForEcgGraph != null) {
663 controllerForEcgGraph.setVisibleXRangeMaximum(500);
664 controllerForEcgGraph.moveViewToX(ecgValueX - 700);
665 controllerForEcgGraph.axisLeft.enabled = false;
666 }
667 }
668
669 //call api for post activity data
670 Future postMeasurementData() async {
671 Constants.progressDialog(true, context);
672 int hr = 0;
673 int sbp = 0;
674 int dbp = 0;
675 if (sharedPreferences == null) {
676 await getPreferences();
677 }
678 hrTextEditController.text = "";
679 sdbTextEditController.text = "";
680 bdbTextEditController.text = "";
681 bool isTrainingEnable = sharedPreferences.getBool(Constants.isTrainingEnableKey) ?? false;
682 if (isTrainingEnable) {
683 await showTrainingDialog(onClickOk: () {
684 Navigator.of(context, rootNavigator: true).pop();
685 hr = int.parse(hrTextEditController.text);
686 sbp = int.parse(sdbTextEditController.text);
687 dbp = int.parse(bdbTextEditController.text);
688 });
689 }
690 bool isInternet = await Constants.isInternetAvailable();
691 if (userId!=null&& userId.isNotEmpty&& !userId.contains("Skip")&&isInternet) {
692 Map map = {
693 "birthdate": "",
694 "data": [
695 {
696 "bg_manual": 0,
697 "demographics": {"age": 0, "gender": "", "height": 0, "weight": 0},
698 "device_id": "",
699 "device_type": "",
700 "dias_healthgauge": 0,
701 "o2_manual": 0,
702 "schema": "",
703 "sys_healthgauge": 0,
704 "username": "",
705 "model_id": "PROTO_1",
706
707 "userID": userId,
708 "raw_ecg": ecgPointList,
709 "raw_ppg": ppgPointList,
710 "raw_times": [], //todo this is remaining
711 "hrv_device": ecgInfoModel.hrv,
712 "dias_device": ecgInfoModel.approxDBP,
713 "hr_device": ecgInfoModel.approxHr,
714 "sys_device": ecgInfoModel.approxSBP,
715 "timestamp": DateTime.now().millisecondsSinceEpoch.toString(),
716 "sys_manual": sbp,
717 "dias_manual": dbp,
718 "hr_manual": hr,
719 "ecg_elapsed_time": [startTimeEcg, endTimeEcg],
720 "ppg_elapsed_time": [startTimePpg, endTimePpg],
721 }
722 ]
723 };
724 Map result = await PostMeasurementData()
725 .callApi(Constants.baseUrl + "estimate", jsonEncode(map));
726 if (!result["isError"]) {
727 await saveMeasurementDataToLocalStorage(
728 trainingHr: hr, trainingDBP: dbp, trainingSBP: sbp, isSync: true);
729 } else {
730 await saveMeasurementDataToLocalStorage(
731 trainingHr: hr, trainingDBP: dbp, trainingSBP: sbp, isSync: false);
732 }
733 }
734 else {
735 await saveMeasurementDataToLocalStorage(trainingHr: hr, trainingDBP: dbp, trainingSBP: sbp, isSync: false);
736 }
737
738 endTimeEcg = null;
739 endTimePpg = null;
740 Constants.progressDialog(false, context);
741 }
742
743 Future saveMeasurementDataToLocalStorage({bool isSync, int trainingHr, int trainingSBP, int trainingDBP}) async {
744 //region point string
745 String strEcgList = "";
746 String strPpgList = "";
747 for (double value in ecgPointList) {
748 strEcgList += value.toString() + ",";
749 }
750 if (strEcgList.isNotEmpty) {
751 strEcgList = strEcgList.substring(0, strEcgList.length - 1);
752 print("ecg $strEcgList");
753 }
754
755 for (double value in ppgPointList) {
756 strPpgList += value.toString() + ",";
757 }
758 if (strPpgList.isNotEmpty) {
759 strPpgList = strPpgList.substring(0, strPpgList.length - 1);
760 print("ppg $strPpgList");
761 }
762 //endregion
763
764 String strEcgTimeList = "";
765 String strPpgTimeList = "";
766 for (double value in ecgElapsedList) {
767 strEcgTimeList += value.toString() + ",";
768 }
769 if (strEcgTimeList.isNotEmpty) {
770 strEcgTimeList = strEcgTimeList.substring(0, strEcgTimeList.length - 1);
771 }
772
773 for (double value in ppgElapsedList) {
774 strPpgTimeList += value.toString() + ",";
775 }
776 if (strPpgTimeList.isNotEmpty) {
777 strPpgTimeList = strPpgTimeList.substring(0, strPpgTimeList.length - 1);
778 }
779
780 if (userId == null) {
781 return Future.value();
782 }
783 Map<String, dynamic> map = ecgInfoModel.toMap();
784 map.putIfAbsent("ppgValue", () => ppgInfoModel.point);
785 map.putIfAbsent("user_Id", () => userId);
786 map.putIfAbsent("date", () => DateTime.now().toString());
787 map.putIfAbsent("ecg", () => strEcgList);
788 map.putIfAbsent("ppg", () => strPpgList);
789 map.putIfAbsent("tHr", () => trainingHr);
790 map.putIfAbsent("tSBP", () => trainingSBP);
791 map.putIfAbsent("tDBP", () => trainingDBP);
792 map.putIfAbsent("IsSync", () => isSync);
793 var result = await helper.insertMeasurementData(map, userId);
794 return;
795 }
796
797 void onClickTraining() {
798 showTrainingDialog(onClickOk: () {
799 Navigator.of(context, rootNavigator: true).pop();
800 });
801 }
802
803 showTrainingDialog({GestureTapCallback onClickOk}) async {
804 var dialog = AlertDialog(
805 title: Text(strings.training),
806 content: SingleChildScrollView(
807 child: Column(
808 mainAxisAlignment: MainAxisAlignment.start,
809 crossAxisAlignment: CrossAxisAlignment.stretch,
810 children: <Widget>[
811 Body1Text(text: strings.shortDescription, maxLine: 3),
812 SizedBox(height: 15.0.h),
813 TextFormField(
814 controller: hrTextEditController,
815 decoration: InputDecoration(
816 border: OutlineInputBorder(),
817 hintText: strings.hr,
818 labelText: strings.hr,
819 ),
820 inputFormatters: <TextInputFormatter>[
821 WhitelistingTextInputFormatter.digitsOnly
822 ], // Only numbers
823 keyboardType: TextInputType.number,
824 ),
825 SizedBox(height: 15.0.h),
826 TextFormField(
827 controller: sdbTextEditController,
828 decoration: InputDecoration(
829 hintText: strings.sbd,
830 labelText: strings.sbd,
831 border: OutlineInputBorder(),
832 ),
833
834 inputFormatters: <TextInputFormatter>[
835 WhitelistingTextInputFormatter.digitsOnly
836 ], // Only numbers
837 keyboardType: TextInputType.number,
838 ),
839 SizedBox(height: 15.0.h),
840 TextFormField(
841 controller: bdbTextEditController,
842 decoration: InputDecoration(
843 hintText: strings.dbp,
844 labelText: strings.dbp,
845 border: OutlineInputBorder(),
846 ),
847
848 inputFormatters: <TextInputFormatter>[
849 WhitelistingTextInputFormatter.digitsOnly
850 ], // Only numbers
851 keyboardType: TextInputType.number,
852 ),
853 SizedBox(height: 10.0.h),
854 Row(
855 children: <Widget>[
856 Expanded(
857 child: RaisedBtn(
858 onPressed: () {
859 Navigator.of(context, rootNavigator: true).pop();
860 },
861 text: strings.cancel.toUpperCase(),
862 elevation: 0,
863 ),
864 ),
865 SizedBox(width: 10.0.w),
866 Expanded(
867 child: RaisedBtn(
868 onPressed: onClickOk,
869 text: strings.add.toUpperCase(),
870 elevation: 0,
871 ),
872 ),
873 ],
874 )
875 ],
876 ),
877 ),
878 );
879 await showDialog(
880 context: context,
881 useRootNavigator: true,
882 builder: (context) => dialog,
883 barrierDismissible: false);
884 }
885
886 showInitDialog() async {
887 var dialog = AlertDialog(
888 backgroundColor: Colors.transparent,
889 content: Column(
890 mainAxisSize: MainAxisSize.min,
891 children: <Widget>[
892 TimerWidget(),
893 ],
894 ),
895 );
896 showDialog(
897 context: context,
898 useRootNavigator: true,
899 builder: (context) => dialog,
900 barrierDismissible: false);
901 }
902
903 void popTillThis() {
904 Navigator.of(context).popUntil((route) => route.isFirst);
905 if(timer == null || !timer.isActive){
906 timer = Timer.periodic(Duration(seconds: 5), (_)async{
907 if(connections == null) {
908 connections = new Connections(measurementListener: this);
909 bool isConnected = await connections.isConnected(isFromMeasurement: true);
910 }
911 });
912 }
913 }
914
915 Future getPreferences() async {
916 sharedPreferences = await SharedPreferences.getInstance();
917 userId = sharedPreferences.getString(Constants.prefUserIdKeyInt);
918 setState(() {});
919 }
920}
921
922class TimerWidget extends StatefulWidget {
923 @override
924 _TimerWidgetState createState() => _TimerWidgetState();
925}
926
927class _TimerWidgetState extends State<TimerWidget> {
928 int strTime = 3;
929
930 @override
931 void initState() {
932 Timer.periodic(Duration(seconds: 1), (t) {
933 strTime = strTime - 1;
934 if (strTime == 0) {
935 Navigator.of(context, rootNavigator: true).pop();
936 }
937 if (mounted) {
938 setState(() {});
939 }
940 });
941 super.initState();
942 }
943
944 @override
945 Widget build(BuildContext context) {
946 return Center(
947 child: Display1Text(
948 text: strTime.toString(),
949 color: Colors.white,
950 ));
951 }
952}