· 6 years ago · May 04, 2020, 10:36 AM
1import 'dart:async';
2import 'dart:convert';
3import 'dart:io';
4
5import 'package:flutter/material.dart';
6import 'package:health_gauge/apis/PostMeasurementData.dart';
7import 'package:health_gauge/apis/PostSportData.dart';
8import 'package:health_gauge/apis/PostTagLabel.dart';
9import 'package:health_gauge/models/DeviceModel.dart';
10import 'package:health_gauge/models/Tag.dart';
11import 'package:health_gauge/models/TagNote.dart';
12import 'package:health_gauge/models/infoModels/DeviceInfoModel.dart';
13import 'package:health_gauge/models/infoModels/HeartInfoModel.dart';
14import 'package:health_gauge/models/infoModels/MotionInfoModel.dart';
15import 'package:health_gauge/models/infoModels/SleepInfoModel.dart';
16import 'package:health_gauge/models/infoModels/WoHeartInfoModel.dart';
17import 'package:health_gauge/models/measurement/EcgInfoReadingModel.dart';
18import 'package:health_gauge/models/measurement/MeasurementHistoryModel.dart';
19import 'package:health_gauge/screens/SettingScreen.dart';
20import 'package:health_gauge/screens/SleepHistoryPage.dart';
21import 'package:health_gauge/screens/SportActivityScreen.dart';
22import 'package:health_gauge/utils/Connections.dart';
23import 'package:health_gauge/utils/Constants.dart';
24import 'package:health_gauge/utils/DatabaseHelper.dart';
25import 'package:health_gauge/value/AppColor.dart';
26import 'package:health_gauge/value/Images.dart';
27import 'package:health_gauge/widgets/Buttons.dart';
28import 'package:health_gauge/widgets/TextUtils.dart';
29import 'package:intl/intl.dart';
30import 'package:percent_indicator/linear_percent_indicator.dart';
31import 'package:shared_preferences/shared_preferences.dart';
32
33import 'package:flutter_screenutil/flutter_screenutil.dart';
34
35import '../main.dart';
36import 'ConnectionScreen.dart';
37import 'MesurementScreen.dart';
38import 'ProfileScreen.dart';
39import 'SignInScreen.dart';
40
41Images images = new Images();
42
43class DashBoardScreen extends StatefulWidget {
44 DashBoardScreen({Key key}) : super(key: key);
45
46 @override
47 DashBoardScreenState createState() => DashBoardScreenState();
48}
49
50class DashBoardScreenState extends State<DashBoardScreen> implements PerformerListener {
51 bool isLoading;
52 bool isErrorInGetMessage = false;
53
54 SharedPreferences sharedPreferences;
55
56 String userId;
57
58 //this model is use for display measurement hr, bp and hrv
59 EcgInfoReadingModel ecgInfoReadingModel;
60
61 //this is mac address of last connected device
62 DeviceModel connectedDevice;
63
64 //this class is use for doing connection utilities like for find that "is device connected or not?"
65 Connections connections;
66
67 //this model used at activity card
68 MotionInfoModel motionInfoModel;
69
70 //this model will use in sleep card
71 SleepInfoModel sleepModel;
72
73 //this model is use for get battery level
74 DeviceInfoModel deviceInfoModel;
75
76 //this is use for store data table wise in local storage
77 final dbHelper = DatabaseHelper.instance;
78
79 double targetSteps = 2000;
80
81 Timer timer;
82
83 int targetMinute = 480;
84
85 @override
86 void initState() {
87 dbHelper.database;
88 //this is registering data listener for whenever data came from sdk then that will be in this class's listener
89 connections = Connections(performerListener: this);
90
91 getPreferences();
92
93 timerForCheckConnection();
94
95 getEcgInfoReadingData();
96 syncDataToApi();
97 super.initState();
98 }
99
100 void syncDataToApi() async {
101 await getPreferences();
102 bool isInternet = await Constants.isInternetAvailable();
103 if (isInternet && userId != null && userId.isNotEmpty && !userId.contains("Skip")) {
104 syncMotionInfoList();
105 syncSleepInfoList();
106 syncMeasurementData();
107 syncTagLabels();
108 syncTagNotes();
109 }
110 }
111
112 @override
113 Widget build(BuildContext context) {
114 print("${MediaQuery.of(context) }");
115 ScreenUtil.init(context, width: 423.5294196844927, height: 752.9411905502093, allowFontScaling: true);
116
117 return SafeArea(
118 top: false,
119 bottom: Platform.isIOS,
120 child: Scaffold(
121 appBar: AppBar(
122 leading: IconButton(
123 icon: Icon(Icons.account_circle, size: 25.0.h),
124 onPressed: () {
125 if (userId == null || userId.contains("Skip")) {
126 var dialog = AlertDialog(
127 title: Text(strings.appName),
128 content: Text(strings.pleaseLoginFirstToUseThisFeature),
129 actions: <Widget>[
130 FlatBtn(
131 onPressed: () {
132 Navigator.of(context, rootNavigator: true).pop();
133 },
134 text: strings.cancel),
135 FlatBtn(
136 onPressed: () async {
137 await Constants.logout();
138 Constants.navigatePushAndRemove(
139 SignInScreen(), context,
140 rootNavigation: true);
141 },
142 text: strings.ok),
143 ],
144 );
145 showDialog(
146 context: context,
147 useRootNavigator: true,
148 builder: (context) => dialog);
149 } else {
150 Constants.navigatePush(ProfileScreen(), context,
151 rootNavigation: false);
152 }
153 },
154 ),
155 title: Container(
156 child: Stack(
157 overflow: Overflow.visible,
158 alignment: Alignment.center,
159 children: <Widget>[
160 Positioned(
161 left: -16.0.w,
162 child: batteryWidget(),
163 ),
164 Container(
165 margin: EdgeInsets.only(left: 15.0.w),
166 alignment: Alignment.center,
167 child: Text(
168 strings.dashBoardName,
169 style: TextStyle(fontSize: 14.0.sp), // changed
170 ),
171 ),
172 ],
173 ),
174 ),
175 actions: <Widget>[
176 bluetoothBtn(context),
177 IconButton(
178 icon: Icon(Icons.settings,size: 25.0.h,),
179 onPressed: () async {
180 await Constants.navigatePush(SettingScreen(), context,
181 rootNavigation: false);
182 getStepTarget();
183 getSleepTarget();
184 },
185 ),
186 ],
187 ),
188 body: layoutMain(),
189 ),
190 );
191 }
192
193 Widget batteryWidget() {
194 if (deviceInfoModel != null && deviceInfoModel.power != null) {
195 return Tooltip(
196 child: RotatedBox(
197 quarterTurns: 135,
198 child: Container(
199 child: Stack(
200 alignment: Alignment.center,
201 children: <Widget>[
202 RotatedBox(
203 quarterTurns: 45,
204 child: Image.asset(
205 "asset/battery.png",
206 color: Colors.white,
207 height: 30.0.h,
208 width: 30.0.h,
209 ),
210 ),
211 Container(
212 child: LinearPercentIndicator(
213 width: 45.0.w,
214 lineHeight: 12.0.h,
215 backgroundColor: Colors.transparent,
216 percent: (deviceInfoModel.power + 0.0) / 100,
217 center: RotatedBox(
218 quarterTurns: 45,
219 child: new CaptionText(
220 text: deviceInfoModel.power >= 100
221 ? ""
222 : "${deviceInfoModel.power}",
223 color: Colors.black)),
224 progressColor: Colors.white,
225 linearStrokeCap: LinearStrokeCap.butt,
226 ),
227 )
228 ],
229 ),
230 ),
231 ),
232 message: strings.deviceBattery,
233 );
234 }
235 return Container();
236 }
237
238 Widget bluetoothBtn(BuildContext context) {
239 return IconButton(
240 padding: EdgeInsets.only(right: 8.0.w), // changed
241 icon: Icon(
242 connectedDevice != null ? Icons.bluetooth : Icons.bluetooth_disabled , size: 25.0.h,),
243 onPressed: () async {
244 timer.cancel();
245 var result = await Constants.navigatePush(ConnectionScreen(performerListener: this), context, rootNavigation: false);
246 timerForCheckConnection();
247
248 var value = sharedPreferences.getString(Constants.connectedDeviceAddressPrefKey);
249 if (value != null) {
250 var val = jsonDecode(value);
251 if (val is Map) {
252 connectedDevice = DeviceModel.fromMap(val);
253 }
254 } else {
255 deviceInfoModel = null;
256 connectedDevice = null;
257 getSleepData();
258 getMotionData();
259 }
260 if (mounted) {
261 setState(() {});
262 }
263 },
264 );
265 }
266
267 Timer timerForCheckConnection() {
268 return timer = Timer.periodic(Duration(seconds: 5), (val) {
269 if(deviceInfoModel == null) {
270 connections = Connections(performerListener: this);
271 getPreferences();
272 }
273 });
274 }
275
276 Widget layoutMain() {
277 return dataLayout();
278 }
279
280 Widget dataLayout() {
281 return ListView(
282 // padding: EdgeInsets.all(8.0),
283 padding: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
284 shrinkWrap: true,
285 children: <Widget>[
286 healthCard(),
287 activityCard(),
288 sleepCard(),
289 ],
290 );
291 }
292
293 Card healthCard() {
294 if (ecgInfoReadingModel == null) {
295 ecgInfoReadingModel = new EcgInfoReadingModel();
296 ecgInfoReadingModel.approxHr = 0;
297 ecgInfoReadingModel.hrv = 0;
298 ecgInfoReadingModel.approxSBP = 0;
299 }
300 return Card(
301 child: InkWell(
302 onTap: () {
303 onClickMeasurement();
304 },
305 child: Column(
306 crossAxisAlignment: CrossAxisAlignment.stretch,
307 children: <Widget>[
308 Container(
309// margin: EdgeInsets.all(8.0),
310// padding: EdgeInsets.all(8.0),
311 margin: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
312 padding: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
313 color: Colors.grey[200],
314
315 child: Column(
316 children: <Widget>[
317 Row(
318 mainAxisAlignment: MainAxisAlignment.spaceBetween,
319 crossAxisAlignment: CrossAxisAlignment.start,
320 children: <Widget>[
321 Body1Text(text: strings.bp),
322 Body1Text(
323 text: ecgInfoReadingModel.approxSBP != null
324 ? ecgInfoReadingModel.approxSBP.toString()
325 : strings.offLineEcgSbp),
326 ],
327 ),
328 SizedBox(height: 8.0.h),
329 Row(
330 mainAxisAlignment: MainAxisAlignment.spaceBetween,
331 crossAxisAlignment: CrossAxisAlignment.start,
332 children: <Widget>[
333 Body1Text(text: strings.heartRate),
334 Body1Text(
335 text: ecgInfoReadingModel.approxHr != null
336 ? ecgInfoReadingModel.approxHr.toString()
337 : "0"),
338 ],
339 ),
340 SizedBox(height: 8.0.h),
341 Row(
342 mainAxisAlignment: MainAxisAlignment.spaceBetween,
343 crossAxisAlignment: CrossAxisAlignment.start,
344 children: <Widget>[
345 Body1Text(text: strings.hrv),
346 Body1Text(
347 text: ecgInfoReadingModel.hrv != null
348 ? ecgInfoReadingModel.hrv.toString()
349 : "0"),
350 ],
351 ),
352 ],
353 ),
354 ),
355 Container(
356 height: 40.0.h,
357 child: Row(
358 mainAxisAlignment: MainAxisAlignment.center,
359 children: <Widget>[
360 TitleText(text: strings.health, color: AppColor.primaryColor),
361 SizedBox(width: 5.0.w),
362 Image.asset(
363 "asset/goal.png",
364 height: 25.0.h,
365 width: 25.0.w,
366 )
367 ],
368 ),
369 )
370 ],
371 ),
372 ),
373 );
374 }
375
376 Card activityCard() {
377 if (motionInfoModel == null) {
378 motionInfoModel =
379 new MotionInfoModel(calories: 0, distance: 0, date: "0", step: 0);
380 }
381 return Card(
382 child: InkWell(
383 onTap: () {
384 Constants.navigatePush(SportActivityScreen(), context);
385 },
386 child: Column(
387 crossAxisAlignment: CrossAxisAlignment.stretch,
388 children: <Widget>[
389 Container(
390// margin: EdgeInsets.all(8.0),
391// padding: EdgeInsets.all(8.0),
392 margin: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
393 padding: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
394 color: Colors.grey[200],
395
396 child: Column(
397 children: <Widget>[
398 Row(
399 mainAxisAlignment: MainAxisAlignment.spaceBetween,
400 crossAxisAlignment: CrossAxisAlignment.start,
401 children: <Widget>[
402 Body1Text(text: strings.complete),
403 completeTxt(),
404 ],
405 ),
406 SizedBox(height: 8.0.h),
407 Row(
408 mainAxisAlignment: MainAxisAlignment.spaceBetween,
409 crossAxisAlignment: CrossAxisAlignment.start,
410 children: <Widget>[
411 Body1Text(text: strings.steps),
412 Body1Text(
413 text: motionInfoModel.step != null
414 ? motionInfoModel.step.toString()
415 : "0"),
416 ],
417 ),
418 SizedBox(height: 8.0.h),
419 Row(
420 mainAxisAlignment: MainAxisAlignment.spaceBetween,
421 crossAxisAlignment: CrossAxisAlignment.start,
422 children: <Widget>[
423 Body1Text(text: strings.calories),
424 Body1Text(
425 text: motionInfoModel.calories != null
426 ? double.parse(motionInfoModel.calories
427 .toStringAsFixed(2))
428 .toString() +
429 strings.kml
430 : strings.zeroKml),
431 ],
432 ),
433 SizedBox(height: 8.0.h),
434 Row(
435 mainAxisAlignment: MainAxisAlignment.spaceBetween,
436 crossAxisAlignment: CrossAxisAlignment.start,
437 children: <Widget>[
438 Body1Text(text: strings.distance),
439 Body1Text(
440 text: motionInfoModel.distance != null
441 ? double.parse(motionInfoModel.distance
442 .toStringAsFixed(2))
443 .toString() +
444 strings.km
445 : strings.zeroKm),
446 ],
447 ),
448 ],
449 ),
450 ),
451 Container(
452 height: 40.0.h,
453 child: Row(
454 mainAxisAlignment: MainAxisAlignment.center,
455 children: <Widget>[
456 TitleText(
457 text: strings.activity, color: AppColor.primaryColor),
458 SizedBox(width: 5.0.w),
459 Image.asset(
460 "asset/running_sport_icon.png",
461 height: 25.0.h,
462 width: 25.0.w,
463 )
464 ],
465 ),
466 )
467 ],
468 ),
469 ),
470 );
471 }
472
473 Body1Text completeTxt() {
474 int step = 0;
475 if (motionInfoModel == null || motionInfoModel.step == null) {
476 step = 0;
477 } else {
478 step = motionInfoModel.step;
479 }
480 /*if (targetSteps < step) {
481 targetSteps = step + 0.0;
482 }*/
483 return Body1Text(
484 text: ((step * 100) / targetSteps).toStringAsFixed(2) + "%");
485 }
486
487 Card sleepCard() {
488 String time = "0";
489 String complete = "0%";
490 if (sleepModel != null) {
491 if (sleepModel.data.length > 0) {
492 int hour = sleepModel.sleepAllTime~/60;
493 int minute = (sleepModel.sleepAllTime%60).toInt();
494 time = "${hour.toString().padLeft(2, "0")} h ${minute.toString().padLeft(2, "0")} m";
495 int completePercentage = (sleepModel.sleepAllTime * 100) ~/ targetMinute;
496 complete = "$completePercentage%";
497 }
498 }
499 return Card(
500 child: InkWell(
501 onTap: () {
502 Constants.navigatePush(SleepHistoryScreen(), context);
503 },
504 child: Column(
505 crossAxisAlignment: CrossAxisAlignment.stretch,
506 children: <Widget>[
507 Container(
508// margin: EdgeInsets.all(8.0),
509// padding: EdgeInsets.all(8.0),
510 margin: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
511 padding: EdgeInsets.only(top: 8.0.h, right: 8.0.w, left: 8.0.w, bottom: 8.0.h),
512 color: Colors.grey[200],
513 child: Column(
514 children: <Widget>[
515 Row(
516 mainAxisAlignment: MainAxisAlignment.spaceBetween,
517 crossAxisAlignment: CrossAxisAlignment.start,
518 children: <Widget>[
519 Body1Text(text: strings.sleepHour),
520 Body1Text(text: "$time"),
521 ],
522 ),
523 SizedBox(height: 8.0.h),
524 Row(
525 mainAxisAlignment: MainAxisAlignment.spaceBetween,
526 crossAxisAlignment: CrossAxisAlignment.start,
527 children: <Widget>[
528 Body1Text(text: strings.complete),
529 Body1Text(text: "$complete"),
530 ],
531 ),
532 ],
533 ),
534 ),
535 Container(
536 height: 40.0.h,
537 child: Row(
538 mainAxisAlignment: MainAxisAlignment.center,
539 children: <Widget>[
540 TitleText(text: strings.sleep, color: AppColor.primaryColor),
541 SizedBox(width: 5.0.w),
542 Image.asset(
543 "asset/sleep_icon.png",
544 height: 25.0.h,
545 width: 25.0.w,
546 )
547 ],
548 ),
549 )
550 ],
551 ),
552 ));
553 }
554
555 static String convertHoursMinutes(String time) {
556 //=======to calculate hours_minutes=========
557 int value_total_minutes = int.parse(time) % 60;
558 double value_total_hours = int.parse(time) / 60;
559
560 /*DecimalFormat decimalFormat = new DecimalFormat("#0");
561 String final_hours_value = String.valueOf(decimalFormat.format(value_total_hours));*/
562 return time;
563 }
564
565 void onClickGraph() {}
566
567 void onClickMeasurement() async {
568 timer.cancel();
569 await Constants.navigatePush(MeasurementScreen(), context);
570 timerForCheckConnection();
571 getEcgInfoReadingData();
572 }
573
574 //in this will get device info like battery, name, etc..
575 @override
576 void onResponseDeviceInfo(DeviceInfoModel deviceInfo) {
577 deviceInfoModel = deviceInfo;
578 print("Flutter device info" + deviceInfoModel.toString());
579 if (mounted) {
580 setState(() {});
581 }
582 }
583
584 //in this we will get activity info like steps,kms,etc.
585 @override
586 Future<void> onResponseMotionInfo(MotionInfoModel mMotionInfo) async {
587 this.motionInfoModel = mMotionInfo;
588 // print("Flutter Motion Info Model " + motionInfoModel.toString());
589 await saveMotionDataToDb(mMotionInfo);
590 if (mounted) {
591 setState(() {});
592 }
593 }
594
595 //in this we will get sleep info
596 @override
597 Future<void> onResponseSleepInfo(SleepInfoModel mSleepInfo) async {
598 //Type sleep duration (0: stay up all night, 1: sleep, 2: light sleep, 3: deep sleep, 4: wake up halfway, 5: get up)
599 sleepModel = mSleepInfo;
600 print("Flutter Sleep Info Model " + sleepModel.toString());
601 await saveSleepDataToDb(sleepModel);
602 if (mounted) {
603 setState(() {});
604 }
605 }
606
607 @override
608 void onResponsePoHeartInfo(HeartInfoModel mPoHeartInfo) {
609 //todo implement onResponsePoHeartInfo
610 }
611
612 @override
613 void onResponseWoHeartInfo(WoHeartInfoModel mWoHeartInfo) {
614 // TODO: implement onResponseWoHeartInfo
615 }
616
617 //this method is called after every update in watch..........
618 //save activity data to local and also post if internet is available
619 Future saveMotionDataToDb(MotionInfoModel mMotionInfo) async {
620 if (userId == null) {
621 return;
622 }
623
624 Map map = mMotionInfo.toMap();
625 map.putIfAbsent("user_Id", () => userId);
626
627 List<MotionInfoModel> motions =
628 await dbHelper.getActivityData(userId.toString());
629 if (motions.length > 0) {
630 MotionInfoModel model = motions.last;
631 DateTime dateTime = DateTime.parse(model.date);
632 DateTime currentDate = DateTime.now();
633 if (currentDate.isAfter(dateTime) &&
634 currentDate.difference(dateTime).inHours > 1) {
635 await postMotionData(mMotionInfo);
636 }
637 } else {
638 await postMotionData(mMotionInfo);
639 }
640 print(motions);
641 }
642
643 //save sleep data to local and also post if internet is available
644 Future saveSleepDataToDb(SleepInfoModel sleepInfoModel) async {
645 if (userId == null) {
646 return;
647 }
648 Map<String, dynamic> map = sleepInfoModel.toMap();
649 map.putIfAbsent("user_Id", () => userId);
650
651 List<SleepInfoModel> sleeps =
652 await dbHelper.getSleepData(userId.toString());
653 if (sleeps.length > 0) {
654 SleepInfoModel model = sleeps.last;
655 DateTime dateTime = DateTime.parse(model.date);
656 DateTime currentDate = DateTime.now();
657 if (currentDate.isAfter(dateTime) &&
658 currentDate.difference(dateTime).inHours > 1) {
659 postSleepData(sleepInfoModel);
660 }
661 } else {
662 postSleepData(sleepInfoModel);
663 }
664 }
665
666 //call api for post activity data
667 Future postMotionData(MotionInfoModel model) async {
668 Map<String, dynamic> dbMap = model.toMap();
669 if (model.id != null && model.id != 0) {
670 dbMap.putIfAbsent("id", () => model.id);
671 }
672 dbMap.putIfAbsent("user_Id", () => userId);
673 bool isInternet = await Constants.isInternetAvailable();
674 if (isInternet && !userId.contains("Skip")) {
675 Map map = {
676 "userid": userId,
677 "motionCalorie": model.calories,
678 "motionDate": model.date,
679 "motionDistance": model.distance,
680 "motionSteps": model.step
681 };
682 Map result = await PostSportsData().callApi(
683 Constants.baseUrl + "StoreMotionRecordDtls", jsonEncode(map));
684 print("motion data result = $result");
685 if (!result["isError"]) {
686 dbMap.putIfAbsent("IsSync", () => true);
687 } else {
688 dbMap.putIfAbsent("IsSync", () => false);
689 }
690 int insertResult = await dbHelper.insertActivityData(dbMap);
691 print("insertResult $insertResult");
692 } else {
693 dbMap.putIfAbsent("IsSync", () => false);
694 int insertResult = await dbHelper.insertActivityData(dbMap);
695 print("insertResult $insertResult");
696 }
697 }
698
699 //call api for post sleep data
700 Future postSleepData(SleepInfoModel model) async {
701 Map<String, dynamic> dbMap = model.toMap();
702 dbMap.putIfAbsent("user_Id", () => userId);
703 if (model.id != null && model.id != 0) {
704 dbMap.putIfAbsent("id", () => model.id);
705 }
706 bool isInternet = await Constants.isInternetAvailable();
707 if (isInternet && !userId.contains("Skip")) {
708 Map map = model.toMapForApi();
709 map.putIfAbsent("id", () => 0);
710 map.putIfAbsent("userid", () => userId);
711 map.putIfAbsent("username", () => "");
712 Map result = await PostSportsData()
713 .callApi(Constants.baseUrl + "StoreSleepRecordDtls", jsonEncode(map));
714 if (!result["isError"]) {
715 dbMap.putIfAbsent("IsSync", () => true);
716 } else {
717 dbMap.putIfAbsent("IsSync", () => false);
718 }
719 int insertResult = await dbHelper.insertSleepData(dbMap);
720 print("insertResult $insertResult");
721 } else {
722 dbMap.putIfAbsent("IsSync", () => false);
723 int result = await dbHelper.insertSleepData(dbMap);
724 print("insertResult $result");
725 }
726 }
727
728 //get hr, bp and hrv from local database
729 getEcgInfoReadingData() async {
730 if (sharedPreferences == null) {
731 await getPreferences();
732 }
733 await dbHelper
734 .getMeasurementData(userId)
735 .then((List<EcgInfoReadingModel> ecgList) {
736 if (ecgList.length > 0) {
737 ecgInfoReadingModel = ecgList.last;
738 if (mounted) {
739 setState(() {});
740 }
741 }
742 });
743 }
744
745 //get activity data from local
746 getMotionData() async {
747 if (sharedPreferences == null) {
748 await getPreferences();
749 }
750 if (connectedDevice == null) {
751 dbHelper
752 .getActivityData(userId.toString())
753 .then((List<MotionInfoModel> motionInfoList) {
754 if (motionInfoList.length > 0) {
755 motionInfoModel = motionInfoList.last;
756 if (mounted) {
757 setState(() {});
758 }
759 }
760 });
761 }
762 }
763
764 //get sleep data from local
765 getSleepData() async {
766 if (sharedPreferences == null) {
767 await getPreferences();
768 }
769 dbHelper
770 .getSleepData(userId.toString())
771 .then((List<SleepInfoModel> sleepInfoList) {
772 if (sleepInfoList.length > 0) {
773 sleepModel = sleepInfoList.last;
774 if (mounted) {
775 setState(() {});
776 }
777 }
778 });
779 }
780
781 syncMotionInfoList() async {
782 await getPreferences();
783 if (userId != null) {
784 try {
785 List<MotionInfoModel> motions =
786 await dbHelper.getActivityData(userId.toString());
787 for (MotionInfoModel model in motions) {
788 if (model.isSync == 0) {
789 await postMotionData(model);
790 }
791 }
792 } catch (e) {
793 print(e);
794 }
795 }
796 }
797
798 syncSleepInfoList() async {
799 await getPreferences();
800 if (userId != null) {
801 try {
802 List<SleepInfoModel> list =
803 await dbHelper.getSleepData(userId.toString());
804 for (SleepInfoModel model in list) {
805 if (model.isSync == 0) {
806 await postSleepData(model);
807 }
808 }
809 } catch (e) {
810 print(e);
811 }
812 }
813 }
814
815 syncMeasurementData() async {
816 await getPreferences();
817 if (userId != null) {
818 try {
819 List<MeasurementHistoryModel> list =
820 await dbHelper.getMeasurementData1(userId);
821 for (MeasurementHistoryModel model in list) {
822 if (model.isSync == 0) {
823 await postMeasurementData(model);
824 }
825 }
826 } catch (e) {
827 print(e);
828 }
829 }
830 }
831
832 syncTagLabels() async {
833 await getPreferences();
834 if (userId != null) {
835 List<Tag> tagList = await dbHelper.getUnSyncTagList(userId);
836 for (Tag tag in tagList) {
837 //region post to api
838 Map postMap = {
839 "ImageName" : tag.icon,
840 "UnitName" : tag.unit,
841 "LabelName": tag.label,
842 "MinRange": tag.min,
843 "MaxRange": tag.max,
844 "DefaultValue": tag.defaultValue,
845 "PrecisionDigit": tag.precision
846 };
847 Map result;
848 if(tag.apiId != null && tag.apiId.isNotEmpty){
849 postMap.putIfAbsent("ID", ()=>tag.apiId);
850 result = await PostTagLabel().callApi(Constants.baseUrl + "EditTagLabel", jsonEncode(postMap));
851 }else{
852 result = await PostTagLabel().callApi(Constants.baseUrl + "AddTagLabel", jsonEncode(postMap));
853 }
854 if (!result["isError"]) {
855 tag.apiId = result["value"];
856 tag.isSync = 1;
857 }
858 //endregion
859
860 //region update in database
861 Map map = tag.toMap();
862 map.putIfAbsent("Id", () => tag.id);
863 var value = await dbHelper.insertTag(map);
864 print("update tag $value");
865 //endregion
866 }
867 }
868 }
869
870 syncTagNotes() async {
871 await getPreferences();
872 if (userId != null) {
873 List<TagNote> tagNoteList = await dbHelper.getUnSyncTagNoteList(userId);
874 for (TagNote note in tagNoteList) {
875 //region post to api
876 String date =
877 DateFormat("yyyy/dd/mm").format(DateTime.parse(note.date));
878 Map postMap = {
879 "date": "$date",
880 "note": note.note,
881 "time": timeOfDayString(note),
882 "type": note.label,
883 "userId": userId,
884 "value": note.value
885 };
886 Map result;
887 if(note.apiId != null && note.apiId.isNotEmpty){
888 postMap.putIfAbsent("ID", ()=>note.apiId);
889 result = await PostTagLabel().callApi(Constants.baseUrl + "EditTagRecordDtls", jsonEncode(postMap));
890 }else{
891 result = await PostTagLabel().callApi(Constants.baseUrl + "StoreTagRecordDtls", jsonEncode(postMap));
892 }
893 if (!result["isError"]) {
894 note.isSync = 1;
895 note.apiId = result["value"];
896 }
897 //endregion
898
899 //region update in database
900 Map map = note.toMap();
901 map.putIfAbsent("Id", () => note.id);
902 var value = await dbHelper.insertTagNote(map);
903 print("update tag $value");
904 //endregion
905 }
906 }
907 }
908
909 String timeOfDayString(TagNote tagSlider) {
910 String time;
911 try {
912 tagSlider.time = tagSlider.time.replaceAll("TimeOfDay(", "");
913 tagSlider.time = tagSlider.time.replaceAll(")", "");
914 TimeOfDay timeOfDay = TimeOfDay(
915 hour: int.parse(tagSlider.time.split(":")[0]),
916 minute: int.parse(tagSlider.time.split(":")[1]));
917 time =
918 "${timeOfDay.hour.toString().padLeft(2, "0")}:${timeOfDay.minute.toString().padLeft(2, "0")}:00";
919 } catch (e) {
920 print(e);
921 }
922 return time ?? "00:00:00";
923 }
924
925 Future postMeasurementData(MeasurementHistoryModel model) async {
926 if (userId.contains("Skip")) {
927 return Future.value();
928 }
929 Map<String, dynamic> dbMap = new Map<String, dynamic>();
930 dbMap.putIfAbsent("user_Id", () => userId);
931 if (model.id != null && model.id != 0) {
932 dbMap.putIfAbsent("id", () => model.id);
933 }
934 bool isInternet = await Constants.isInternetAvailable();
935 if (isInternet) {
936 Map map = {
937 "birthdate": "",
938 "data": [
939 {
940 "bg_manual": 0,
941 "demographics": {"age": 0, "gender": "", "height": 0, "weight": 0},
942 "device_id": "",
943 "device_type": "",
944 "dias_healthgauge": 0,
945 "o2_manual": 0,
946 "schema": "",
947 "sys_healthgauge": 0,
948 "username": "",
949 "model_id": "PROTO_1",
950
951 "userID": userId,
952 "raw_ecg": model.ecg,
953 "raw_ppg": model.ppg,
954 "raw_times": [], //todo this is remaining
955 "hrv_device": model.hrv,
956 "dias_device": model.dbp,
957 "hr_device": model.hr,
958 "sys_device": model.sbp,
959 "timestamp":
960 DateTime.parse(model.date).millisecondsSinceEpoch.toString(),
961 "sys_manual": model.tSbp ?? 0,
962 "dias_manual": model.tDbp ?? 0,
963 "hr_manual": model.tHr ?? 0,
964 }
965 ]
966 };
967 Map result = await PostMeasurementData()
968 .callApi(Constants.baseUrl + "estimate", jsonEncode(map));
969 if (!result["isError"]) {
970 await dbHelper.updateSyncInMeasurement(model.id);
971 }
972 }
973 }
974
975 @override
976 void onConnectIosDevice(DeviceModel device) async {
977 connectedDevice = device;
978 if (sharedPreferences == null) {
979 sharedPreferences = await SharedPreferences.getInstance();
980 }
981 sharedPreferences.setString(
982 Constants.connectedDeviceAddressPrefKey, jsonEncode(device.toMap()));
983 if (mounted) {
984 setState(() {});
985 }
986 }
987
988 Future<void> callApi() async {
989 isLoading = false;
990 if (mounted) {
991 setState(() {});
992 }
993 }
994
995 void popTillThis() {
996 Navigator.of(context).popUntil((route) => route.isFirst);
997 getEcgInfoReadingData();
998 if(timer == null || !timer.isActive){
999 timerForCheckConnection();
1000 }
1001 }
1002
1003 getPreferences() async {
1004 sharedPreferences = await SharedPreferences.getInstance();
1005 userId = sharedPreferences.getString(Constants.prefUserIdKeyInt);
1006
1007 getStepTarget();
1008 getSleepTarget();
1009
1010 String value = sharedPreferences.getString(Constants.connectedDeviceAddressPrefKey);
1011 if (value != null) {
1012 var val = jsonDecode(value);
1013 if (val is Map) {
1014 connectedDevice = DeviceModel.fromMap(val);
1015 }
1016 }
1017 //region this is checking that device is connected or not
1018 Future.delayed(Duration(milliseconds: 500)).then((_) {
1019 connections.isConnected().then((bool isConnected) {
1020 if (isConnected == null || !isConnected) {
1021 //code for not connected
1022 connectedDevice = null;
1023 deviceInfoModel = null;
1024 sharedPreferences.remove(Constants.connectedDeviceAddressPrefKey);
1025 getSleepData();
1026 getMotionData();
1027 if (mounted) {
1028 setState(() {});
1029 }
1030 }else{
1031 //code for connected
1032 //region set default
1033 var wearOnLeft = sharedPreferences.getBool(Constants.isWearOnLeftKey) ?? true;
1034 connections.setWearType(wearOnLeft);
1035
1036 bool isLiftTheWristBrightnessOn = sharedPreferences.getBool(Constants.isLiftTheWristBrightnessOnKey) ?? true;
1037 bool isDoNotDisturb = sharedPreferences.getBool(Constants.isDoNotDisturbKey) ?? false;
1038 bool timeFormat24h = sharedPreferences.getBool(Constants.isTimeFormat24hKey) ?? true;
1039 bool isHourlyHrMonitorOn = sharedPreferences.getBool(Constants.isHourlyHrMonitorOnKey) ?? false;
1040
1041 if(Platform.isAndroid){
1042 connections.setLiftTheWristBrightnessOn(isLiftTheWristBrightnessOn);
1043 connections.setDoNotDisturb(isDoNotDisturb);
1044 connections.setTimeFormat(timeFormat24h);
1045 connections.setHourlyHrMonitorOn(isHourlyHrMonitorOn);
1046 }else{
1047 Map map = {
1048 "hrMonitor":isHourlyHrMonitorOn,
1049 "liftBrighten":isLiftTheWristBrightnessOn,
1050 "doNotDisturb":isDoNotDisturb,
1051 "timeFormat":timeFormat24h,
1052 };
1053 connections.sendDataToSDK(map);
1054 }
1055
1056 //endregion
1057 }
1058 });
1059 });
1060 //endregion
1061
1062 if (mounted) {
1063 setState(() {});
1064 }
1065 }
1066
1067 void getStepTarget() {
1068 String strJsonForStep =
1069 sharedPreferences.getString(Constants.prefSavedStepTarget);
1070 if (strJsonForStep != null && strJsonForStep.isNotEmpty) {
1071 Map map = jsonDecode(strJsonForStep);
1072 if (map != null && map.containsKey("userId")) {
1073 if (map["userId"] == userId) {
1074 if (map.containsKey("step") && map["step"] > 0) {
1075 targetSteps = map["step"].toDouble();
1076 }
1077 }
1078 }
1079 }
1080 }
1081
1082 void getSleepTarget() {
1083 String strJson1 = sharedPreferences.getString(Constants.prefSavedSleepTarget);
1084 if (strJson1 != null && strJson1.isNotEmpty) {
1085 Map map = jsonDecode(strJson1);
1086 if (map != null && map.containsKey("userId")) {
1087 if (map["userId"] == userId) {
1088 int hour = 8;
1089 int minute = 0;
1090 if (map.containsKey("hour")) {
1091 hour = map["hour"].toInt();
1092 }
1093 if (map.containsKey("minute")) {
1094 minute = map["minute"].toInt();
1095 }
1096 targetMinute = (hour*60) + minute;
1097 }
1098 }
1099 }
1100 }
1101}