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