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