Commit 790fc3bf2bb0bddf37ec9a0290bf194e8be08e34
1 parent
90cd21c2ba
Exists in
master
update: fix bug count step
Showing 7 changed files with 200 additions and 25 deletions Side-by-side Diff
- app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java
- app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java
- app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java
- app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java
- app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java
- app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java
- app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java
app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryContentFragment.java
... | ... | @@ -71,6 +71,8 @@ |
71 | 71 | TextView tvSmallRemain; |
72 | 72 | @BindView(R.id.tv_stepGoal) |
73 | 73 | TextView tvGoal; |
74 | + @BindView(R.id.tv_stepRemain) | |
75 | + TextView tv_stepRemain; | |
74 | 76 | |
75 | 77 | @BindView(R.id.tv_caloConsumned) |
76 | 78 | TextView tvCaloConsumned; |
... | ... | @@ -264,12 +266,12 @@ |
264 | 266 | int status = jsonObject.optInt("status"); |
265 | 267 | if (status == 1) { |
266 | 268 | JSONObject jsonObject1 = jsonObject.optJSONObject("result"); |
267 | - JSONObject jsonMod1 = jsonObject1.getJSONObject("mode_1"); | |
268 | - JSONObject jsonMod2 = jsonObject1.getJSONObject("mode_2"); | |
269 | - JSONObject jsonMod3 = jsonObject1.getJSONObject("mode_3"); | |
270 | - addDataModWalking(jsonMod1); | |
271 | - addDataModRunning(jsonMod2); | |
272 | - addDataModBike(jsonMod3); | |
269 | + JSONObject jsonMod1 = jsonObject1.optJSONObject("mode_1"); | |
270 | + JSONObject jsonMod2 = jsonObject1.optJSONObject("mode_2"); | |
271 | + JSONObject jsonMod3 = jsonObject1.optJSONObject("mode_3"); | |
272 | + if (jsonMod1 != null)addDataModWalking(jsonMod1); | |
273 | + if (jsonMod2 != null)addDataModRunning(jsonMod2); | |
274 | + if (jsonMod3 != null)addDataModBike(jsonMod3); | |
273 | 275 | |
274 | 276 | } |
275 | 277 | } catch (JSONException e) { |
... | ... | @@ -295,6 +297,7 @@ |
295 | 297 | tvGoal.setText(getResources().getString(R.string.step_unit, mDataCurrent.getTaget())); |
296 | 298 | tvStep.setText(getResources().getString(R.string.step_unit, mDataCurrent.getSteps())); |
297 | 299 | tvSmallRemain.setText(getResources().getString(R.string.step_unit_1, mDataCurrent.getStepRemain())); |
300 | + tv_stepRemain.setText(mDataCurrent.getStepRemain() + getResources().getString(R.string.step)); | |
298 | 301 | tvRemain.setText(getResources().getString(R.string.step_unit, mDataCurrent.getStepRemain())); |
299 | 302 | tvRateDone.setText(getResources().getString(R.string.percent_unit, Utils.convert2String2Decimal(mDataCurrent.getCompletePercent()))); |
300 | 303 | tvCaloConsumned.setText(getResources().getString(R.string.kcal_unit, Utils.convert2String2Decimal(mDataCurrent.getKcal()))); |
app/src/main/java/com/dinhcv/lifelogpedometer/activity/HistoryDetailFragment.java
... | ... | @@ -235,9 +235,9 @@ |
235 | 235 | int status = jsonObject.optInt("status"); |
236 | 236 | if (status == 1) { |
237 | 237 | JSONObject jsonObject1 = jsonObject.optJSONObject("result"); |
238 | - JSONObject jsonMod1 = jsonObject1.getJSONObject("mode_1"); | |
239 | - JSONObject jsonMod2 = jsonObject1.getJSONObject("mode_2"); | |
240 | - JSONObject jsonMod3 = jsonObject1.getJSONObject("mode_3"); | |
238 | + JSONObject jsonMod1 = jsonObject1.optJSONObject("mode_1"); | |
239 | + JSONObject jsonMod2 = jsonObject1.optJSONObject("mode_2"); | |
240 | + JSONObject jsonMod3 = jsonObject1.optJSONObject("mode_3"); | |
241 | 241 | //addDataModWalking(jsonMod1); |
242 | 242 | //addDataModRunning(jsonMod2); |
243 | 243 | //addDataModBike(jsonMod3); |
app/src/main/java/com/dinhcv/lifelogpedometer/activity/TopTodayFragment.java
... | ... | @@ -23,6 +23,7 @@ |
23 | 23 | |
24 | 24 | import com.dinhcv.lifelogpedometer.R; |
25 | 25 | import com.dinhcv.lifelogpedometer.interfaces.LLAPIManagerListener; |
26 | +import com.dinhcv.lifelogpedometer.interfaces.StepListener; | |
26 | 27 | import com.dinhcv.lifelogpedometer.model.StepModel; |
27 | 28 | import com.dinhcv.lifelogpedometer.model.structure.top.StepItemInfo; |
28 | 29 | import com.dinhcv.lifelogpedometer.model.structure.top.TopInfo; |
... | ... | @@ -31,6 +32,7 @@ |
31 | 32 | import com.dinhcv.lifelogpedometer.utils.Const; |
32 | 33 | import com.dinhcv.lifelogpedometer.utils.DayAxisValueFormatter; |
33 | 34 | import com.dinhcv.lifelogpedometer.utils.Debug; |
35 | +import com.dinhcv.lifelogpedometer.utils.SimpleStepDetector; | |
34 | 36 | import com.dinhcv.lifelogpedometer.utils.Utils; |
35 | 37 | import com.github.mikephil.charting.components.XAxis; |
36 | 38 | import com.github.mikephil.charting.components.YAxis; |
... | ... | @@ -58,7 +60,7 @@ |
58 | 60 | import static com.github.mikephil.charting.utils.ColorTemplate.rgb; |
59 | 61 | |
60 | 62 | |
61 | -public class TopTodayFragment extends FragmentBase implements SettingFragmentPresenter, SensorEventListener { | |
63 | +public class TopTodayFragment extends FragmentBase implements SettingFragmentPresenter, SensorEventListener, StepListener { | |
62 | 64 | |
63 | 65 | private TextView stepsView; |
64 | 66 | private TextView tvStepGoal; |
... | ... | @@ -108,6 +110,9 @@ |
108 | 110 | private String[] mParties; |
109 | 111 | private Integer[] mStep; |
110 | 112 | private ProgressDialog progress; |
113 | + private boolean isAccelo = false; | |
114 | + private boolean isBusy = false; | |
115 | + private SimpleStepDetector simpleStepDetector; | |
111 | 116 | |
112 | 117 | private TopFragment mTopFragment; |
113 | 118 | public void setRootFragment(TopFragment frag) { |
... | ... | @@ -118,6 +123,7 @@ |
118 | 123 | public void onCreate(final Bundle savedInstanceState) { |
119 | 124 | super.onCreate(savedInstanceState); |
120 | 125 | setHasOptionsMenu(true); |
126 | + | |
121 | 127 | } |
122 | 128 | |
123 | 129 | @Override |
... | ... | @@ -127,6 +133,9 @@ |
127 | 133 | mContext = getActivity(); |
128 | 134 | sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); |
129 | 135 | |
136 | + simpleStepDetector = new SimpleStepDetector(); | |
137 | + simpleStepDetector.registerListener(this); | |
138 | + | |
130 | 139 | initView(v); |
131 | 140 | |
132 | 141 | // slice for the steps taken today |
... | ... | @@ -481,6 +490,8 @@ |
481 | 490 | Date date = mCalendar.getTime(); |
482 | 491 | tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date)); |
483 | 492 | mAnaDate = date; |
493 | + | |
494 | + getTopPage(mAnaDate, stepType); | |
484 | 495 | } |
485 | 496 | }); |
486 | 497 | |
... | ... | @@ -493,6 +504,8 @@ |
493 | 504 | Date date = mCalendar.getTime(); |
494 | 505 | tvDate.setText(Utils.dateToStringFormatDayMonthYearJp(date)); |
495 | 506 | mAnaDate = date; |
507 | + | |
508 | + getTopPage(mAnaDate, stepType); | |
496 | 509 | } |
497 | 510 | }); |
498 | 511 | |
... | ... | @@ -552,6 +565,8 @@ |
552 | 565 | |
553 | 566 | |
554 | 567 | private void updateUI(){ |
568 | + creatLogStep(); | |
569 | + | |
555 | 570 | Debug.normal("Step total================ "+ stepTotal); |
556 | 571 | int stepRemain = stepGoal - stepTotal; |
557 | 572 | double percentDone = stepTotal *100.0 / stepGoal; |
558 | 573 | |
559 | 574 | |
560 | 575 | |
561 | 576 | |
... | ... | @@ -590,25 +605,36 @@ |
590 | 605 | super.onResume(); |
591 | 606 | activityRunning = true; |
592 | 607 | Debug.normal("Today: "+ "Onresume "); |
608 | + | |
593 | 609 | Sensor countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER); |
594 | - if (countSensor != null) { | |
595 | - Debug.normal("Today: "+ "countSensor not null "); | |
596 | - sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI); | |
597 | - } else { | |
598 | - Debug.normal("Today: "+ "countSensor is null "); | |
599 | - Toast.makeText(mContext, getResources().getString(R.string.sensor_available), Toast.LENGTH_SHORT).show(); | |
610 | + if (countSensor == null) { | |
611 | + isAccelo = true; | |
612 | + countSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); | |
600 | 613 | } |
614 | + if (countSensor != null) { | |
615 | + Debug.normal("Today: " + "countSensor not null "); | |
616 | + sensorManager.registerListener(this, countSensor, SensorManager.SENSOR_DELAY_UI); | |
617 | + } else { | |
618 | + Debug.normal("Today: " + "countSensor is null "); | |
619 | + Toast.makeText(mContext, getResources().getString(R.string.sensor_available), Toast.LENGTH_SHORT).show(); | |
620 | + } | |
621 | + | |
601 | 622 | } |
602 | 623 | |
603 | 624 | @Override |
604 | 625 | public void onSensorChanged(SensorEvent event) { |
605 | - Debug.normal("Sensor count step active"); | |
626 | + //Debug.normal("Sensor count step active"); | |
606 | 627 | if (activityRunning){ |
607 | - stepCount = (int) event.values[0]; | |
608 | - Debug.normal("Step change: "+ stepCount); | |
609 | - stepTotal++; | |
610 | - // update UI | |
611 | - updateUI(); | |
628 | + if (isAccelo) { | |
629 | + simpleStepDetector.updateAccel( | |
630 | + event.timestamp, event.values[0], event.values[1], event.values[2]); | |
631 | + }else { | |
632 | + stepCount = (int) event.values[0]; | |
633 | + Debug.normal("Step change: " + stepCount); | |
634 | + stepTotal++; | |
635 | + // update UI | |
636 | + updateUI(); | |
637 | + } | |
612 | 638 | } |
613 | 639 | } |
614 | 640 | |
615 | 641 | |
... | ... | @@ -622,12 +648,11 @@ |
622 | 648 | super.onPause(); |
623 | 649 | activityRunning = false; |
624 | 650 | Debug.normal("Start create log"); |
625 | - mToDate = new Date(); | |
626 | 651 | if (sensorManager != null) { |
627 | 652 | sensorManager.unregisterListener(this); |
628 | 653 | } |
629 | 654 | // create log step |
630 | - creatLogStep(); | |
655 | + //creatLogStep(); | |
631 | 656 | } |
632 | 657 | |
633 | 658 | @Override |
634 | 659 | |
635 | 660 | |
636 | 661 | |
637 | 662 | |
... | ... | @@ -637,26 +662,39 @@ |
637 | 662 | |
638 | 663 | private void creatLogStep(){ |
639 | 664 | Debug.normal("Today: "+ "Create log "+ stepCount); |
665 | + mToDate = new Date(); | |
640 | 666 | |
641 | 667 | ApiServices.createLog(stepType, stepCount, mFromDate, mToDate, new LLAPIManagerListener() { |
642 | 668 | @Override |
643 | 669 | public void onError(Error error) { |
670 | + isBusy = false; | |
644 | 671 | Debug.error("Get data history error"); |
645 | 672 | } |
646 | 673 | |
647 | 674 | @Override |
648 | 675 | public void onSuccess(String json) { |
676 | + isBusy = false; | |
649 | 677 | Debug.error("Get data history success"); |
650 | 678 | } |
651 | 679 | |
652 | 680 | @Override |
653 | 681 | public void onSuccess(JSONObject object) { |
682 | + isBusy = false; | |
654 | 683 | Debug.error("Get data history success"); |
655 | 684 | } |
656 | 685 | }); |
657 | 686 | } |
658 | 687 | |
659 | 688 | |
660 | - | |
689 | + @Override | |
690 | + public void step(long timeNs) { | |
691 | + if (!isBusy) { | |
692 | + isBusy = true; | |
693 | + stepCount = 1; | |
694 | + stepTotal++; | |
695 | + // update UI | |
696 | + updateUI(); | |
697 | + } | |
698 | + } | |
661 | 699 | } |
app/src/main/java/com/dinhcv/lifelogpedometer/interfaces/StepListener.java
app/src/main/java/com/dinhcv/lifelogpedometer/portal/LLAPIManager.java
... | ... | @@ -997,6 +997,7 @@ |
997 | 997 | @Override |
998 | 998 | protected void onPreExecute() { |
999 | 999 | super.onPreExecute(); |
1000 | + | |
1000 | 1001 | } |
1001 | 1002 | |
1002 | 1003 | @Override |
... | ... | @@ -1020,6 +1021,7 @@ |
1020 | 1021 | = MediaType.parse("application/json"); |
1021 | 1022 | RequestBody requestBody = RequestBody.create(JSON, jsonObject.toString()); |
1022 | 1023 | |
1024 | + Debug.warn("token data: " + APIResponse.getInstance().getToken()); | |
1023 | 1025 | final Request.Builder request = new Request.Builder() |
1024 | 1026 | .url(baseUrl) |
1025 | 1027 | .header("User-Agent", Utils.getCustomUA()) |
app/src/main/java/com/dinhcv/lifelogpedometer/utils/SensorFusionMath.java
1 | +package com.dinhcv.lifelogpedometer.utils; | |
2 | + | |
3 | +/** | |
4 | + * Created by Administrator on 08/01/2018. | |
5 | + */ | |
6 | + | |
7 | +public class SensorFusionMath { | |
8 | + | |
9 | + private SensorFusionMath() { | |
10 | + } | |
11 | + | |
12 | + public static float sum(float[] array) { | |
13 | + float retval = 0; | |
14 | + for (int i = 0; i < array.length; i++) { | |
15 | + retval += array[i]; | |
16 | + } | |
17 | + return retval; | |
18 | + } | |
19 | + | |
20 | + public static float[] cross(float[] arrayA, float[] arrayB) { | |
21 | + float[] retArray = new float[3]; | |
22 | + retArray[0] = arrayA[1] * arrayB[2] - arrayA[2] * arrayB[1]; | |
23 | + retArray[1] = arrayA[2] * arrayB[0] - arrayA[0] * arrayB[2]; | |
24 | + retArray[2] = arrayA[0] * arrayB[1] - arrayA[1] * arrayB[0]; | |
25 | + return retArray; | |
26 | + } | |
27 | + | |
28 | + public static float norm(float[] array) { | |
29 | + float retval = 0; | |
30 | + for (int i = 0; i < array.length; i++) { | |
31 | + retval += array[i] * array[i]; | |
32 | + } | |
33 | + return (float) Math.sqrt(retval); | |
34 | + } | |
35 | + | |
36 | + // Note: only works with 3D vectors. | |
37 | + public static float dot(float[] a, float[] b) { | |
38 | + float retval = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; | |
39 | + return retval; | |
40 | + } | |
41 | + | |
42 | + public static float[] normalize(float[] a) { | |
43 | + float[] retval = new float[a.length]; | |
44 | + float norm = norm(a); | |
45 | + for (int i = 0; i < a.length; i++) { | |
46 | + retval[i] = a[i] / norm; | |
47 | + } | |
48 | + return retval; | |
49 | + } | |
50 | + | |
51 | +} |
app/src/main/java/com/dinhcv/lifelogpedometer/utils/SimpleStepDetector.java
1 | +package com.dinhcv.lifelogpedometer.utils; | |
2 | + | |
3 | +import com.dinhcv.lifelogpedometer.interfaces.StepListener; | |
4 | + | |
5 | +/** | |
6 | + * Created by Administrator on 08/01/2018. | |
7 | + */ | |
8 | + | |
9 | +public class SimpleStepDetector { | |
10 | + private static final int ACCEL_RING_SIZE = 50; | |
11 | + private static final int VEL_RING_SIZE = 10; | |
12 | + private static final float STEP_THRESHOLD = 4f; | |
13 | + private static final int STEP_DELAY_NS = 250000000; | |
14 | + | |
15 | + private int accelRingCounter = 0; | |
16 | + private float[] accelRingX = new float[ACCEL_RING_SIZE]; | |
17 | + private float[] accelRingY = new float[ACCEL_RING_SIZE]; | |
18 | + private float[] accelRingZ = new float[ACCEL_RING_SIZE]; | |
19 | + private int velRingCounter = 0; | |
20 | + private float[] velRing = new float[VEL_RING_SIZE]; | |
21 | + private long lastStepTimeNs = 0; | |
22 | + private float oldVelocityEstimate = 0; | |
23 | + | |
24 | + private StepListener listener; | |
25 | + | |
26 | + public void registerListener(StepListener listener) { | |
27 | + this.listener = listener; | |
28 | + } | |
29 | + | |
30 | + /** | |
31 | + * Accepts updates from the accelerometer. | |
32 | + */ | |
33 | + public void updateAccel(long timeNs, float x, float y, float z) { | |
34 | + float[] currentAccel = new float[3]; | |
35 | + currentAccel[0] = x; | |
36 | + currentAccel[1] = y; | |
37 | + currentAccel[2] = z; | |
38 | + | |
39 | + // First step is to update our guess of where the global z vector is. | |
40 | + accelRingCounter++; | |
41 | + accelRingX[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[0]; | |
42 | + accelRingY[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[1]; | |
43 | + accelRingZ[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[2]; | |
44 | + | |
45 | + float[] worldZ = new float[3]; | |
46 | + worldZ[0] = SensorFusionMath.sum(accelRingX) / Math.min(accelRingCounter, ACCEL_RING_SIZE); | |
47 | + worldZ[1] = SensorFusionMath.sum(accelRingY) / Math.min(accelRingCounter, ACCEL_RING_SIZE); | |
48 | + worldZ[2] = SensorFusionMath.sum(accelRingZ) / Math.min(accelRingCounter, ACCEL_RING_SIZE); | |
49 | + | |
50 | + float normalization_factor = SensorFusionMath.norm(worldZ); | |
51 | + | |
52 | + worldZ[0] = worldZ[0] / normalization_factor; | |
53 | + worldZ[1] = worldZ[1] / normalization_factor; | |
54 | + worldZ[2] = worldZ[2] / normalization_factor; | |
55 | + | |
56 | + // Next step is to figure out the component of the current acceleration | |
57 | + // in the direction of world_z and subtract gravity's contribution | |
58 | + float currentZ = SensorFusionMath.dot(worldZ, currentAccel) - normalization_factor; | |
59 | + velRingCounter++; | |
60 | + velRing[velRingCounter % VEL_RING_SIZE] = currentZ; | |
61 | + | |
62 | + float velocityEstimate = SensorFusionMath.sum(velRing); | |
63 | + | |
64 | + if (velocityEstimate > STEP_THRESHOLD && oldVelocityEstimate <= STEP_THRESHOLD | |
65 | + && (timeNs - lastStepTimeNs > STEP_DELAY_NS)) { | |
66 | + listener.step(timeNs); | |
67 | + lastStepTimeNs = timeNs; | |
68 | + } | |
69 | + oldVelocityEstimate = velocityEstimate; | |
70 | + } | |
71 | +} |