From 04789f841b69c86df8a8aef2411b5cc3cb4ad644 Mon Sep 17 00:00:00 2001 From: Pavel Elagin Date: Thu, 6 Sep 2018 16:45:31 +0300 Subject: [PATCH 01/65] Group language settings. --- app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/preferences.xml | 116 +++++++++++++------------ 3 files changed, 61 insertions(+), 57 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 7164990b6..dd0d67f5d 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -628,4 +628,5 @@ Частота УКВ Недопустимая частота Выберите, пожалуйста, частоту в интервале 87.5—108 + Язык и региональные настройки diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d67d8feb6..63db94ef8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -660,4 +660,5 @@ FM Frequency Invalid frequency Please enter a frequency between 87.5 and 108.0 + Language and region settings diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 934195805..5ae7e772d 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -30,20 +30,55 @@ android:entryValues="@array/pref_theme_values" android:defaultValue="@string/pref_theme_value_light" android:summary="%s" /> - - + + + + + + + + + + + + + - - - - - - - - + android:layout="@layout/preference_checkbox" + android:summary="@string/pref_summary_pebble_gatt_clientonly" + android:title="@string/pref_title_pebble_gatt_clientonly" /> Date: Thu, 6 Sep 2018 18:21:21 +0200 Subject: [PATCH 02/65] Attempt to fix connection problems on Samsung devices --- .../gadgetbridge/service/btle/BtLEQueue.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java index 1f2cb4d34..8ca171816 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java @@ -26,6 +26,8 @@ import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.content.Context; +import android.os.Handler; +import android.os.Looper; import android.support.annotation.Nullable; import org.slf4j.Logger; @@ -38,6 +40,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.Logging; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; @@ -177,7 +180,11 @@ public final class BtLEQueue { BluetoothDevice remoteDevice = mBluetoothAdapter.getRemoteDevice(mGbDevice.getAddress()); synchronized (mGattMonitor) { // connectGatt with true doesn't really work ;( too often connection problems - mBluetoothGatt = remoteDevice.connectGatt(mContext, false, internalGattCallback); + if (GBApplication.isRunningMarshmallowOrLater()) { + mBluetoothGatt = remoteDevice.connectGatt(mContext, false, internalGattCallback, BluetoothDevice.TRANSPORT_LE); + } else { + mBluetoothGatt = remoteDevice.connectGatt(mContext, false, internalGattCallback); + } } boolean result = mBluetoothGatt != null; if (result) { @@ -371,8 +378,16 @@ public final class BtLEQueue { LOG.info("Using cached services, skipping discovery"); onServicesDiscovered(gatt, BluetoothGatt.GATT_SUCCESS); } else { - LOG.info("Attempting to start service discovery:" + - gatt.discoverServices()); + LOG.info("Attempting to start service discovery"); + // discover services in the main thread (appears to fix Samsung connection problems) + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + if (mBluetoothGatt != null) { + mBluetoothGatt.discoverServices(); + } + } + }); } break; case BluetoothProfile.STATE_DISCONNECTED: From 49948967f59f07666dee6d74333e7f2d580072cd Mon Sep 17 00:00:00 2001 From: Ranved Sticon Date: Sun, 2 Sep 2018 16:15:36 +0000 Subject: [PATCH 03/65] Added translation using Weblate (Croatian) --- app/src/main/res/values-hr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/src/main/res/values-hr/strings.xml diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml new file mode 100644 index 000000000..a6b3daec9 --- /dev/null +++ b/app/src/main/res/values-hr/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From ba6fa314b651e78853db1b09c5e3171a21e84434 Mon Sep 17 00:00:00 2001 From: Ranved Sticon Date: Sun, 2 Sep 2018 16:17:01 +0000 Subject: [PATCH 04/65] Translated using Weblate (Croatian) Currently translated at 1.2% (7 of 559 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/hr/ --- app/src/main/res/values-hr/strings.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index a6b3daec9..303d7f110 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -1,2 +1,10 @@ - - \ No newline at end of file + +Gadgetbridge + + Amazfit Bip Postavke + Amazfit Cor Postavkes + Muško + Žensko + Ostalo + Lijevo + From 1d3ecc847fe458bfb1fee2c55a7a89419f6301ef Mon Sep 17 00:00:00 2001 From: postsorino Date: Sun, 2 Sep 2018 14:28:44 +0000 Subject: [PATCH 05/65] Translated using Weblate (Greek) Currently translated at 100.0% (559 of 559 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/el/ --- app/src/main/res/values-el/strings.xml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 6c89a7a02..741a297ee 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -663,4 +663,24 @@ "Κοιμηθήκατε %1$s έως %2$s" Δεν κοιμηθήκατε Νορβηγικά (Bokmål) - + Αλλαγή χρώματος LED ειδοποιήσεων + Αλλαγή συχνότητας FM + Λειτουργία \"νύχτας\" + Μείωση φωτεινότητας της οθόνης του Mi band 3 κατά τη διάρκεια της νύχτας + + Οκ + + Στη δύση του ηλίου + "Roidmi " + Roidmi3 + + Αποστολή αρχείου καταγραφής + Παρακαλώ έχετε υπ\'όψιν σας ότι τα αρχεία καταγραφής του Gedgetbridge ενδέχεται να περιέχουν προσωπικά δεδομένα συμπεριλαμβανομένων δεδομένα υγείας, μοναδικά χαρακτηριστικά (όπως διευθύνσεις MAC), μουσικές επιλογές κλπ. προσπαθήστε να επεξεργαστείτε το αρχείο καταγραφής και να αφαιρέσετε αυτές τις πληροφορίες πριν το στείλετε για την αναφορά προβλήματος. + Προσοχή! + + Χρώμα LED + + Συχνότητα FM + Μη έγκυρη συχνότητα + Παρακαλώ εισάγετε συχνότητα από 87.5 έως 108.0 + From 41be5218d7c02f1c1c8e1ef32b191d9ef17fdc40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Aslan?= Date: Sun, 2 Sep 2018 21:17:56 +0000 Subject: [PATCH 06/65] Translated using Weblate (Turkish) Currently translated at 23.9% (134 of 559 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/tr/ --- app/src/main/res/values-tr/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 115a2fcdb..7dfd241e3 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -203,4 +203,6 @@ Enlem Boylam Konumumu güncel tut + "Türkçe " + Change FM Frequency From 370369fae5b32559934931f4a416076dbc58d0f9 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Tue, 4 Sep 2018 20:56:28 +0000 Subject: [PATCH 07/65] Translated using Weblate (Hebrew) Currently translated at 100.0% (564 of 564 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index ff92bbbad..cb838a6cb 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -626,4 +626,10 @@ תדר FM תדר שגוי נא לבחור בתדר בין 87.5 לבין 108.0 - +הסוללה של %1$s חלשה + הסוללה של %1$s חלשה: %2$s + הגדרות תרשימים + דופק מרבי + דופק מזערי + + From 2b70acd60eddd93618d965d019300f432403ec4b Mon Sep 17 00:00:00 2001 From: mesnevi Date: Wed, 5 Sep 2018 05:03:54 +0000 Subject: [PATCH 08/65] Translated using Weblate (Russian) Currently translated at 100.0% (564 of 564 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index dd0d67f5d..24b8aec5a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -629,4 +629,10 @@ Недопустимая частота Выберите, пожалуйста, частоту в интервале 87.5—108 Язык и региональные настройки + Аккумулятор %1$s почти разряжен + Аккумулятор %1$s почти разряжен: %2$s + Настройки статистики активности + Максимальный пульс + Минимальный пульс + From 1fc3e82b066a904652b07101f6cd08355fce4298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A8=D7=95=D7=A2=D7=99=20=D7=92=D7=A8=D7=99=D7=A0=D7=91?= =?UTF-8?q?=D7=A8=D7=92?= Date: Wed, 5 Sep 2018 21:38:58 +0000 Subject: [PATCH 09/65] Translated using Weblate (Hebrew) Currently translated at 99.1% (566 of 571 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index cb838a6cb..82a950063 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -632,4 +632,12 @@ דופק מרבי דופק מזערי + כתיבה מימין לשמאל + הפעל אפשרות זו אם להתקן אין תמיכה בשפות הנכתבות מימין לשמאל + גודל שורה מקסימלי מימין-לשמאל + כאשר התמיכה בכתיבה מימין לשמאל מופעלת, הטקסט מופרד לשורות. שנה ערך זה אם השורות קצרות/ארוכות מדי. + + ערבית מחוברת + הפעל אפשרות זו על מנת לתמוך בערבית מחוברת + תמיכה בכתיבה מימין לשמאל From bf80474b71fb1b63ebc8589760c2656c128059fb Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Thu, 6 Sep 2018 07:41:41 +0000 Subject: [PATCH 10/65] Translated using Weblate (Hebrew) Currently translated at 100.0% (571 of 571 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 82a950063..67a6f39e7 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -632,12 +632,12 @@ דופק מרבי דופק מזערי - כתיבה מימין לשמאל + מימין לשמאל הפעל אפשרות זו אם להתקן אין תמיכה בשפות הנכתבות מימין לשמאל - גודל שורה מקסימלי מימין-לשמאל + גודל שורה מרבי מימין לשמאל כאשר התמיכה בכתיבה מימין לשמאל מופעלת, הטקסט מופרד לשורות. שנה ערך זה אם השורות קצרות/ארוכות מדי. ערבית מחוברת - הפעל אפשרות זו על מנת לתמוך בערבית מחוברת - תמיכה בכתיבה מימין לשמאל + יש להפעיל אפשרות זו כדי לתמוך בערבית מחוברת + תמיכה בטקסט מימין לשמאל From 4592d35cc672e6b157676aa78285c40cce3f665f Mon Sep 17 00:00:00 2001 From: Pavel Elagin Date: Thu, 6 Sep 2018 16:07:48 +0300 Subject: [PATCH 11/65] Calculation and display of weekly balance by steps and time of sleep. --- .../charts/AbstractWeekChartFragment.java | 18 +++++++++---- .../charts/WeekSleepChartFragment.java | 25 ++++++++++++++++++- .../charts/WeekStepsChartFragment.java | 15 +++++++++++ .../layout-land/fragment_weeksteps_chart.xml | 24 ++++++++++++------ .../res/layout/fragment_weeksteps_chart.xml | 8 ++++-- app/src/main/res/values-ru/strings.xml | 5 ++++ app/src/main/res/values/strings.xml | 5 ++++ 7 files changed, 85 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java index 4fb76c56e..1fc3dce75 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.TextView; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.PieChart; @@ -56,12 +57,15 @@ import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue; public abstract class AbstractWeekChartFragment extends AbstractChartFragment { protected static final Logger LOG = LoggerFactory.getLogger(AbstractWeekChartFragment.class); + protected final int TOTAL_DAYS = 7; private Locale mLocale; - private int mTargetValue = 0; + protected int mTargetValue = 0; + protected long mBalance = 0; private PieChart mTodayPieChart; private BarChart mWeekChart; + private TextView mBalanceView; private int mOffsetHours = getOffsetHours(); @@ -93,15 +97,16 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { protected void renderCharts() { mWeekChart.invalidate(); mTodayPieChart.invalidate(); + mBalanceView.setText(getBalance()); } private DefaultChartsData refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) { day = (Calendar) day.clone(); // do not modify the caller's argument - day.add(Calendar.DATE, -7); + day.add(Calendar.DATE, -TOTAL_DAYS); List entries = new ArrayList<>(); ArrayList labels = new ArrayList(); - for (int counter = 0; counter < 7; counter++) { + for (int counter = 0; counter < TOTAL_DAYS; counter++) { ActivityAmounts amounts = getActivityAmountsForDay(db, day, device); entries.add(new BarEntry(counter, getTotalsForActivityAmounts(amounts))); @@ -177,8 +182,9 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { mTargetValue = goal; } - mTodayPieChart = (PieChart) rootView.findViewById(R.id.todaystepschart); - mWeekChart = (BarChart) rootView.findViewById(R.id.weekstepschart); + mTodayPieChart = rootView.findViewById(R.id.todaystepschart); + mWeekChart = rootView.findViewById(R.id.weekstepschart); + mBalanceView = rootView.findViewById(R.id.balance); setupWeekChart(); setupTodayPieChart(); @@ -324,4 +330,6 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { abstract int[] getColors(); abstract String getPieDescription(int targetValue); + + abstract String getBalance(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java index a3c44c250..b30952dc4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java @@ -58,6 +58,20 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return -12; } + @Override + String getBalance() { + final long balance = this.mBalance; + this.mBalance = 0; + if (balance > 0) { + final long totalBalance = balance - (mTargetValue * TOTAL_DAYS); + if (totalBalance > 0) + return getString(R.string.overslept, getHM((int) totalBalance)); + else + return getString(R.string.lack_of_sleep, getHM((int) Math.abs(totalBalance))); + } else + return getString(R.string.no_data); + } + @Override float[] getTotalsForActivityAmounts(ActivityAmounts activityAmounts) { long totalSecondsDeepSleep = 0; @@ -69,7 +83,10 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { totalSecondsLightSleep += amount.getTotalSeconds(); } } - return new float[]{(int) (totalSecondsDeepSleep / 60), (int) (totalSecondsLightSleep / 60)}; + int totalMinutesDeepSleep = (int) (totalSecondsDeepSleep / 60); + int totalMinutesLightSleep = (int) (totalSecondsLightSleep / 60); + mBalance = mBalance + totalMinutesDeepSleep + totalMinutesLightSleep; + return new float[]{totalMinutesDeepSleep, totalMinutesLightSleep}; } @Override @@ -136,4 +153,10 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { chart.getLegend().setWordWrapEnabled(true); chart.getLegend().setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); } + + private String getHM(int value) { + int hours = value / 60; + int minutes = value % 60; + return String.format("%d:%02d", hours, minutes); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java index 32be63c45..905e31f50 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java @@ -54,6 +54,7 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { for (ActivityAmount amount : activityAmounts.getAmounts()) { totalSteps += amount.getTotalSteps(); amount.getTotalSteps(); + mBalance = mBalance + totalSteps; } return new float[]{totalSteps}; } @@ -93,4 +94,18 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { // no legend here, it is all about the steps here chart.getLegend().setEnabled(false); } + + @Override + String getBalance() { + final long balance = this.mBalance; + this.mBalance = 0; + if (balance > 0) { + final long totalBalance = balance - (mTargetValue * TOTAL_DAYS); + if (totalBalance > 0) + return getString(R.string.overstep, (int) Math.abs(totalBalance)); + else + return getString(R.string.lack_of_step, (int) Math.abs(totalBalance)); + } else + return getString(R.string.no_data); + } } diff --git a/app/src/main/res/layout-land/fragment_weeksteps_chart.xml b/app/src/main/res/layout-land/fragment_weeksteps_chart.xml index ddd9355df..246a55b69 100644 --- a/app/src/main/res/layout-land/fragment_weeksteps_chart.xml +++ b/app/src/main/res/layout-land/fragment_weeksteps_chart.xml @@ -4,18 +4,28 @@ tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment" android:orientation="horizontal"> - - + + + + + + diff --git a/app/src/main/res/layout/fragment_weeksteps_chart.xml b/app/src/main/res/layout/fragment_weeksteps_chart.xml index 260b249cd..b51b1428a 100644 --- a/app/src/main/res/layout/fragment_weeksteps_chart.xml +++ b/app/src/main/res/layout/fragment_weeksteps_chart.xml @@ -5,17 +5,21 @@ tools:context="nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity$PlaceholderFragment" android:orientation="vertical"> + + + android:layout_weight="20" /> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 24b8aec5a..9d4b628fb 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -253,6 +253,8 @@ Сон сегодня, цель: %1$s Шагов в неделю Ваши активность и сон + Недосып: %1$s + Пересып: %1$s Обновление прошивки… Файл не может быть установлен, устройство не готово. %1$s: %2$s %3$s @@ -273,6 +275,8 @@ Расстояние Жизненная активность Шагов сегодня, цель: %1$s + Недопройдено %1$d шагов. + Пройдено на %1$d шагов больше. Не подтверждать передачу данных об активности Если данные об активности не будут переданы на устройство, оно не будет очищено. Полезно, если GB используется с другими приложениями. Хранить данные о деятельности на Mi Band, даже после синхронизации. Полезно, если Mi Band используется совместно с другими приложениями. @@ -600,6 +604,7 @@ Поделиться лог-файлом Файлы журнала Gadgetbridge могут содержать личную информацию, например уникальные идентификаторы: (устройство, MAC-адрес), предпочтения в музыке и т.д. Рассмотрите возможность редактирования файла и удаления этой информации перед отправкой файла общедоступное место. Внимание! + Нет данных Минимальный интервал между уведомлениями Без ограничений diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 63db94ef8..d4e5f6135 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -356,6 +356,8 @@ Sleep today, target: %1$s Steps per week Your activity and sleep + Lack of sleep: %1$s + Overslept: %1$s Flashing firmware… File cannot be installed, device not ready. %1$s: %2$s %3$s @@ -390,6 +392,8 @@ Live activity Steps today, target: %1$s + Lack of step: %1$d + Overstep: %1$d Do not ACK activity data transfer If the activity data are not acked to the band, they will not be cleared. Useful if GB is used together with other apps. Will keep activity data on the Mi Band even after synchronization. Useful if GB is used together with other apps. @@ -652,6 +656,7 @@ Share log Please keep in mind Gadgetbridge log files may contain lots of personal information, including but not limited to health data, unique identifiers (such as a device MAC address), music preferences, etc. Consider editing the file and removing this information before sending the file to a public issue report. Warning! + No data LED Color From 88ad6cf0e0eaf2225e913063060790a5ca2a83a4 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 10 Sep 2018 23:38:49 +0200 Subject: [PATCH 12/65] Improve balance handling --- .../charts/AbstractWeekChartFragment.java | 39 ++++++++++++++----- .../charts/WeekSleepChartFragment.java | 24 ++++++++---- .../charts/WeekStepsChartFragment.java | 17 +++++--- app/src/main/res/values/strings.xml | 2 +- 4 files changed, 57 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java index 1fc3dce75..c6b07dee4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java @@ -33,6 +33,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -60,8 +61,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { protected final int TOTAL_DAYS = 7; private Locale mLocale; - protected int mTargetValue = 0; - protected long mBalance = 0; + private int mTargetValue = 0; private PieChart mTodayPieChart; private BarChart mWeekChart; @@ -75,7 +75,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { day.setTime(chartsHost.getEndDate()); //NB: we could have omitted the day, but this way we can move things to the past easily DayData dayData = refreshDayPie(db, day, device); - DefaultChartsData weekBeforeData = refreshWeekBeforeData(db, mWeekChart, day, device); + WeekChartsData weekBeforeData = refreshWeekBeforeData(db, mWeekChart, day, device); return new MyChartsData(dayData, weekBeforeData); } @@ -91,24 +91,28 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { mWeekChart.setData(null); // workaround for https://github.com/PhilJay/MPAndroidChart/issues/2317 mWeekChart.setData(mcd.getWeekBeforeData().getData()); mWeekChart.getXAxis().setValueFormatter(mcd.getWeekBeforeData().getXValueFormatter()); + + mBalanceView.setText(mcd.getWeekBeforeData().getBalanceMessage()); } @Override protected void renderCharts() { mWeekChart.invalidate(); mTodayPieChart.invalidate(); - mBalanceView.setText(getBalance()); +// mBalanceView.setText(getBalanceMessage(balance)); } - private DefaultChartsData refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) { + private WeekChartsData refreshWeekBeforeData(DBHandler db, BarChart barChart, Calendar day, GBDevice device) { day = (Calendar) day.clone(); // do not modify the caller's argument day.add(Calendar.DATE, -TOTAL_DAYS); List entries = new ArrayList<>(); ArrayList labels = new ArrayList(); + int balance = 0; for (int counter = 0; counter < TOTAL_DAYS; counter++) { ActivityAmounts amounts = getActivityAmountsForDay(db, day, device); + balance += calculateBalance(amounts); entries.add(new BarEntry(counter, getTotalsForActivityAmounts(amounts))); labels.add(day.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, mLocale)); day.add(Calendar.DATE, 1); @@ -126,7 +130,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { barChart.getAxisLeft().removeAllLimitLines(); barChart.getAxisLeft().addLimitLine(target); - return new DefaultChartsData(barData, new PreformattedXIndexLabelFormatter(labels)); + return new WeekChartsData(barData, new PreformattedXIndexLabelFormatter(labels), getBalanceMessage(balance, mTargetValue)); } private DayData refreshDayPie(DBHandler db, Calendar day, GBDevice device) { @@ -271,10 +275,10 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { } private static class MyChartsData extends ChartsData { - private final DefaultChartsData weekBeforeData; + private final WeekChartsData weekBeforeData; private final DayData dayData; - MyChartsData(DayData dayData, DefaultChartsData weekBeforeData) { + MyChartsData(DayData dayData, WeekChartsData weekBeforeData) { this.dayData = dayData; this.weekBeforeData = weekBeforeData; } @@ -283,7 +287,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { return dayData; } - DefaultChartsData getWeekBeforeData() { + WeekChartsData getWeekBeforeData() { return weekBeforeData; } } @@ -331,5 +335,20 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { abstract String getPieDescription(int targetValue); - abstract String getBalance(); + protected abstract int calculateBalance(ActivityAmounts amounts); + + protected abstract String getBalanceMessage(int balance, int targetValue); + + private class WeekChartsData> extends DefaultChartsData { + private final String balanceMessage; + + public WeekChartsData(T data, PreformattedXIndexLabelFormatter xIndexLabelFormatter, String balanceMessage) { + super(data, xIndexLabelFormatter); + this.balanceMessage = balanceMessage; + } + + public String getBalanceMessage() { + return balanceMessage; + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java index b30952dc4..1d82cd5c8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java @@ -58,12 +58,23 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return -12; } + @Override - String getBalance() { - final long balance = this.mBalance; - this.mBalance = 0; + protected int calculateBalance(ActivityAmounts activityAmounts) { + long balance = 0; + + for (ActivityAmount amount : activityAmounts.getAmounts()) { + if (amount.getActivityKind() == ActivityKind.TYPE_DEEP_SLEEP || amount.getActivityKind() == ActivityKind.TYPE_LIGHT_SLEEP) { + balance += amount.getTotalSeconds(); + } + } + return (int) (balance / 60); + } + + @Override + protected String getBalanceMessage(int balance, int targetValue) { if (balance > 0) { - final long totalBalance = balance - (mTargetValue * TOTAL_DAYS); + final long totalBalance = balance - (targetValue * TOTAL_DAYS); if (totalBalance > 0) return getString(R.string.overslept, getHM((int) totalBalance)); else @@ -85,7 +96,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { } int totalMinutesDeepSleep = (int) (totalSecondsDeepSleep / 60); int totalMinutesLightSleep = (int) (totalSecondsLightSleep / 60); - mBalance = mBalance + totalMinutesDeepSleep + totalMinutesLightSleep; return new float[]{totalMinutesDeepSleep, totalMinutesLightSleep}; } @@ -155,8 +165,6 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { } private String getHM(int value) { - int hours = value / 60; - int minutes = value % 60; - return String.format("%d:%02d", hours, minutes); + return DateTimeUtils.formatDurationHoursMinutes(value, TimeUnit.MINUTES); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java index 905e31f50..df298ca24 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java @@ -53,12 +53,19 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { int totalSteps = 0; for (ActivityAmount amount : activityAmounts.getAmounts()) { totalSteps += amount.getTotalSteps(); - amount.getTotalSteps(); - mBalance = mBalance + totalSteps; } return new float[]{totalSteps}; } + @Override + protected int calculateBalance(ActivityAmounts activityAmounts) { + int balance = 0; + for (ActivityAmount amount : activityAmounts.getAmounts()) { + balance += amount.getTotalSteps(); + } + return balance; + } + @Override protected String formatPieValue(int value) { return String.valueOf(value); @@ -96,11 +103,9 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { } @Override - String getBalance() { - final long balance = this.mBalance; - this.mBalance = 0; + protected String getBalanceMessage(int balance, int targetValue) { if (balance > 0) { - final long totalBalance = balance - (mTargetValue * TOTAL_DAYS); + final long totalBalance = balance - (targetValue * TOTAL_DAYS); if (totalBalance > 0) return getString(R.string.overstep, (int) Math.abs(totalBalance)); else diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d4e5f6135..2e863afcc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -392,7 +392,7 @@ Live activity Steps today, target: %1$s - Lack of step: %1$d + Lack of steps: %1$d Overstep: %1$d Do not ACK activity data transfer If the activity data are not acked to the band, they will not be cleared. Useful if GB is used together with other apps. From 8b8202a96efa23ed07d9113546057177f01296a4 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Sun, 9 Sep 2018 08:24:15 +0000 Subject: [PATCH 13/65] Translated using Weblate (Hebrew) Currently translated at 100.0% (572 of 572 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 67a6f39e7..3329538b2 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -640,4 +640,5 @@ ערבית מחוברת יש להפעיל אפשרות זו כדי לתמוך בערבית מחוברת תמיכה בטקסט מימין לשמאל - + הגדרות שפה ואיזור + From 6644ad0bb0bb840b68c31b7f2b2bec0103493ade Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 11 Sep 2018 21:32:13 +0200 Subject: [PATCH 14/65] Mi Band 3: Allow enabling the "Workout" menu item (This is called "Activity" in Gadgetbridge, since we have that on the Bip, we should probably rename that to Workout also for consistency with the menus) --- .../service/devices/huami/miband3/MiBand3Support.java | 4 ++++ app/src/main/res/values/arrays.xml | 3 +++ 2 files changed, 7 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3Support.java index 70192943f..fdde8db14 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3Support.java @@ -63,6 +63,10 @@ public class MiBand3Support extends AmazfitBipSupport { command[1] |= 0x04; command[5] = pos++; } + if (pages.contains("activity")) { + command[1] |= 0x08; + command[6] = pos++; + } if (pages.contains("more")) { command[1] |= 0x10; command[7] = pos++; diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index c31318900..b73d378cd 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -210,6 +210,7 @@ @string/menuitem_notifications @string/menuitem_weather + @string/menuitem_activity @string/menuitem_more @string/menuitem_status @string/heart_rate @@ -218,6 +219,7 @@ @string/p_menuitem_notifications @string/p_menuitem_weather + @string/p_menuitem_activity @string/p_menuitem_more @string/p_menuitem_status @string/p_heart_rate @@ -226,6 +228,7 @@ @string/p_menuitem_notifications @string/p_menuitem_weather + @string/p_menuitem_activity @string/p_menuitem_more @string/p_menuitem_status @string/p_heart_rate From 59ddedcf9a15e686d660303508f9480fa6511a14 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 11 Sep 2018 21:35:30 +0200 Subject: [PATCH 15/65] Mi Band 3: Whitelist FW 1.6.0.16 --- .../service/devices/huami/miband3/MiBand3FirmwareInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java index a821a74f7..995cebb2d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband3/MiBand3FirmwareInfo.java @@ -50,12 +50,13 @@ public class MiBand3FirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(30045, "1.5.0.2"); crcToVersion.put(38254, "1.5.0.7"); crcToVersion.put(46985, "1.5.0.11"); + crcToVersion.put(31330, "1.6.0.16"); // resources crcToVersion.put(54724, "1.2.0.8"); crcToVersion.put(52589, "1.3.0.4"); crcToVersion.put(34642, "1.3.0.8"); - crcToVersion.put(25278, "1.4.0.12-1.5.0.11"); + crcToVersion.put(25278, "1.4.0.12-1.6.0.16"); // font crcToVersion.put(19775, "1"); From fbcd2840ca125770e5518cebb2cce0f35d85be59 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Tue, 11 Sep 2018 23:04:18 +0200 Subject: [PATCH 16/65] No need to call method twice --- .../gadgetbridge/activities/charts/ActivityAnalysis.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityAnalysis.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityAnalysis.java index f9e3e654c..a3e199c75 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityAnalysis.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/ActivityAnalysis.java @@ -121,7 +121,7 @@ class ActivityAnalysis { for (ActivitySample sample : samples) { int steps = sample.getSteps(); if (steps > 0) { - totalSteps += sample.getSteps(); + totalSteps += steps; } } return totalSteps; From aee0e54d0505fe58ba4467b9e94ca50786be622d Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Tue, 11 Sep 2018 23:08:29 +0200 Subject: [PATCH 17/65] Handle possible negative steps values --- .../gadgetbridge/activities/charts/LiveActivityFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index 2331a5a22..00a6e6bb4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -172,7 +172,7 @@ public class LiveActivityFragment extends AbstractChartFragment { setCurrentHeartRate(heartRate, timestamp); } int steps = sample.getSteps(); - if (steps != ActivitySample.NOT_MEASURED) { + if (steps > 0) { addEntries(steps, timestamp); } } From add9be5ff6e8841bf361117120399f0fed1717ce Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Tue, 11 Sep 2018 23:24:27 +0200 Subject: [PATCH 18/65] Another place to handle possible negative steps values --- .../service/devices/miband/RealtimeSamplesSupport.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/RealtimeSamplesSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/RealtimeSamplesSupport.java index dd88b69de..09a1257e5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/RealtimeSamplesSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/RealtimeSamplesSupport.java @@ -74,7 +74,11 @@ public abstract class RealtimeSamplesSupport { } public synchronized void setSteps(int stepsPerMinute) { - this.steps = stepsPerMinute; + if (stepsPerMinute == ActivitySample.NOT_MEASURED || stepsPerMinute >= 0) { + this.steps = stepsPerMinute; + } else { + this.steps = ActivitySample.NOT_MEASURED; + } } /** From b6d68207cb2badacbf6ac1f05a248637ed26a9da Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Tue, 11 Sep 2018 23:26:51 +0200 Subject: [PATCH 19/65] Don't store the live step values in the db --- .../gadgetbridge/service/devices/huami/HuamiSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index 757e5996e..d3d305ea3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -1343,7 +1343,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { MiBand2SampleProvider provider = new MiBand2SampleProvider(gbDevice, session); MiBandActivitySample sample = createActivitySample(device, user, ts, provider); sample.setHeartRate(getHeartrateBpm()); - sample.setSteps(getSteps()); +// sample.setSteps(getSteps()); sample.setRawIntensity(ActivitySample.NOT_MEASURED); sample.setRawKind(HuamiConst.TYPE_ACTIVITY); // to make it visible in the charts TODO: add a MANUAL kind for that? From e85257b545a0fa522c0bb524bb089886edd443b1 Mon Sep 17 00:00:00 2001 From: Pavel Elagin Date: Thu, 13 Sep 2018 12:51:52 +0300 Subject: [PATCH 20/65] Show current / max heart rate. Ignore heart rate < user settings. Invisible button bar into LiveActivity. Auto scale totalStepsChart. Fix time x axis history chart. Draw total and per minute steps. Set limit on per minute chart by user settings. --- .../charts/AbstractChartFragment.java | 2 +- .../charts/LiveActivityFragment.java | 28 +++++++++++++------ .../res/layout/fragment_live_activity.xml | 4 +++ app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java index b1ae9cc48..d6db6f5ea 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java @@ -230,7 +230,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { } protected void showDateBar(boolean show) { - getChartsHost().getDateBar().setVisibility(show ? View.VISIBLE : View.INVISIBLE); + getChartsHost().getDateBar().setVisibility(show ? View.VISIBLE : View.GONE); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index 00a6e6bb4..6c66f3906 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -29,6 +29,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.widget.TextView; import android.widget.Toast; import com.github.mikephil.charting.charts.BarLineChartBase; @@ -60,6 +61,7 @@ import nodomain.freeyourgadget.gadgetbridge.activities.HeartRateUtils; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.model.Measurement; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -78,6 +80,7 @@ public class LiveActivityFragment extends AbstractChartFragment { private BarLineChartBase mStepsPerMinuteHistoryChart; private CustomBarChart mStepsPerMinuteCurrentChart; private CustomBarChart mTotalStepsChart; + private TextView mMaxHeartRateView; private final Steps mSteps = new Steps(); private ScheduledExecutorService pulseScheduler; @@ -85,6 +88,7 @@ public class LiveActivityFragment extends AbstractChartFragment { private List heartRateValues; private LineDataSet mHeartRateSet; private int mHeartRate; + private int mMaxHeartRate = 0; private TimestampTranslation tsTranslation; private class Steps { @@ -189,6 +193,10 @@ public class LiveActivityFragment extends AbstractChartFragment { private void setCurrentHeartRate(int heartRate, int timestamp) { addHistoryDataSet(true); mHeartRate = heartRate; + if (mMaxHeartRate < mHeartRate) { + mMaxHeartRate = mHeartRate; + } + mMaxHeartRateView.setText(getContext().getString(R.string.live_activity_max_heart_rate, heartRate, mMaxHeartRate)); } private int getCurrentHeartRate() { @@ -233,8 +241,8 @@ public class LiveActivityFragment extends AbstractChartFragment { } mHistorySet.addEntry(new Entry(timestamp, stepsPerMinute)); int hr = getCurrentHeartRate(); - if (hr < 0) { - hr = 0; + if (hr > HeartRateUtils.getInstance().getMinHeartRate()) { + mHeartRateSet.addEntry(new Entry(timestamp, hr)); } mHeartRateSet.addEntry(new Entry(timestamp, hr)); } @@ -272,8 +280,13 @@ public class LiveActivityFragment extends AbstractChartFragment { stepsPerMinuteEntry = new BarEntry(1, 0); mStepsPerMinuteData = setupCurrentChart(mStepsPerMinuteCurrentChart, stepsPerMinuteEntry, getString(R.string.live_activity_current_steps_per_minute)); + mStepsPerMinuteData.setDrawValues(true); + mStepsPerMinuteData.setValueTextColor(DESCRIPTION_COLOR); mTotalStepsData = setupTotalStepsChart(mTotalStepsChart, totalStepsEntry, getString(R.string.live_activity_total_steps)); + mTotalStepsData.setDrawValues(true); + mTotalStepsData.setValueTextColor(DESCRIPTION_COLOR); setupHistoryChart(mStepsPerMinuteHistoryChart); + mMaxHeartRateView = rootView.findViewById(R.id.livechart_max_heart_rate); LocalBroadcastManager.getInstance(getActivity()).registerReceiver(mReceiver, filterLocal); @@ -385,7 +398,7 @@ public class LiveActivityFragment extends AbstractChartFragment { } private BarDataSet setupCurrentChart(CustomBarChart chart, BarEntry entry, String title) { - mStepsPerMinuteCurrentChart.getAxisLeft().setAxisMaxValue(MAX_STEPS_PER_MINUTE); + mStepsPerMinuteCurrentChart.getAxisLeft().setAxisMaximum(MAX_STEPS_PER_MINUTE); return setupCommonChart(chart, entry, title); } @@ -408,9 +421,7 @@ public class LiveActivityFragment extends AbstractChartFragment { List entries = new ArrayList<>(); List colors = new ArrayList<>(); - entries.add(new BarEntry(0, 0)); entries.add(entry); - entries.add(new BarEntry(2, 0)); colors.add(akActivity.color); colors.add(akActivity.color); colors.add(akActivity.color); @@ -432,7 +443,9 @@ public class LiveActivityFragment extends AbstractChartFragment { } private BarDataSet setupTotalStepsChart(CustomBarChart chart, BarEntry entry, String label) { - mTotalStepsChart.getAxisLeft().setAxisMaximum(5000); // TODO: use daily goal - already reached steps + mTotalStepsChart.getAxisLeft().addLimitLine(new LimitLine(GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, 10000), "ss")); // TODO: use daily goal - already reached steps + mTotalStepsChart.getAxisLeft().setAxisMinimum(0); + mTotalStepsChart.setAutoScaleMinMaxEnabled(true); return setupCommonChart(chart, entry, label); // at the moment, these look the same } @@ -455,6 +468,7 @@ public class LiveActivityFragment extends AbstractChartFragment { x.setDrawGridLines(false); x.setEnabled(true); x.setTextColor(CHART_TEXT_COLOR); + x.setValueFormatter(new SampleXLabelFormatter(tsTranslation)); x.setDrawLimitLinesBehindData(true); YAxis y = chart.getAxisLeft(); @@ -470,8 +484,6 @@ public class LiveActivityFragment extends AbstractChartFragment { yAxisRight.setDrawLabels(true); yAxisRight.setDrawTopYLabelEntry(false); yAxisRight.setTextColor(CHART_TEXT_COLOR); - yAxisRight.setAxisMaximum(HeartRateUtils.getInstance().getMaxHeartRate()); - yAxisRight.setAxisMinimum(HeartRateUtils.getInstance().getMinHeartRate()); mHistorySet = new LineDataSet(new ArrayList(), getString(R.string.live_activity_steps_history)); mHistorySet.setAxisDependency(YAxis.AxisDependency.LEFT); diff --git a/app/src/main/res/layout/fragment_live_activity.xml b/app/src/main/res/layout/fragment_live_activity.xml index b2a460940..2aabfebcf 100644 --- a/app/src/main/res/layout/fragment_live_activity.xml +++ b/app/src/main/res/layout/fragment_live_activity.xml @@ -30,6 +30,10 @@ android:layout_weight="20"> --> + Всего шагов История шагов за минуту Начните вашу активность + Текущая / максимальная ЧСС: %1$d / %2$d Активность Быстрый сон Глубокий сон diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2e863afcc..7942f6cf4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -405,6 +405,7 @@ Total steps Steps per minute history Start your activity + Current / Max heart rate: %1$d / %2$d Activity Light sleep Deep sleep From 91529bbc05e8bc07230eabd5a8303b1ecf96f7b6 Mon Sep 17 00:00:00 2001 From: Xavier RENE-CORAIL Date: Fri, 14 Sep 2018 11:26:10 +0100 Subject: [PATCH 21/65] Add LGTM.com code quality badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ca18a09b2..feb582a0a 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ vendor's servers. [![Build](https://travis-ci.org/Freeyourgadget/Gadgetbridge.svg?branch=master)](https://travis-ci.org/Freeyourgadget/Gadgetbridge) +[![Code Quality: Java](https://img.shields.io/lgtm/grade/java/g/Freeyourgadget/Gadgetbridge.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Freeyourgadget/Gadgetbridge/context:java) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/Freeyourgadget/Gadgetbridge.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/Freeyourgadget/Gadgetbridge/alerts) ## Download From d6f5e36e12104fd489dd06702c12175fb9e5c893 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Fri, 14 Sep 2018 20:11:27 +0200 Subject: [PATCH 22/65] Huami devices: Fix seldom fetch failures (better support for app level ble feedback) Fixes #1264 --- .../service/btle/AbstractBTLEOperation.java | 10 +++++ .../gadgetbridge/service/btle/BtLEQueue.java | 5 +++ .../service/btle/GattListenerAction.java | 5 +++ .../service/btle/TransactionBuilder.java | 4 ++ .../AbstractGattListenerWriteAction.java | 33 +++++++++++++++ .../service/btle/actions/WaitAction.java | 5 +++ .../AmazfitBipFetchLogsOperation.java | 39 +++++++++++++++--- .../operations/FetchActivityOperation.java | 40 +++++++++++++++++-- .../huami/operations/InitOperation.java | 6 --- 9 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattListenerAction.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/AbstractGattListenerWriteAction.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java index 5dc29645f..c0c61756a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEOperation.java @@ -108,6 +108,16 @@ public abstract class AbstractBTLEOperation return builder; } + public TransactionBuilder createTransactionBuilder(String taskName) { + TransactionBuilder builder = getSupport().createTransactionBuilder(taskName); + builder.setGattCallback(this); + return builder; + } + + public void performImmediately(TransactionBuilder builder) throws IOException { + mSupport.performImmediately(builder); + } + protected Context getContext() { return mSupport.getContext(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java index 8ca171816..542e92fb8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java @@ -107,6 +107,11 @@ public final class BtLEQueue { if (LOG.isDebugEnabled()) { LOG.debug("About to run action: " + action); } + if (action instanceof GattListenerAction) { + // this special action overwrites the transaction gatt listener (if any), it must + // always be the last action in the transaction + internalGattCallback.setTransactionGattCallback(((GattListenerAction)action).getGattCallback()); + } if (action.run(mBluetoothGatt)) { // check again, maybe due to some condition, action did not need to write, so we can't wait boolean waitForResult = action.expectsResult(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattListenerAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattListenerAction.java new file mode 100644 index 000000000..733ca2795 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/GattListenerAction.java @@ -0,0 +1,5 @@ +package nodomain.freeyourgadget.gadgetbridge.service.btle; + +public interface GattListenerAction { + GattCallback getGattCallback(); +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java index cef217495..37dad0bb8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java @@ -110,4 +110,8 @@ public class TransactionBuilder { public Transaction getTransaction() { return mTransaction; } + + public String getTaskName() { + return mTransaction.getTaskName(); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/AbstractGattListenerWriteAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/AbstractGattListenerWriteAction.java new file mode 100644 index 000000000..18916f15e --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/AbstractGattListenerWriteAction.java @@ -0,0 +1,33 @@ +package nodomain.freeyourgadget.gadgetbridge.service.btle.actions; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; + +import java.util.Objects; + +import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractGattCallback; +import nodomain.freeyourgadget.gadgetbridge.service.btle.BtLEQueue; +import nodomain.freeyourgadget.gadgetbridge.service.btle.GattCallback; +import nodomain.freeyourgadget.gadgetbridge.service.btle.GattListenerAction; + +public abstract class AbstractGattListenerWriteAction extends WriteAction implements GattListenerAction { + private final BtLEQueue queue; + + public AbstractGattListenerWriteAction(BtLEQueue queue, BluetoothGattCharacteristic characteristic, byte[] value) { + super(characteristic, value); + this.queue = queue; + Objects.requireNonNull(queue, "queue must not be null"); + } + + @Override + public GattCallback getGattCallback() { + return new AbstractGattCallback() { + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + return AbstractGattListenerWriteAction.this.onCharacteristicChanged(gatt, characteristic); + } + }; + } + + protected abstract boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic); +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WaitAction.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WaitAction.java index edfe25158..841b0ac55 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WaitAction.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/actions/WaitAction.java @@ -18,6 +18,11 @@ package nodomain.freeyourgadget.gadgetbridge.service.btle.actions; import android.bluetooth.BluetoothGatt; +/** + * An action that will cause the queue to sleep for the specified time. + * Note that this is usually a bad idea, since it will not be able to process messages + * during that time. It is also likely to cause race conditions. + */ public class WaitAction extends PlainAction { private final int mMillis; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java index bbaeb2c85..cee4c9449 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java @@ -16,6 +16,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.operations; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; import android.support.annotation.NonNull; import android.widget.Toast; @@ -30,17 +32,21 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; +import java.util.UUID; import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.AbstractGattListenerWriteAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitbip.AmazfitBipSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.AbstractFetchOperation; +import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation { private static final Logger LOG = LoggerFactory.getLogger(AmazfitBipFetchLogsOperation.class); @@ -72,15 +78,38 @@ public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation { return; } + final String taskName = StringUtils.ensureNotNull(builder.getTaskName()); GregorianCalendar sinceWhen = BLETypeConversions.createCalendar(); sinceWhen.add(Calendar.DAY_OF_MONTH, -10); - builder.write(characteristicFetch, BLETypeConversions.join(new byte[]{ + byte[] fetchBytes = BLETypeConversions.join(new byte[]{ HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_DEBUGLOGS}, - getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES))); - builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply - builder.notify(characteristicActivityData, true); - builder.write(characteristicFetch, new byte[]{HuamiService.COMMAND_FETCH_DATA}); + getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)); + builder.add(new AbstractGattListenerWriteAction(getQueue(), characteristicFetch, fetchBytes) { + @Override + protected boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + UUID characteristicUUID = characteristic.getUuid(); + if (HuamiService.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { + byte[] value = characteristic.getValue(); + + if (ArrayUtils.equals(value, HuamiService.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { + handleActivityMetadata(value); + TransactionBuilder newBuilder = createTransactionBuilder(taskName + " Step 2"); + newBuilder.notify(characteristicActivityData, true); + newBuilder.write(characteristicFetch, new byte[]{HuamiService.COMMAND_FETCH_DATA}); + try { + performImmediately(newBuilder); + } catch (IOException ex) { + GB.toast(getContext(), "Error fetching debug logs: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); + } + return true; + } else { + handleActivityMetadata(value); + } + } + return false; + } + }); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java index 650bc2406..fe1f3951b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java @@ -16,6 +16,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations; +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; import android.text.format.DateUtils; import android.widget.Toast; @@ -24,9 +26,11 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; +import java.util.UUID; import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.GBApplication; @@ -34,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandSampleProvider; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; @@ -41,10 +46,14 @@ import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.AbstractGattListenerWriteAction; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.PlainAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.WaitAction; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport; +import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; /** * An operation that fetches activity data. For every fetch, a new operation must @@ -68,11 +77,34 @@ public class FetchActivityOperation extends AbstractFetchOperation { @Override protected void startFetching(TransactionBuilder builder) { + final String taskName = StringUtils.ensureNotNull(builder.getTaskName()); GregorianCalendar sinceWhen = getLastSuccessfulSyncTime(); - builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, HuamiService.COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES))); - builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply - builder.notify(characteristicActivityData, true); - builder.write(characteristicFetch, new byte[] { HuamiService.COMMAND_FETCH_DATA}); + byte[] fetchBytes = BLETypeConversions.join(new byte[] { HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, HuamiService.COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)); + builder.add(new AbstractGattListenerWriteAction(getQueue(), characteristicFetch, fetchBytes) { + @Override + protected boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + UUID characteristicUUID = characteristic.getUuid(); + if (HuamiService.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { + byte[] value = characteristic.getValue(); + + if (ArrayUtils.equals(value, HuamiService.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { + handleActivityMetadata(value); + TransactionBuilder newBuilder = createTransactionBuilder(taskName + " Step 2"); + newBuilder.notify(characteristicActivityData, true); + newBuilder.write(characteristicFetch, new byte[] { HuamiService.COMMAND_FETCH_DATA}); + try { + performImmediately(newBuilder); + } catch (IOException ex) { + GB.toast(getContext(), "Error fetching activity data: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); + } + return true; + } else { + handleActivityMetadata(value); + } + } + return false; + } + }); } protected void handleActivityFetchFinish(boolean success) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/InitOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/InitOperation.java index a7d64a135..06917ddb8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/InitOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/InitOperation.java @@ -137,12 +137,6 @@ public class InitOperation extends AbstractBTLEOperation { } } - private TransactionBuilder createTransactionBuilder(String task) { - TransactionBuilder builder = getSupport().createTransactionBuilder(task); - builder.setGattCallback(this); - return builder; - } - private byte[] getMD5(byte[] message) throws NoSuchAlgorithmException { MessageDigest md5 = MessageDigest.getInstance("MD5"); return md5.digest(message); From f9e600d36965174aa3f999efd128734da97cf560 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 15 Sep 2018 22:38:20 +0200 Subject: [PATCH 23/65] Deduplicate code --- .../AmazfitBipFetchLogsOperation.java | 31 +-------------- .../operations/AbstractFetchOperation.java | 38 +++++++++++++++++++ .../operations/FetchActivityOperation.java | 27 +------------ .../FetchSportsDetailsOperation.java | 9 +---- .../FetchSportsSummaryOperation.java | 8 +--- 5 files changed, 42 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java index cee4c9449..7b9efe988 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/operations/AmazfitBipFetchLogsOperation.java @@ -78,38 +78,9 @@ public class AmazfitBipFetchLogsOperation extends AbstractFetchOperation { return; } - final String taskName = StringUtils.ensureNotNull(builder.getTaskName()); GregorianCalendar sinceWhen = BLETypeConversions.createCalendar(); sinceWhen.add(Calendar.DAY_OF_MONTH, -10); - byte[] fetchBytes = BLETypeConversions.join(new byte[]{ - HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, - AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_DEBUGLOGS}, - getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)); - builder.add(new AbstractGattListenerWriteAction(getQueue(), characteristicFetch, fetchBytes) { - @Override - protected boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - UUID characteristicUUID = characteristic.getUuid(); - if (HuamiService.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { - byte[] value = characteristic.getValue(); - - if (ArrayUtils.equals(value, HuamiService.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { - handleActivityMetadata(value); - TransactionBuilder newBuilder = createTransactionBuilder(taskName + " Step 2"); - newBuilder.notify(characteristicActivityData, true); - newBuilder.write(characteristicFetch, new byte[]{HuamiService.COMMAND_FETCH_DATA}); - try { - performImmediately(newBuilder); - } catch (IOException ex) { - GB.toast(getContext(), "Error fetching debug logs: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); - } - return true; - } else { - handleActivityMetadata(value); - } - } - return false; - } - }); + startFetching(builder, AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_DEBUGLOGS, sinceWhen); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/AbstractFetchOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/AbstractFetchOperation.java index ab3bab6b8..8d0abdd3d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/AbstractFetchOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/AbstractFetchOperation.java @@ -22,6 +22,7 @@ import android.bluetooth.BluetoothGattCharacteristic; import android.content.SharedPreferences; import android.support.annotation.CallSuper; import android.support.annotation.NonNull; +import android.widget.Toast; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,18 +33,22 @@ import java.util.Arrays; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.UUID; +import java.util.concurrent.TimeUnit; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.Logging; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.AbstractGattListenerWriteAction; import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.AbstractHuamiOperation; import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; /** * An operation that fetches activity data. For every fetch, a new operation must @@ -137,6 +142,39 @@ public abstract class AbstractFetchOperation extends AbstractHuamiOperation { protected abstract void bufferActivityData(byte[] value); + protected void startFetching(TransactionBuilder builder, byte fetchType, GregorianCalendar sinceWhen) { + final String taskName = StringUtils.ensureNotNull(builder.getTaskName()); + byte[] fetchBytes = BLETypeConversions.join(new byte[]{ + HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, + fetchType}, + getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)); + builder.add(new AbstractGattListenerWriteAction(getQueue(), characteristicFetch, fetchBytes) { + @Override + protected boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { + UUID characteristicUUID = characteristic.getUuid(); + if (HuamiService.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { + byte[] value = characteristic.getValue(); + + if (ArrayUtils.equals(value, HuamiService.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { + handleActivityMetadata(value); + TransactionBuilder newBuilder = createTransactionBuilder(taskName + " Step 2"); + newBuilder.notify(characteristicActivityData, true); + newBuilder.write(characteristicFetch, new byte[]{HuamiService.COMMAND_FETCH_DATA}); + try { + performImmediately(newBuilder); + } catch (IOException ex) { + GB.toast(getContext(), "Error fetching debug logs: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); + } + return true; + } else { + handleActivityMetadata(value); + } + } + return false; + } + }); + } + protected void handleActivityMetadata(byte[] value) { if (value.length == 15) { // first two bytes are whether our request was accepted diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java index fe1f3951b..131c333ef 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchActivityOperation.java @@ -79,32 +79,7 @@ public class FetchActivityOperation extends AbstractFetchOperation { protected void startFetching(TransactionBuilder builder) { final String taskName = StringUtils.ensureNotNull(builder.getTaskName()); GregorianCalendar sinceWhen = getLastSuccessfulSyncTime(); - byte[] fetchBytes = BLETypeConversions.join(new byte[] { HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, HuamiService.COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY }, getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES)); - builder.add(new AbstractGattListenerWriteAction(getQueue(), characteristicFetch, fetchBytes) { - @Override - protected boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { - UUID characteristicUUID = characteristic.getUuid(); - if (HuamiService.UUID_UNKNOWN_CHARACTERISTIC4.equals(characteristicUUID)) { - byte[] value = characteristic.getValue(); - - if (ArrayUtils.equals(value, HuamiService.RESPONSE_ACTIVITY_DATA_START_DATE_SUCCESS, 0)) { - handleActivityMetadata(value); - TransactionBuilder newBuilder = createTransactionBuilder(taskName + " Step 2"); - newBuilder.notify(characteristicActivityData, true); - newBuilder.write(characteristicFetch, new byte[] { HuamiService.COMMAND_FETCH_DATA}); - try { - performImmediately(newBuilder); - } catch (IOException ex) { - GB.toast(getContext(), "Error fetching activity data: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); - } - return true; - } else { - handleActivityMetadata(value); - } - } - return false; - } - }); + startFetching(builder, HuamiService.COMMAND_ACTIVITY_DATA_TYPE_ACTIVTY, sinceWhen); } protected void handleActivityFetchFinish(boolean success) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsDetailsOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsDetailsOperation.java index 6de70b5e6..478d86b5a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsDetailsOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsDetailsOperation.java @@ -71,14 +71,7 @@ public class FetchSportsDetailsOperation extends AbstractFetchOperation { LOG.info("start " + getName()); buffer = new ByteArrayOutputStream(1024); GregorianCalendar sinceWhen = getLastSuccessfulSyncTime(); - - builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { - HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, - AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_DETAILS}, - getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES))); - builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply - builder.notify(characteristicActivityData, true); - builder.write(characteristicFetch, new byte[] { HuamiService.COMMAND_FETCH_DATA }); + startFetching(builder, AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_DETAILS, sinceWhen); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsSummaryOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsSummaryOperation.java index 0d26eca17..c5a498ce1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsSummaryOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/operations/FetchSportsSummaryOperation.java @@ -67,13 +67,7 @@ public class FetchSportsSummaryOperation extends AbstractFetchOperation { protected void startFetching(TransactionBuilder builder) { LOG.info("start" + getName()); GregorianCalendar sinceWhen = getLastSuccessfulSyncTime(); - builder.write(characteristicFetch, BLETypeConversions.join(new byte[] { - HuamiService.COMMAND_ACTIVITY_DATA_START_DATE, - AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_SUMMARIES}, - getSupport().getTimeBytes(sinceWhen, TimeUnit.MINUTES))); - builder.add(new WaitAction(1000)); // TODO: actually wait for the success-reply - builder.notify(characteristicActivityData, true); - builder.write(characteristicFetch, new byte[] { HuamiService.COMMAND_FETCH_DATA }); + startFetching(builder, AmazfitBipService.COMMAND_ACTIVITY_DATA_TYPE_SPORTS_SUMMARIES, sinceWhen); } @Override From 87bee53ef3515148cac7c393e0d915ec939e351a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 15 Sep 2018 22:43:45 +0200 Subject: [PATCH 24/65] Add a tiny bit of javadoc --- .../gadgetbridge/service/btle/TransactionBuilder.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java index 37dad0bb8..6672a7bf0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/TransactionBuilder.java @@ -68,6 +68,12 @@ public class TransactionBuilder { return new NotifyAction(characteristic, enable); } + /** + * Causes the queue to sleep for the specified time. + * Note that this is usually a bad idea, since it will not be able to process messages + * during that time. It is also likely to cause race conditions. + * @param millis the number of milliseconds to sleep + */ public TransactionBuilder wait(int millis) { WaitAction action = new WaitAction(millis); return add(action); From 08595f4e3ddb597c76f6244a75c0533601e52452 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 15 Sep 2018 22:52:30 +0200 Subject: [PATCH 25/65] Avoid autoboxing --- .../gadgetbridge/externalevents/NotificationListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java index 7ffceff57..18f6242bb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -272,9 +272,9 @@ public class NotificationListener extends NotificationListenerService { // Ignore too frequent notifications, according to user preference long min_timeout = prefs.getInt("notifications_timeout", 0) * 1000; - Long cur_time = System.currentTimeMillis(); + long cur_time = System.currentTimeMillis(); if (notificationTimes.containsKey(source)) { - Long last_time = notificationTimes.get(source); + long last_time = notificationTimes.get(source); if (cur_time - last_time < min_timeout) { LOG.info("Ignoring frequent notification, last one was " + (cur_time - last_time) + "ms ago"); return; From 898165ce0bed7698c35006cf87cd123d4bd978f0 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 15 Sep 2018 23:30:39 +0200 Subject: [PATCH 26/65] Avoid lots of false static analysis warnings --- .../service/DeviceCommunicationService.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index b96b663c1..2929fdda7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -339,6 +339,19 @@ public class DeviceCommunicationService extends Service implements SharedPrefere mGBDevice.sendDeviceUpdateIntent(this); } break; + default: + if (mDeviceSupport == null || mGBDevice == null) { + LOG.warn("device support:" + mDeviceSupport + ", device: " + mGBDevice + ", aborting"); + } else { + handleAction(intent, action, prefs); + } + break; + } + return START_STICKY; + } + + private void handleAction(Intent intent, String action, Prefs prefs) { + switch (action) { case ACTION_REQUEST_DEVICEINFO: mGBDevice.sendDeviceUpdateIntent(this); break; @@ -567,8 +580,6 @@ public class DeviceCommunicationService extends Service implements SharedPrefere } break; } - - return START_STICKY; } /** From 8aad6cd620cccbfc77d228a5c225599f7fca1cf8 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 15 Sep 2018 23:51:00 +0200 Subject: [PATCH 27/65] Avoid autoboxing, remove redundant cast --- .../gadgetbridge/activities/ActivitySummariesActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesActivity.java index 9f73841c7..0e8fe8f69 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ActivitySummariesActivity.java @@ -183,7 +183,7 @@ public class ActivitySummariesActivity extends AbstractListActivity Date: Sat, 15 Sep 2018 23:54:51 +0200 Subject: [PATCH 28/65] Fix some file closing issues --- .../freeyourgadget/gadgetbridge/export/GPXExporter.java | 5 ++--- .../gadgetbridge/util/ImportExportSharedPreferences.java | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/GPXExporter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/GPXExporter.java index ab8b64914..25a29b6c4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/GPXExporter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/export/GPXExporter.java @@ -60,8 +60,8 @@ public class GPXExporter implements ActivityTrackExporter { public void performExport(ActivityTrack track, File targetFile) throws IOException, GPXTrackEmptyException { String encoding = StandardCharsets.UTF_8.name(); XmlSerializer ser = Xml.newSerializer(); - try { - ser.setOutput(new FileOutputStream(targetFile), encoding); + try (FileOutputStream outputStream = new FileOutputStream(targetFile)) { + ser.setOutput(outputStream, encoding); ser.startDocument(encoding, Boolean.TRUE); ser.setPrefix("xsi", NS_XSI_URI); ser.setPrefix(NS_TRACKPOINT_EXTENSION, NS_TRACKPOINT_EXTENSION_URI); @@ -77,7 +77,6 @@ public class GPXExporter implements ActivityTrackExporter { ser.endTag(NS_DEFAULT, "gpx"); ser.endDocument(); - } finally { ser.flush(); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ImportExportSharedPreferences.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ImportExportSharedPreferences.java index f89ab5088..fbef26e6e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ImportExportSharedPreferences.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/ImportExportSharedPreferences.java @@ -50,11 +50,12 @@ public class ImportExportSharedPreferences { public static void exportToFile(SharedPreferences sharedPreferences, File outFile, Set doNotExport) throws IOException { - export(sharedPreferences, new FileWriter(outFile), doNotExport); + try (FileWriter outputWriter = new FileWriter(outFile)) { + export(sharedPreferences, outputWriter, doNotExport); + } } - - public static void export(SharedPreferences sharedPreferences, Writer writer, + private static void export(SharedPreferences sharedPreferences, Writer writer, Set doNotExport) throws IOException { XmlSerializer serializer = Xml.newSerializer(); serializer.setOutput(writer); @@ -75,11 +76,9 @@ public class ImportExportSharedPreferences { serializer.attribute("", NAME, key); serializer.text(value); serializer.endTag("", valueType); - } serializer.endTag("", PREFERENCES); serializer.endDocument(); - writer.close(); } public static boolean importFromFile(SharedPreferences sharedPreferences, File inFile) From f142003f095487b5c9d4facf23382f25253bd31f Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 15 Sep 2018 23:56:44 +0200 Subject: [PATCH 29/65] Avoid boxing --- .../appmanager/AbstractAppManagerFragment.java | 12 ++++++------ .../gadgetbridge/devices/hplus/HPlusCoordinator.java | 2 +- .../gadgetbridge/model/CalendarEvents.java | 4 ++-- .../gadgetbridge/service/AbstractDeviceSupport.java | 10 +++++----- .../service/DeviceCommunicationService.java | 2 +- .../service/devices/pebble/PebbleProtocol.java | 4 ++-- .../freeyourgadget/gadgetbridge/util/GB.java | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java index 8b5ce649f..d88c97890 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/appmanager/AbstractAppManagerFragment.java @@ -88,7 +88,7 @@ public abstract class AbstractAppManagerFragment extends Fragment { protected void refreshList() { appList.clear(); - ArrayList uuids = AppManagerActivity.getUuidsFromFile(getSortFilename()); + ArrayList uuids = AppManagerActivity.getUuidsFromFile(getSortFilename()); List systemApps = getSystemAppsInCategory(); boolean needsRewrite = false; for (GBDeviceApp systemApp : systemApps) { @@ -106,11 +106,11 @@ public abstract class AbstractAppManagerFragment extends Fragment { private void refreshListFromPebble(Intent intent) { appList.clear(); int appCount = intent.getIntExtra("app_count", 0); - for (Integer i = 0; i < appCount; i++) { - String appName = intent.getStringExtra("app_name" + i.toString()); - String appCreator = intent.getStringExtra("app_creator" + i.toString()); - UUID uuid = UUID.fromString(intent.getStringExtra("app_uuid" + i.toString())); - GBDeviceApp.Type appType = GBDeviceApp.Type.values()[intent.getIntExtra("app_type" + i.toString(), 0)]; + for (int i = 0; i < appCount; i++) { + String appName = intent.getStringExtra("app_name" + i); + String appCreator = intent.getStringExtra("app_creator" + i); + UUID uuid = UUID.fromString(intent.getStringExtra("app_uuid" + i)); + GBDeviceApp.Type appType = GBDeviceApp.Type.values()[intent.getIntExtra("app_type" + i, 0)]; GBDeviceApp app = new GBDeviceApp(uuid, appName, appCreator, "", appType); app.setOnDevice(true); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java index e4f8012e8..5717a3f02 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/hplus/HPlusCoordinator.java @@ -255,7 +255,7 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator { } public static byte getAllDayHR(String address) { - Boolean value = (prefs.getBoolean(HPlusConstants.PREF_HPLUS_ALLDAYHR, true)); + boolean value = (prefs.getBoolean(HPlusConstants.PREF_HPLUS_ALLDAYHR, true)); if(value){ return HPlusConstants.ARG_HEARTRATE_ALLDAY_ON; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CalendarEvents.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CalendarEvents.java index e882af658..8a1fbe071 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CalendarEvents.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/CalendarEvents.java @@ -71,9 +71,9 @@ public class CalendarEvents { private boolean fetchSystemEvents(Context mContext) { Calendar cal = GregorianCalendar.getInstance(); - Long dtStart = cal.getTimeInMillis(); + long dtStart = cal.getTimeInMillis(); cal.add(Calendar.DATE, lookahead_days); - Long dtEnd = cal.getTimeInMillis(); + long dtEnd = cal.getTimeInMillis(); Uri.Builder eventsUriBuilder = Instances.CONTENT_URI.buildUpon(); ContentUris.appendId(eventsUriBuilder, dtStart); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index 7b6331b1d..dd969d237 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -241,11 +241,11 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { Intent appInfoIntent = new Intent(AbstractAppManagerFragment.ACTION_REFRESH_APPLIST); int appCount = appInfoEvent.apps.length; appInfoIntent.putExtra("app_count", appCount); - for (Integer i = 0; i < appCount; i++) { - appInfoIntent.putExtra("app_name" + i.toString(), appInfoEvent.apps[i].getName()); - appInfoIntent.putExtra("app_creator" + i.toString(), appInfoEvent.apps[i].getCreator()); - appInfoIntent.putExtra("app_uuid" + i.toString(), appInfoEvent.apps[i].getUUID().toString()); - appInfoIntent.putExtra("app_type" + i.toString(), appInfoEvent.apps[i].getType().ordinal()); + for (int i = 0; i < appCount; i++) { + appInfoIntent.putExtra("app_name" + i, appInfoEvent.apps[i].getName()); + appInfoIntent.putExtra("app_creator" + i, appInfoEvent.apps[i].getCreator()); + appInfoIntent.putExtra("app_uuid" + i, appInfoEvent.apps[i].getUUID().toString()); + appInfoIntent.putExtra("app_type" + i, appInfoEvent.apps[i].getType().ordinal()); } LocalBroadcastManager.getInstance(context).sendBroadcast(appInfoIntent); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index 2929fdda7..065c8045a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -542,7 +542,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere break; } case ACTION_SET_HEARTRATE_MEASUREMENT_INTERVAL: { - Integer seconds = intent.getIntExtra(EXTRA_INTERVAL_SECONDS, 0); + int seconds = intent.getIntExtra(EXTRA_INTERVAL_SECONDS, 0); mDeviceSupport.onSetHeartRateMeasurementInterval(seconds); break; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index 7da9430e3..bcdebe2c6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -497,7 +497,7 @@ public class PebbleProtocol extends GBDeviceProtocol { title = notificationSpec.title; } - Long ts = System.currentTimeMillis(); + long ts = System.currentTimeMillis(); if (mFwMajor < 3) { ts += (SimpleTimeZone.getDefault().getOffset(ts)); } @@ -514,7 +514,7 @@ public class PebbleProtocol extends GBDeviceProtocol { notificationSpec.sourceName, hasHandle, notificationSpec.cannedReplies); } else { // 1.x notification on FW 2.X - String[] parts = {title, notificationSpec.body, ts.toString(), subtitle}; + String[] parts = {title, notificationSpec.body, String.valueOf(ts), subtitle}; // be aware that type is at this point always NOTIFICATION_EMAIL return encodeMessage(ENDPOINT_NOTIFICATION, NOTIFICATION_EMAIL, 0, parts); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java index 1af2c4e89..b63102a17 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java @@ -91,7 +91,7 @@ public class GB { text += ": " + context.getString(R.string.battery) + " " + device.getBatteryLevel() + "%"; } - Boolean connected = device.isInitialized(); + boolean connected = device.isInitialized(); NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID); builder.setContentTitle(deviceName) .setTicker(deviceName + " - " + text) From 08dfa2a47d16cd388ad961a490f76dc8849791f4 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 16 Sep 2018 00:12:52 +0200 Subject: [PATCH 30/65] Log the stacktrace as well --- .../gadgetbridge/service/devices/pebble/PebbleIoThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java index d359391e4..eb486ac9e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java @@ -464,7 +464,7 @@ class PebbleIoThread extends GBDeviceIoThread { mOutStream.flush(); } } catch (IOException e) { - LOG.error("Error writing.", e.getMessage()); + LOG.error("Error writing.", e); } try { Thread.sleep(100); From 5028458fe8c441de7b6ac6872d6df76d941c8a8a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 16 Sep 2018 13:37:08 +0200 Subject: [PATCH 31/65] Fix some static analysis warnings --- .../charts/AbstractWeekChartFragment.java | 10 +-- .../charts/WeekSleepChartFragment.java | 16 ++--- .../charts/WeekStepsChartFragment.java | 14 ++--- .../service/devices/xwatch/XWatchSupport.java | 38 ++++++------ .../devices/zetime/ZeTimeDeviceSupport.java | 61 ++++++++----------- 5 files changed, 63 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java index c6b07dee4..5a5ab43f6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractWeekChartFragment.java @@ -108,7 +108,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { List entries = new ArrayList<>(); ArrayList labels = new ArrayList(); - int balance = 0; + long balance = 0; for (int counter = 0; counter < TOTAL_DAYS; counter++) { ActivityAmounts amounts = getActivityAmountsForDay(db, day, device); @@ -171,7 +171,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { set.setValueFormatter(getPieValueFormatter()); } - return new DayData(data, formatPieValue((int) totalValue)); + return new DayData(data, formatPieValue((long) totalValue)); } @Override @@ -321,7 +321,7 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { abstract float[] getTotalsForActivityAmounts(ActivityAmounts activityAmounts); - abstract String formatPieValue(int value); + abstract String formatPieValue(long value); abstract String[] getPieLabels(); @@ -335,9 +335,9 @@ public abstract class AbstractWeekChartFragment extends AbstractChartFragment { abstract String getPieDescription(int targetValue); - protected abstract int calculateBalance(ActivityAmounts amounts); + protected abstract long calculateBalance(ActivityAmounts amounts); - protected abstract String getBalanceMessage(int balance, int targetValue); + protected abstract String getBalanceMessage(long balance, int targetValue); private class WeekChartsData> extends DefaultChartsData { private final String balanceMessage; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java index 1d82cd5c8..fffa5fbf8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekSleepChartFragment.java @@ -60,7 +60,7 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { @Override - protected int calculateBalance(ActivityAmounts activityAmounts) { + protected long calculateBalance(ActivityAmounts activityAmounts) { long balance = 0; for (ActivityAmount amount : activityAmounts.getAmounts()) { @@ -72,13 +72,13 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { } @Override - protected String getBalanceMessage(int balance, int targetValue) { + protected String getBalanceMessage(long balance, int targetValue) { if (balance > 0) { final long totalBalance = balance - (targetValue * TOTAL_DAYS); if (totalBalance > 0) - return getString(R.string.overslept, getHM((int) totalBalance)); + return getString(R.string.overslept, getHM(totalBalance)); else - return getString(R.string.lack_of_sleep, getHM((int) Math.abs(totalBalance))); + return getString(R.string.lack_of_sleep, getHM(Math.abs(totalBalance))); } else return getString(R.string.no_data); } @@ -100,8 +100,8 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { } @Override - protected String formatPieValue(int value) { - return DateTimeUtils.formatDurationHoursMinutes((long) value, TimeUnit.MINUTES); + protected String formatPieValue(long value) { + return DateTimeUtils.formatDurationHoursMinutes(value, TimeUnit.MINUTES); } @Override @@ -114,7 +114,7 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { return new IValueFormatter() { @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return formatPieValue((int) value); + return formatPieValue((long) value); } }; } @@ -164,7 +164,7 @@ public class WeekSleepChartFragment extends AbstractWeekChartFragment { chart.getLegend().setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); } - private String getHM(int value) { + private String getHM(long value) { return DateTimeUtils.formatDurationHoursMinutes(value, TimeUnit.MINUTES); } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java index df298ca24..2291e3665 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java @@ -50,7 +50,7 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { @Override float[] getTotalsForActivityAmounts(ActivityAmounts activityAmounts) { - int totalSteps = 0; + long totalSteps = 0; for (ActivityAmount amount : activityAmounts.getAmounts()) { totalSteps += amount.getTotalSteps(); } @@ -58,8 +58,8 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { } @Override - protected int calculateBalance(ActivityAmounts activityAmounts) { - int balance = 0; + protected long calculateBalance(ActivityAmounts activityAmounts) { + long balance = 0; for (ActivityAmount amount : activityAmounts.getAmounts()) { balance += amount.getTotalSteps(); } @@ -67,7 +67,7 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { } @Override - protected String formatPieValue(int value) { + protected String formatPieValue(long value) { return String.valueOf(value); } @@ -103,13 +103,13 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { } @Override - protected String getBalanceMessage(int balance, int targetValue) { + protected String getBalanceMessage(long balance, int targetValue) { if (balance > 0) { final long totalBalance = balance - (targetValue * TOTAL_DAYS); if (totalBalance > 0) - return getString(R.string.overstep, (int) Math.abs(totalBalance)); + return getString(R.string.overstep, Math.abs(totalBalance)); else - return getString(R.string.lack_of_step, (int) Math.abs(totalBalance)); + return getString(R.string.lack_of_step, Math.abs(totalBalance)); } else return getString(R.string.no_data); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java index 4c5ee35f0..d0144995d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java @@ -1,19 +1,19 @@ -/* Copyright (C) 2018 Andreas Shimokawa, ladbsoft - - This file is part of Gadgetbridge. - - Gadgetbridge is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Gadgetbridge is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . */ +/* Copyright (C) 2018 Andreas Shimokawa, ladbsoft + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.xwatch; import android.bluetooth.BluetoothGatt; @@ -548,9 +548,9 @@ public class XWatchSupport extends AbstractBTLEDeviceSupport { int yearInt, monthInt, dayInt, hoursMinutesInt = 0; int hours, minutes = 0; - yearInt = Integer.valueOf(String.format("%02x", year, 16)); - monthInt = Integer.valueOf(String.format("%02x", month, 16)); - dayInt = Integer.valueOf(String.format("%02x", day, 16)); + yearInt = Integer.valueOf(String.format("%02x", year), 16); + monthInt = Integer.valueOf(String.format("%02x", month), 16); + dayInt = Integer.valueOf(String.format("%02x", day), 16); hoursMinutesInt = Integer.valueOf(String.format("%02x", hoursminutes), 16); minutes = hoursMinutesInt % 4; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java index bbfee0214..23310194c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/zetime/ZeTimeDeviceSupport.java @@ -200,14 +200,12 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { music[5] = musicState; System.arraycopy(songtitle.getBytes(StandardCharsets.UTF_8), 0, music, 6, songtitle.getBytes(StandardCharsets.UTF_8).length); music[music.length - 1] = ZeTimeConstants.CMD_END; - if (music != null) { - try { - TransactionBuilder builder = performInitialized("setMusicStateInfo"); - replyMsgToWatch(builder, music); - builder.queue(getQueue()); - } catch (IOException e) { - GB.toast(getContext(), "Error setting music state and info: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } + try { + TransactionBuilder builder = performInitialized("setMusicStateInfo"); + replyMsgToWatch(builder, music); + builder.queue(getQueue()); + } catch (IOException e) { + GB.toast(getContext(), "Error setting music state and info: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } } } @@ -345,14 +343,12 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { } System.arraycopy(songtitle.getBytes(StandardCharsets.UTF_8), 0, music, 6, songtitle.getBytes(StandardCharsets.UTF_8).length); music[music.length - 1] = ZeTimeConstants.CMD_END; - if (music != null) { - try { - TransactionBuilder builder = performInitialized("setMusicStateInfo"); - replyMsgToWatch(builder, music); - builder.queue(getQueue()); - } catch (IOException e) { - GB.toast(getContext(), "Error setting music state and info: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } + try { + TransactionBuilder builder = performInitialized("setMusicStateInfo"); + replyMsgToWatch(builder, music); + builder.queue(getQueue()); + } catch (IOException e) { + GB.toast(getContext(), "Error setting music state and info: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } } } @@ -379,15 +375,12 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { CalendarEvent[14] = (byte) calendarEventSpec.title.getBytes(StandardCharsets.UTF_8).length; System.arraycopy(calendarEventSpec.title.getBytes(StandardCharsets.UTF_8), 0, CalendarEvent, 15, calendarEventSpec.title.getBytes(StandardCharsets.UTF_8).length); CalendarEvent[CalendarEvent.length-1] = ZeTimeConstants.CMD_END; - if(CalendarEvent != null) - { - try { - TransactionBuilder builder = performInitialized("sendCalendarEvenr"); - sendMsgToWatch(builder, CalendarEvent); - builder.queue(getQueue()); - } catch (IOException e) { - GB.toast(getContext(), "Error sending calendar event: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } + try { + TransactionBuilder builder = performInitialized("sendCalendarEvenr"); + sendMsgToWatch(builder, CalendarEvent); + builder.queue(getQueue()); + } catch (IOException e) { + GB.toast(getContext(), "Error sending calendar event: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } } @@ -449,15 +442,12 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { } System.arraycopy(weatherSpec.location.getBytes(StandardCharsets.UTF_8), 0, weather, 25, weatherSpec.location.getBytes(StandardCharsets.UTF_8).length); weather[weather.length-1] = ZeTimeConstants.CMD_END; - if(weather != null) - { - try { - TransactionBuilder builder = performInitialized("sendWeahter"); - sendMsgToWatch(builder, weather); - builder.queue(getQueue()); - } catch (IOException e) { - GB.toast(getContext(), "Error sending weather: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } + try { + TransactionBuilder builder = performInitialized("sendWeahter"); + sendMsgToWatch(builder, weather); + builder.queue(getQueue()); + } catch (IOException e) { + GB.toast(getContext(), "Error sending weather: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } } @@ -620,8 +610,6 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { notification[5] = ZeTimeConstants.NOTIFICATION_SOCIAL; break; } - if(notification != null) - { try { TransactionBuilder builder = performInitialized("sendNotification"); sendMsgToWatch(builder, notification); @@ -629,7 +617,6 @@ public class ZeTimeDeviceSupport extends AbstractBTLEDeviceSupport { } catch (IOException e) { GB.toast(getContext(), "Error sending notification: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); } - } } @Override From 100ed9f50c591b995f7bc35e3d248dd6d3576b8a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 16 Sep 2018 13:55:57 +0200 Subject: [PATCH 32/65] Use \n as line endings --- .../service/devices/xwatch/XWatchSupport.java | 1144 ++++++++--------- 1 file changed, 572 insertions(+), 572 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java index d0144995d..0cc76021e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/xwatch/XWatchSupport.java @@ -1,572 +1,572 @@ -/* Copyright (C) 2018 Andreas Shimokawa, ladbsoft - - This file is part of Gadgetbridge. - - Gadgetbridge is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Gadgetbridge is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . */ -package nodomain.freeyourgadget.gadgetbridge.service.devices.xwatch; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCharacteristic; -import android.content.Context; -import android.media.AudioManager; -import android.net.Uri; -import android.view.KeyEvent; -import android.widget.Toast; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.UUID; - -import nodomain.freeyourgadget.gadgetbridge.GBApplication; -import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; -import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; -import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo; -import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; -import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchSampleProvider; -import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchService; -import nodomain.freeyourgadget.gadgetbridge.entities.Device; -import nodomain.freeyourgadget.gadgetbridge.entities.User; -import nodomain.freeyourgadget.gadgetbridge.entities.XWatchActivitySample; -import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; -import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; -import nodomain.freeyourgadget.gadgetbridge.model.Alarm; -import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; -import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; -import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; -import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; -import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; -import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; -import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; -import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; -import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; -import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; -import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.DeviceInfo; -import nodomain.freeyourgadget.gadgetbridge.util.GB; - -public class XWatchSupport extends AbstractBTLEDeviceSupport { - private static final Logger LOG = LoggerFactory.getLogger(XWatchSupport.class); - private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo(); - TransactionBuilder builder = null; - private DeviceInfo mDeviceInfo; - private byte dayToFetch; //0 = Today; 1 = Yesterday ... - private byte maxDayToFetch; - long lastButtonTimestamp; - - public XWatchSupport() { - super(LOG); - - addSupportedService(XWatchService.UUID_SERVICE); - addSupportedService(XWatchService.UUID_WRITE); - addSupportedService(XWatchService.UUID_NOTIFY); - } - - public static byte[] crcChecksum(byte[] data) { - byte[] return_data = new byte[(data.length + 1)]; - byte checksum = 0; - - for (int i = 0; i < data.length; i++) { - return_data[i] = data[i]; - checksum += data[i]; - } - return_data[return_data.length - 1] = checksum; - - return return_data; - } - - @Override - protected TransactionBuilder initializeDevice(TransactionBuilder builder) { - builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZING, getContext())); - - enableNotifications(builder) - .setDateTime(builder) - .setInitialized(builder); - - return builder; - } - - /** - * Last action of initialization sequence. Sets the device to initialized. - * It is only invoked if all other actions were successfully run, so the device - * must be initialized, then. - * - * @param builder - */ - private void setInitialized(TransactionBuilder builder) { - builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZED, getContext())); - } - - @Override - public boolean useAutoConnect() { - return true; - } - - @Override - public boolean connectFirstTime() { - for (int i = 0; i < 5; i++) { - if (connect()) { - return true; - } - } - return false; - } - - private XWatchSupport setDateTime(TransactionBuilder builder) { - byte[] data; - - LOG.debug("Sending current date to the XWatch"); - BluetoothGattCharacteristic deviceData = getCharacteristic(XWatchService.UUID_WRITE); - - String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); - String y = time.substring(2, 4); - String M = time.substring(4, 6); - String d = time.substring(6, 8); - String H = time.substring(8, 10); - String m = time.substring(10, 12); - String s = time.substring(12, 14); - System.out.println(y + ":" + M + ":" + d + ":" + H + ":" + m + ":" + time.substring(12, 14)); - - data = new byte[]{(byte) 1, - (byte) Integer.parseInt(y, 16), - (byte) Integer.parseInt(M, 16), - (byte) Integer.parseInt(d, 16), - (byte) Integer.parseInt(H, 16), - (byte) Integer.parseInt(m, 16), - (byte) Integer.parseInt(s, 16), - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0}; - - data = crcChecksum(data); - - builder.write(deviceData, data); - - return this; - } - - private XWatchSupport enableNotifications(TransactionBuilder builder) { - LOG.debug("Enabling action button"); - BluetoothGattCharacteristic deviceInfo = getCharacteristic(XWatchService.UUID_NOTIFY); - builder.notify(deviceInfo, true); - return this; - } - - @Override - public void onEnableHeartRateSleepSupport(boolean enable) { - //Not supported - } - - @Override - public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) { - // not supported - } - - @Override - public void onDeleteCalendarEvent(byte type, long id) { - // not supported - } - - @Override - public void onSetAlarms(ArrayList alarms) { - //TODO: Implement - } - - @Override - public void onNotification(NotificationSpec notificationSpec) { - //TODO: Implement - } - - @Override - public void onDeleteNotification(int id) { - //TODO: Implement - } - - @Override - public void onSetTime() { - try { - TransactionBuilder builder = performInitialized("Set date and time"); - setDateTime(builder); - builder.queue(getQueue()); - } catch (IOException ex) { - LOG.error("Unable to set time and date on XWatch device", ex); - } - } - - @Override - public void onSetCallState(CallSpec callSpec) { - //TODO: Implement (if necessary) - } - - @Override - public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) { - } - - @Override - public void onSetMusicState(MusicStateSpec stateSpec) { - // not supported - } - - @Override - public void onSetMusicInfo(MusicSpec musicSpec) { - // not supported - } - - @Override - public void onReboot() { - //Not supported - } - - @Override - public void onHeartRateTest() { - //Not supported - } - - @Override - public void onEnableRealtimeHeartRateMeasurement(boolean enable) { - //Not supported - } - - @Override - public void onFindDevice(boolean start) { - //TODO: Implement - } - - @Override - public void onSetConstantVibration(int intensity) { - //TODO: Implement - } - - @Override - public void onFetchRecordedData(int dataTypes) { - try { - if(builder == null) { - builder = performInitialized("fetchActivityData"); - } - requestSummarizedData(builder); - performConnected(builder.getTransaction()); - } catch (IOException e) { - GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } - } - - @Override - public void onEnableRealtimeSteps(boolean enable) { - //Not supported - } - - @Override - public void onInstallApp(Uri uri) { - //Not supported - } - - @Override - public void onAppInfoReq() { - // not supported - } - - @Override - public void onAppStart(UUID uuid, boolean start) { - // not supported - } - - @Override - public void onAppDelete(UUID uuid) { - // not supported - } - - @Override - public void onAppReorder(UUID[] uuids) { - // not supported - } - - @Override - public void onScreenshotReq() { - // not supported - } - - @Override - public boolean onCharacteristicChanged(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic) { - super.onCharacteristicChanged(gatt, characteristic); - - UUID characteristicUUID = characteristic.getUuid(); - if (XWatchService.UUID_NOTIFY.equals(characteristicUUID)) { - byte[] data = characteristic.getValue(); - if (data[0] == XWatchService.COMMAND_ACTIVITY_TOTALS) { - handleSummarizedData(characteristic.getValue()); - } else if (data[0] == XWatchService.COMMAND_ACTIVITY_DATA) { - handleDetailedData(characteristic.getValue()); - } else if (data[0] == XWatchService.COMMAND_ACTION_BUTTON) { - handleButtonPressed(characteristic.getValue()); - } else if (data[0] == XWatchService.COMMAND_CONNECTED) { - handleDeviceInfo(data, BluetoothGatt.GATT_SUCCESS); - } else { - LOG.info("Handled characteristic with unknown data: " + characteristicUUID); - logMessageContent(characteristic.getValue()); - } - } else { - LOG.info("Unhandled characteristic changed: " + characteristicUUID); - logMessageContent(characteristic.getValue()); - } - return false; - } - - @Override - public boolean onCharacteristicRead(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic, int status) { - return super.onCharacteristicChanged(gatt, characteristic); - //TODO: Implement (if necessary) - } - - @Override - public boolean onCharacteristicWrite(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic, int status) { - return super.onCharacteristicWrite(gatt, characteristic, status); - //TODO: Implement (if necessary) - } - - public XWatchActivitySample createActivitySample(Device device, User user, int timestampInSeconds, SampleProvider provider) { - XWatchActivitySample sample = new XWatchActivitySample(); - sample.setDevice(device); - sample.setUser(user); - sample.setTimestamp(timestampInSeconds); - sample.setProvider(provider); - - return sample; - } - - private void handleDeviceInfo(byte[] value, int status) { - if (status == BluetoothGatt.GATT_SUCCESS) { - mDeviceInfo = new DeviceInfo(value); - LOG.warn("Device info: " + mDeviceInfo); - versionCmd.hwVersion = "1.0"; - versionCmd.fwVersion = "1.0"; - handleGBDeviceEvent(versionCmd); - } - } - - @Override - public void onSendConfiguration(String config) { - // nothing yet - } - - @Override - public void onTestNewFunction() { - //Not supported - } - - @Override - public void onSendWeather(WeatherSpec weatherSpec) { - //Not supported - } - - private void handleSummarizedData(byte[] value) { - int daysIntTotal; - int daysIntPart; - - if (value.length != 16) { - LOG.warn("GOT UNEXPECTED SENSOR DATA WITH LENGTH: " + value.length); - for (byte b : value) { - LOG.warn("DATA: " + String.format("0x%4x", b)); - } - } else { - daysIntPart = (value[1] & 255) << 24; - daysIntTotal = daysIntPart; - daysIntPart = (value[2] & 255) << 16; - daysIntTotal += daysIntPart; - daysIntPart = (value[3] & 255) << 8; - daysIntTotal += daysIntPart; - daysIntPart = (value[4] & 255); - daysIntTotal += daysIntPart; - - dayToFetch = 0; - maxDayToFetch = (byte) Integer.bitCount(daysIntTotal); - - try { - requestDetailedData(builder); - performConnected(builder.getTransaction()); - } catch (IOException e) { - GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } - } - } - - private void handleDetailedData(byte[] value) { - int category, intensity, steps = 0; - - if (value.length != 16) { - LOG.warn("GOT UNEXPECTED SENSOR DATA WITH LENGTH: " + value.length); - for (byte b : value) { - LOG.warn("DATA: " + String.format("0x%4x", b)); - } - } else { - try (DBHandler dbHandler = GBApplication.acquireDB()) { - XWatchSampleProvider provider = new XWatchSampleProvider(getDevice(), dbHandler.getDaoSession()); - User user = DBHelper.getUser(dbHandler.getDaoSession()); - Device device = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()); - int timestampInSeconds = 0; - - timestampInSeconds = getTimestampFromData( - value[2], - value[3], - value[4], - value[5] - ); - - category = ActivityKind.TYPE_ACTIVITY; - intensity = (value[7] & 255) + ((value[8] & 255) << 8); - steps = (value[9] & 255) + ((value[10] & 255) << 8); - - XWatchActivitySample sample = createActivitySample(device, user, timestampInSeconds, provider); - sample.setRawIntensity(intensity); - sample.setSteps(steps); - sample.setRawKind(category); - - if (LOG.isDebugEnabled()) { - LOG.debug("sample: " + sample); - } - - provider.addGBActivitySample(sample); - - if (value[5] == 95) { - dayToFetch++; - if(dayToFetch <= maxDayToFetch) { - try { - builder = performInitialized("fetchActivityData"); - requestDetailedData(builder); - performConnected(builder.getTransaction()); - } catch (IOException e) { - GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); - } - } - } - } catch (Exception ex) { - GB.toast(getContext(), ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); - } - } - } - - private void handleButtonPressed(byte[] value) { - long currentTimestamp = System.currentTimeMillis(); - - AudioManager audioManager = (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE); - if(audioManager.isWiredHeadsetOn()) { - if (currentTimestamp - lastButtonTimestamp < 1000) { - if (audioManager.isMusicActive()) { - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); - } else { - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); - } - } else { - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); - audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); - } - } - - lastButtonTimestamp = currentTimestamp; - } - - @Override - public void onAppConfiguration(UUID appUuid, String config, Integer id) { - //Not supported - } - - @Override - public void onSetHeartRateMeasurementInterval(int seconds) { - //Not supported - } - - private void requestSummarizedData(TransactionBuilder builder) { - byte[] fetch = new byte[]{(byte) XWatchService.COMMAND_ACTIVITY_TOTALS, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0}; - - fetch = XWatchSupport.crcChecksum(fetch); - builder.write(getCharacteristic(XWatchService.UUID_WRITE), fetch); - } - - private void requestDetailedData(TransactionBuilder builder) { - byte[] fetch = new byte[]{(byte) XWatchService.COMMAND_ACTIVITY_DATA, - (byte) dayToFetch, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0, - (byte) 0}; - - fetch = XWatchSupport.crcChecksum(fetch); - builder.write(getCharacteristic(XWatchService.UUID_WRITE), fetch); - } - - private int getTimestampFromData(byte year, byte month, byte day, byte hoursminutes) { - int timestamp = 0; - int yearInt, monthInt, dayInt, hoursMinutesInt = 0; - int hours, minutes = 0; - - yearInt = Integer.valueOf(String.format("%02x", year), 16); - monthInt = Integer.valueOf(String.format("%02x", month), 16); - dayInt = Integer.valueOf(String.format("%02x", day), 16); - hoursMinutesInt = Integer.valueOf(String.format("%02x", hoursminutes), 16); - - minutes = hoursMinutesInt % 4; - hours = (hoursMinutesInt - minutes) / 4; - minutes = minutes * 15; - - GregorianCalendar cal = new GregorianCalendar( - 2000 + yearInt, - monthInt - 1, - dayInt, - hours, - minutes - ); - - timestamp = (int)(cal.getTimeInMillis() / 1000); - - return timestamp; - } -} +/* Copyright (C) 2018 Andreas Shimokawa, ladbsoft + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.xwatch; + +import android.bluetooth.BluetoothGatt; +import android.bluetooth.BluetoothGattCharacteristic; +import android.content.Context; +import android.media.AudioManager; +import android.net.Uri; +import android.view.KeyEvent; +import android.widget.Toast; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.UUID; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; +import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo; +import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchSampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchService; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.entities.User; +import nodomain.freeyourgadget.gadgetbridge.entities.XWatchActivitySample; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice.State; +import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; +import nodomain.freeyourgadget.gadgetbridge.model.Alarm; +import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; +import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; +import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; +import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; +import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; +import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; +import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport; +import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; +import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.DeviceInfo; +import nodomain.freeyourgadget.gadgetbridge.util.GB; + +public class XWatchSupport extends AbstractBTLEDeviceSupport { + private static final Logger LOG = LoggerFactory.getLogger(XWatchSupport.class); + private final GBDeviceEventVersionInfo versionCmd = new GBDeviceEventVersionInfo(); + TransactionBuilder builder = null; + private DeviceInfo mDeviceInfo; + private byte dayToFetch; //0 = Today; 1 = Yesterday ... + private byte maxDayToFetch; + long lastButtonTimestamp; + + public XWatchSupport() { + super(LOG); + + addSupportedService(XWatchService.UUID_SERVICE); + addSupportedService(XWatchService.UUID_WRITE); + addSupportedService(XWatchService.UUID_NOTIFY); + } + + public static byte[] crcChecksum(byte[] data) { + byte[] return_data = new byte[(data.length + 1)]; + byte checksum = 0; + + for (int i = 0; i < data.length; i++) { + return_data[i] = data[i]; + checksum += data[i]; + } + return_data[return_data.length - 1] = checksum; + + return return_data; + } + + @Override + protected TransactionBuilder initializeDevice(TransactionBuilder builder) { + builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZING, getContext())); + + enableNotifications(builder) + .setDateTime(builder) + .setInitialized(builder); + + return builder; + } + + /** + * Last action of initialization sequence. Sets the device to initialized. + * It is only invoked if all other actions were successfully run, so the device + * must be initialized, then. + * + * @param builder + */ + private void setInitialized(TransactionBuilder builder) { + builder.add(new SetDeviceStateAction(getDevice(), State.INITIALIZED, getContext())); + } + + @Override + public boolean useAutoConnect() { + return true; + } + + @Override + public boolean connectFirstTime() { + for (int i = 0; i < 5; i++) { + if (connect()) { + return true; + } + } + return false; + } + + private XWatchSupport setDateTime(TransactionBuilder builder) { + byte[] data; + + LOG.debug("Sending current date to the XWatch"); + BluetoothGattCharacteristic deviceData = getCharacteristic(XWatchService.UUID_WRITE); + + String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + String y = time.substring(2, 4); + String M = time.substring(4, 6); + String d = time.substring(6, 8); + String H = time.substring(8, 10); + String m = time.substring(10, 12); + String s = time.substring(12, 14); + System.out.println(y + ":" + M + ":" + d + ":" + H + ":" + m + ":" + time.substring(12, 14)); + + data = new byte[]{(byte) 1, + (byte) Integer.parseInt(y, 16), + (byte) Integer.parseInt(M, 16), + (byte) Integer.parseInt(d, 16), + (byte) Integer.parseInt(H, 16), + (byte) Integer.parseInt(m, 16), + (byte) Integer.parseInt(s, 16), + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0}; + + data = crcChecksum(data); + + builder.write(deviceData, data); + + return this; + } + + private XWatchSupport enableNotifications(TransactionBuilder builder) { + LOG.debug("Enabling action button"); + BluetoothGattCharacteristic deviceInfo = getCharacteristic(XWatchService.UUID_NOTIFY); + builder.notify(deviceInfo, true); + return this; + } + + @Override + public void onEnableHeartRateSleepSupport(boolean enable) { + //Not supported + } + + @Override + public void onAddCalendarEvent(CalendarEventSpec calendarEventSpec) { + // not supported + } + + @Override + public void onDeleteCalendarEvent(byte type, long id) { + // not supported + } + + @Override + public void onSetAlarms(ArrayList alarms) { + //TODO: Implement + } + + @Override + public void onNotification(NotificationSpec notificationSpec) { + //TODO: Implement + } + + @Override + public void onDeleteNotification(int id) { + //TODO: Implement + } + + @Override + public void onSetTime() { + try { + TransactionBuilder builder = performInitialized("Set date and time"); + setDateTime(builder); + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Unable to set time and date on XWatch device", ex); + } + } + + @Override + public void onSetCallState(CallSpec callSpec) { + //TODO: Implement (if necessary) + } + + @Override + public void onSetCannedMessages(CannedMessagesSpec cannedMessagesSpec) { + } + + @Override + public void onSetMusicState(MusicStateSpec stateSpec) { + // not supported + } + + @Override + public void onSetMusicInfo(MusicSpec musicSpec) { + // not supported + } + + @Override + public void onReboot() { + //Not supported + } + + @Override + public void onHeartRateTest() { + //Not supported + } + + @Override + public void onEnableRealtimeHeartRateMeasurement(boolean enable) { + //Not supported + } + + @Override + public void onFindDevice(boolean start) { + //TODO: Implement + } + + @Override + public void onSetConstantVibration(int intensity) { + //TODO: Implement + } + + @Override + public void onFetchRecordedData(int dataTypes) { + try { + if(builder == null) { + builder = performInitialized("fetchActivityData"); + } + requestSummarizedData(builder); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } + } + + @Override + public void onEnableRealtimeSteps(boolean enable) { + //Not supported + } + + @Override + public void onInstallApp(Uri uri) { + //Not supported + } + + @Override + public void onAppInfoReq() { + // not supported + } + + @Override + public void onAppStart(UUID uuid, boolean start) { + // not supported + } + + @Override + public void onAppDelete(UUID uuid) { + // not supported + } + + @Override + public void onAppReorder(UUID[] uuids) { + // not supported + } + + @Override + public void onScreenshotReq() { + // not supported + } + + @Override + public boolean onCharacteristicChanged(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic) { + super.onCharacteristicChanged(gatt, characteristic); + + UUID characteristicUUID = characteristic.getUuid(); + if (XWatchService.UUID_NOTIFY.equals(characteristicUUID)) { + byte[] data = characteristic.getValue(); + if (data[0] == XWatchService.COMMAND_ACTIVITY_TOTALS) { + handleSummarizedData(characteristic.getValue()); + } else if (data[0] == XWatchService.COMMAND_ACTIVITY_DATA) { + handleDetailedData(characteristic.getValue()); + } else if (data[0] == XWatchService.COMMAND_ACTION_BUTTON) { + handleButtonPressed(characteristic.getValue()); + } else if (data[0] == XWatchService.COMMAND_CONNECTED) { + handleDeviceInfo(data, BluetoothGatt.GATT_SUCCESS); + } else { + LOG.info("Handled characteristic with unknown data: " + characteristicUUID); + logMessageContent(characteristic.getValue()); + } + } else { + LOG.info("Unhandled characteristic changed: " + characteristicUUID); + logMessageContent(characteristic.getValue()); + } + return false; + } + + @Override + public boolean onCharacteristicRead(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, int status) { + return super.onCharacteristicChanged(gatt, characteristic); + //TODO: Implement (if necessary) + } + + @Override + public boolean onCharacteristicWrite(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, int status) { + return super.onCharacteristicWrite(gatt, characteristic, status); + //TODO: Implement (if necessary) + } + + public XWatchActivitySample createActivitySample(Device device, User user, int timestampInSeconds, SampleProvider provider) { + XWatchActivitySample sample = new XWatchActivitySample(); + sample.setDevice(device); + sample.setUser(user); + sample.setTimestamp(timestampInSeconds); + sample.setProvider(provider); + + return sample; + } + + private void handleDeviceInfo(byte[] value, int status) { + if (status == BluetoothGatt.GATT_SUCCESS) { + mDeviceInfo = new DeviceInfo(value); + LOG.warn("Device info: " + mDeviceInfo); + versionCmd.hwVersion = "1.0"; + versionCmd.fwVersion = "1.0"; + handleGBDeviceEvent(versionCmd); + } + } + + @Override + public void onSendConfiguration(String config) { + // nothing yet + } + + @Override + public void onTestNewFunction() { + //Not supported + } + + @Override + public void onSendWeather(WeatherSpec weatherSpec) { + //Not supported + } + + private void handleSummarizedData(byte[] value) { + int daysIntTotal; + int daysIntPart; + + if (value.length != 16) { + LOG.warn("GOT UNEXPECTED SENSOR DATA WITH LENGTH: " + value.length); + for (byte b : value) { + LOG.warn("DATA: " + String.format("0x%4x", b)); + } + } else { + daysIntPart = (value[1] & 255) << 24; + daysIntTotal = daysIntPart; + daysIntPart = (value[2] & 255) << 16; + daysIntTotal += daysIntPart; + daysIntPart = (value[3] & 255) << 8; + daysIntTotal += daysIntPart; + daysIntPart = (value[4] & 255); + daysIntTotal += daysIntPart; + + dayToFetch = 0; + maxDayToFetch = (byte) Integer.bitCount(daysIntTotal); + + try { + requestDetailedData(builder); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } + } + } + + private void handleDetailedData(byte[] value) { + int category, intensity, steps = 0; + + if (value.length != 16) { + LOG.warn("GOT UNEXPECTED SENSOR DATA WITH LENGTH: " + value.length); + for (byte b : value) { + LOG.warn("DATA: " + String.format("0x%4x", b)); + } + } else { + try (DBHandler dbHandler = GBApplication.acquireDB()) { + XWatchSampleProvider provider = new XWatchSampleProvider(getDevice(), dbHandler.getDaoSession()); + User user = DBHelper.getUser(dbHandler.getDaoSession()); + Device device = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()); + int timestampInSeconds = 0; + + timestampInSeconds = getTimestampFromData( + value[2], + value[3], + value[4], + value[5] + ); + + category = ActivityKind.TYPE_ACTIVITY; + intensity = (value[7] & 255) + ((value[8] & 255) << 8); + steps = (value[9] & 255) + ((value[10] & 255) << 8); + + XWatchActivitySample sample = createActivitySample(device, user, timestampInSeconds, provider); + sample.setRawIntensity(intensity); + sample.setSteps(steps); + sample.setRawKind(category); + + if (LOG.isDebugEnabled()) { + LOG.debug("sample: " + sample); + } + + provider.addGBActivitySample(sample); + + if (value[5] == 95) { + dayToFetch++; + if(dayToFetch <= maxDayToFetch) { + try { + builder = performInitialized("fetchActivityData"); + requestDetailedData(builder); + performConnected(builder.getTransaction()); + } catch (IOException e) { + GB.toast(getContext(), "Error fetching activity data: " + e.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR); + } + } + } + } catch (Exception ex) { + GB.toast(getContext(), ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex); + } + } + } + + private void handleButtonPressed(byte[] value) { + long currentTimestamp = System.currentTimeMillis(); + + AudioManager audioManager = (AudioManager)getContext().getSystemService(Context.AUDIO_SERVICE); + if(audioManager.isWiredHeadsetOn()) { + if (currentTimestamp - lastButtonTimestamp < 1000) { + if (audioManager.isMusicActive()) { + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); + } else { + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT)); + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); + } + } else { + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); + audioManager.dispatchMediaKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); + } + } + + lastButtonTimestamp = currentTimestamp; + } + + @Override + public void onAppConfiguration(UUID appUuid, String config, Integer id) { + //Not supported + } + + @Override + public void onSetHeartRateMeasurementInterval(int seconds) { + //Not supported + } + + private void requestSummarizedData(TransactionBuilder builder) { + byte[] fetch = new byte[]{(byte) XWatchService.COMMAND_ACTIVITY_TOTALS, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0}; + + fetch = XWatchSupport.crcChecksum(fetch); + builder.write(getCharacteristic(XWatchService.UUID_WRITE), fetch); + } + + private void requestDetailedData(TransactionBuilder builder) { + byte[] fetch = new byte[]{(byte) XWatchService.COMMAND_ACTIVITY_DATA, + (byte) dayToFetch, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0, + (byte) 0}; + + fetch = XWatchSupport.crcChecksum(fetch); + builder.write(getCharacteristic(XWatchService.UUID_WRITE), fetch); + } + + private int getTimestampFromData(byte year, byte month, byte day, byte hoursminutes) { + int timestamp = 0; + int yearInt, monthInt, dayInt, hoursMinutesInt = 0; + int hours, minutes = 0; + + yearInt = Integer.valueOf(String.format("%02x", year), 16); + monthInt = Integer.valueOf(String.format("%02x", month), 16); + dayInt = Integer.valueOf(String.format("%02x", day), 16); + hoursMinutesInt = Integer.valueOf(String.format("%02x", hoursminutes), 16); + + minutes = hoursMinutesInt % 4; + hours = (hoursMinutesInt - minutes) / 4; + minutes = minutes * 15; + + GregorianCalendar cal = new GregorianCalendar( + 2000 + yearInt, + monthInt - 1, + dayInt, + hours, + minutes + ); + + timestamp = (int)(cal.getTimeInMillis() / 1000); + + return timestamp; + } +} From c1de67744829302c93f38b5d6208629b6dd52d76 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 16 Sep 2018 13:58:01 +0200 Subject: [PATCH 33/65] Remove redundant null checks --- .../devices/pebble/PebbleProtocol.java | 158 ++++++++---------- 1 file changed, 70 insertions(+), 88 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java index bcdebe2c6..a9ff4a8ad 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleProtocol.java @@ -636,14 +636,12 @@ public class PebbleProtocol extends GBDeviceProtocol { byte attributes_count = 0; int length = 21 + 10 + actions_length; - if (parts != null) { - for (String s : parts) { - if (s == null || s.equals("")) { - continue; - } - attributes_count++; - length += (3 + s.getBytes().length); + for (String s : parts) { + if (s == null || s.equals("")) { + continue; } + attributes_count++; + length += (3 + s.getBytes().length); } // Encode Prefix @@ -667,19 +665,17 @@ public class PebbleProtocol extends GBDeviceProtocol { byte attribute_id = 0; // Encode Pascal-Style Strings - if (parts != null) { - for (String s : parts) { - attribute_id++; - if (s == null || s.equals("")) { - continue; - } - - int partlength = s.getBytes().length; - if (partlength > 255) partlength = 255; - buf.put(attribute_id); - buf.putShort((short) partlength); - buf.put(s.getBytes(), 0, partlength); + for (String s : parts) { + attribute_id++; + if (s == null || s.equals("")) { + continue; } + + int partlength = s.getBytes().length; + if (partlength > 255) partlength = 255; + buf.put(attribute_id); + buf.putShort((short) partlength); + buf.put(s.getBytes(), 0, partlength); } @@ -981,14 +977,12 @@ public class PebbleProtocol extends GBDeviceProtocol { byte attributes_count = 2; // icon short attributes_length = (short) (11 + actions_length); - if (parts != null) { - for (String s : parts) { - if (s == null || s.equals("")) { - continue; - } - attributes_count++; - attributes_length += (3 + s.getBytes().length); + for (String s : parts) { + if (s == null || s.equals("")) { + continue; } + attributes_count++; + attributes_length += (3 + s.getBytes().length); } short pin_length = (short) (NOTIFICATION_PIN_LENGTH + attributes_length); @@ -1013,19 +1007,17 @@ public class PebbleProtocol extends GBDeviceProtocol { byte attribute_id = 0; // Encode Pascal-Style Strings - if (parts != null) { - for (String s : parts) { - attribute_id++; - if (s == null || s.equals("")) { - continue; - } - - int partlength = s.getBytes().length; - if (partlength > 512) partlength = 512; - buf.put(attribute_id); - buf.putShort((short) partlength); - buf.put(s.getBytes(), 0, partlength); + for (String s : parts) { + attribute_id++; + if (s == null || s.equals("")) { + continue; } + + int partlength = s.getBytes().length; + if (partlength > 512) partlength = 512; + buf.put(attribute_id); + buf.putShort((short) partlength); + buf.put(s.getBytes(), 0, partlength); } buf.put((byte) 4); // icon @@ -1116,14 +1108,12 @@ public class PebbleProtocol extends GBDeviceProtocol { byte attributes_count = 3; short attributes_length = (short) (21 + actions_length); - if (parts != null) { - for (String s : parts) { - if (s == null || s.equals("")) { - continue; - } - attributes_count++; - attributes_length += (3 + s.getBytes().length); + for (String s : parts) { + if (s == null || s.equals("")) { + continue; } + attributes_count++; + attributes_length += (3 + s.getBytes().length); } UUID uuid = UUID.fromString("61b22bc8-1e29-460d-a236-3fe409a43901"); @@ -1150,27 +1140,25 @@ public class PebbleProtocol extends GBDeviceProtocol { byte attribute_id = 0; // Encode Pascal-Style Strings - if (parts != null) { - for (String s : parts) { - attribute_id++; - if (s == null || s.equals("")) { - continue; - } - - int partlength = s.getBytes().length; - if (partlength > 512) partlength = 512; - if (attribute_id == 4) { - buf.put((byte) 11); - } else if (attribute_id == 5) { - buf.put((byte) 25); - } else if (attribute_id == 6) { - buf.put((byte) 26); - } else { - buf.put(attribute_id); - } - buf.putShort((short) partlength); - buf.put(s.getBytes(), 0, partlength); + for (String s : parts) { + attribute_id++; + if (s == null || s.equals("")) { + continue; } + + int partlength = s.getBytes().length; + if (partlength > 512) partlength = 512; + if (attribute_id == 4) { + buf.put((byte) 11); + } else if (attribute_id == 5) { + buf.put((byte) 25); + } else if (attribute_id == 6) { + buf.put((byte) 26); + } else { + buf.put(attribute_id); + } + buf.putShort((short) partlength); + buf.put(s.getBytes(), 0, partlength); } buf.put((byte) 4); // icon @@ -1254,13 +1242,11 @@ public class PebbleProtocol extends GBDeviceProtocol { // Calculate length first short attributes_length = 0; - if (parts != null) { - for (String s : parts) { - if (s == null || s.equals("")) { - continue; - } - attributes_length += (2 + s.getBytes().length); + for (String s : parts) { + if (s == null || s.equals("")) { + continue; } + attributes_length += (2 + s.getBytes().length); } short pin_length = (short) (WEATHER_FORECAST_LENGTH + attributes_length); @@ -1280,17 +1266,15 @@ public class PebbleProtocol extends GBDeviceProtocol { buf.putShort(attributes_length); // Encode Pascal-Style Strings - if (parts != null) { - for (String s : parts) { - if (s == null || s.equals("")) { - continue; - } - - int partlength = s.getBytes().length; - if (partlength > 512) partlength = 512; - buf.putShort((short) partlength); - buf.put(s.getBytes(), 0, partlength); + for (String s : parts) { + if (s == null || s.equals("")) { + continue; } + + int partlength = s.getBytes().length; + if (partlength > 512) partlength = 512; + buf.putShort((short) partlength); + buf.put(s.getBytes(), 0, partlength); } return encodeBlobdb(UUID_LOCATION, BLOBDB_INSERT, BLOBDB_WEATHER, buf.array()); @@ -1434,14 +1418,12 @@ public class PebbleProtocol extends GBDeviceProtocol { } else { // Calculate length first int length = LENGTH_PREFIX + 9; - if (parts != null) { - for (String s : parts) { - if (s == null || s.equals("")) { - length++; // encode null or empty strings as 0x00 later - continue; - } - length += (1 + s.getBytes().length); + for (String s : parts) { + if (s == null || s.equals("")) { + length++; // encode null or empty strings as 0x00 later + continue; } + length += (1 + s.getBytes().length); } // Encode Prefix From 8c1a1861e49fb032a3f924f9bf29579f48c700d8 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 16 Sep 2018 13:59:16 +0200 Subject: [PATCH 34/65] Fix some static analysis warnings --- .../service/btle/profiles/heartrate/HeartRateProfile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/heartrate/HeartRateProfile.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/heartrate/HeartRateProfile.java index 841c09603..9b199ad37 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/heartrate/HeartRateProfile.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/profiles/heartrate/HeartRateProfile.java @@ -71,7 +71,7 @@ public class HeartRateProfile extends Abstr format = BluetoothGattCharacteristic.FORMAT_UINT8; } final int heartRate = characteristic.getIntValue(format, 1); - LOG.info("Heart rate: " + heartRate, Toast.LENGTH_LONG, GB.INFO); + LOG.info("Heart rate: " + heartRate); } return false; } From 2993260b526fac5da59c07bc5af59c555a1e11f3 Mon Sep 17 00:00:00 2001 From: Carsten Pfeiffer Date: Sun, 16 Sep 2018 15:59:55 +0200 Subject: [PATCH 35/65] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 25 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 25 +++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..921bd9cc4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,25 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +#### Before reporting a bug, please confirm the following: +- [ ] I have read the [wiki](https://github.com/Freeyourgadget/Gadgetbridge/wiki), and I didn't find a solution to my problem / an answer to my question. +- [ ] I have searched the [issues](https://github.com/Freeyourgadget/Gadgetbridge/issues), and I didn't find a solution to my problem / an answer to my question. +- [ ] If you upload an image or other content, please make sure you have read and understood the [github policies and terms of services](https://help.github.com/articles/github-terms-of-service/#1-responsibility-for-user-generated-content) + +#### Your issue is: +*If possible, please attach [logs](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Log-Files)! that might help identifying the problem.* + +#### Your wearable device is: + +*Please specify model and firmware version if possible* + +#### Your android version is: + +#### Your Gadgetbridge version is: + + + +*New issues about already solved/documented topics could be closed without further comments. Same for too generic or incomplete reports.* diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..0b8a613e6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,25 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +#### Before requesting a new feature, please confirm the following: +- [ ] I have read the [wiki](https://github.com/Freeyourgadget/Gadgetbridge/wiki), and I didn't find a solution to my problem / an answer to my question. +- [ ] I have searched the [issues](https://github.com/Freeyourgadget/Gadgetbridge/issues), and I didn't find a solution to my problem / an answer to my question. +- [ ] If you upload an image or other content, please make sure you have read and understood the [github policies and terms of services](https://help.github.com/articles/github-terms-of-service/#1-responsibility-for-user-generated-content) + +#### Your issue is: +*If applicable, please attach [logs](https://github.com/Freeyourgadget/Gadgetbridge/wiki/Log-Files)* + +#### Your wearable device is: + +*Please specify model and firmware version if possible* + +#### Your android version is: + +#### Your Gadgetbridge version is: + + + +*New requests about already solved/documented topics could be closed without further comments. Same for too generic or incomplete reports.* From 62e080d5ac22f3d6f7fbedafe478211c3383cc0a Mon Sep 17 00:00:00 2001 From: Pavel Date: Sun, 16 Sep 2018 20:35:28 +0300 Subject: [PATCH 36/65] Update LiveActivityFragment.java I'm sorry, I wanted to add entry if > min HR --- .../gadgetbridge/activities/charts/LiveActivityFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index 6c66f3906..c2ac03045 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -244,7 +244,6 @@ public class LiveActivityFragment extends AbstractChartFragment { if (hr > HeartRateUtils.getInstance().getMinHeartRate()) { mHeartRateSet.addEntry(new Entry(timestamp, hr)); } - mHeartRateSet.addEntry(new Entry(timestamp, hr)); } private boolean addHistoryDataSet(boolean force) { From 934f36f45aea864f15181afc963ead4310db8de9 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 16 Sep 2018 20:49:00 +0200 Subject: [PATCH 37/65] Use ActivityUser.defaultUserStepsGoal instead of hardcoded values ActivityUser has room for improvement, though. --- .../gadgetbridge/activities/charts/LiveActivityFragment.java | 2 +- .../gadgetbridge/activities/charts/WeekStepsChartFragment.java | 2 +- .../gadgetbridge/service/devices/huami/HuamiSupport.java | 2 +- .../gadgetbridge/service/devices/miband/MiBandSupport.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index c2ac03045..0d8a7dcf2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -442,7 +442,7 @@ public class LiveActivityFragment extends AbstractChartFragment { } private BarDataSet setupTotalStepsChart(CustomBarChart chart, BarEntry entry, String label) { - mTotalStepsChart.getAxisLeft().addLimitLine(new LimitLine(GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, 10000), "ss")); // TODO: use daily goal - already reached steps + mTotalStepsChart.getAxisLeft().addLimitLine(new LimitLine(GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal), "ss")); // TODO: use daily goal - already reached steps mTotalStepsChart.getAxisLeft().setAxisMinimum(0); mTotalStepsChart.setAutoScaleMinMaxEnabled(true); return setupCommonChart(chart, entry, label); // at the moment, these look the same diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java index 2291e3665..e70490a0a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/WeekStepsChartFragment.java @@ -40,7 +40,7 @@ public class WeekStepsChartFragment extends AbstractWeekChartFragment { @Override int getGoal() { - return GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, 10000); + return GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal); } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index d3d305ea3..a90a174e8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -377,7 +377,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { LOG.info("Attempting to set Fitness Goal..."); BluetoothGattCharacteristic characteristic = getCharacteristic(HuamiService.UUID_CHARACTERISTIC_8_USER_SETTINGS); if (characteristic != null) { - int fitnessGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, 10000); + int fitnessGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal); byte[] bytes = ArrayUtils.addAll( HuamiService.COMMAND_SET_FITNESS_GOAL_START, BLETypeConversions.fromUint16(fitnessGoal)); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java index 877debd5f..549cbb9d5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband/MiBandSupport.java @@ -389,7 +389,7 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport { LOG.info("Attempting to set Fitness Goal..."); BluetoothGattCharacteristic characteristic = getCharacteristic(MiBandService.UUID_CHARACTERISTIC_CONTROL_POINT); if (characteristic != null) { - int fitnessGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, 10000); + int fitnessGoal = GBApplication.getPrefs().getInt(ActivityUser.PREF_USER_STEPS_GOAL, ActivityUser.defaultUserStepsGoal); transaction.write(characteristic, new byte[]{ MiBandService.COMMAND_SET_FITNESS_GOAL, 0, From 87c09b038b485d23382f3857680f17df91cbc72b Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Mon, 10 Sep 2018 22:38:51 +0000 Subject: [PATCH 38/65] Translated using Weblate (Hebrew) Currently translated at 100.0% (577 of 577 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 3329538b2..be7550450 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -641,4 +641,10 @@ יש להפעיל אפשרות זו כדי לתמוך בערבית מחוברת תמיכה בטקסט מימין לשמאל הגדרות שפה ואיזור - +מחסור בשינה: %1$s + עודף שינה: %1$s + מחסור בצעדים: %1$d + עודף צעדים: %1$d + אין נתונים + + From 1fe8842743afb1f27277bf3f493de2221f5ef486 Mon Sep 17 00:00:00 2001 From: postsorino Date: Fri, 14 Sep 2018 05:02:49 +0000 Subject: [PATCH 39/65] Translated using Weblate (Greek) Currently translated at 97.2% (561 of 577 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/el/ --- app/src/main/res/values-el/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 741a297ee..11db0ccb0 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -683,4 +683,6 @@ Συχνότητα FM Μη έγκυρη συχνότητα Παρακαλώ εισάγετε συχνότητα από 87.5 έως 108.0 - +"Από δεξιά προς αριστερά " + "Ενεργοποιήστε αυτή την επιλογή αν η συσκευή σας δεν έχει υποστήριξη για γλώσσες που γράφονται από δεξιά " + From b9944ec0282eb0abd03be5e4e4b5c78dbc951ade Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 17 Sep 2018 00:11:32 +0200 Subject: [PATCH 40/65] Changelog for 0.30.0 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 958a74253..15353a0cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ ### Changelog +#### Version 0.30.0 +* Amazfit Bip + Mi Band 3: Support for right to left display (configurable) (#976) +* Add Arabic, Bengali Farsi, Persian, Scandinavian transliteration +* Add support for some Roidmi FM receivers +* Mi Band 3: Allow enabling the "Workout" menu item +* Mi Band 3: Support for night mode configuration +* Huami devices: fix seldom activity/sports synchronization problem (#1264) +* Preferences: Make minimum heart rate configurable (lower values will be disregarded) +* Preferences: Group language settings +* Preferences: Configure minimum time between notifications +* Attempt to fix BLE connection issues on Samsung S devices +* Week sleep and steps charts: display balance (actual value vs. desired value) +* Live Activity: show current/maximum heart rate, display minute steps and total steps and more improvements +* Live Activity: fix discrepancy between number of steps in Gadgetbridge and wearable device +* Fix missing caller ID for incoming calls on Android 9 +* Support for easy sharing of log files via the Debug screen +* Misc small bugfixes + #### Version 0.29.1 * Mi Band 3: Support setting language to to German, Italian, French, Polish, Japanese, Korean (read wiki) * Mi Band 3: Support flashing latest RES files From 46aec12aa6ab141949bf6ee31eda70cbe34e51f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Mon, 17 Sep 2018 01:15:18 +0200 Subject: [PATCH 41/65] News strings reworked --- app/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7942f6cf4..91dec54a0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -107,9 +107,9 @@ Enable this if your device has no support for your language\'s font Right-To-Left - Enable this if your device has no support in right-to-left languages + Enable this if your device can not show right-to-left languages Right-To-Left Max Line Length - When Right-To-Left is enable, the text is separated to lines. Change this value if the lines are to long/short. + Lengthens or shortens the lines Right-To-Left text is seperated into Always When screen is off From a55c3d72205d90d437b45a65bc9d6ffa4586161c Mon Sep 17 00:00:00 2001 From: Newline Bot Date: Mon, 17 Sep 2018 18:28:56 +0200 Subject: [PATCH 42/65] Replace CRLF with LF (no content changes) --- .../devices/xwatch/XWatchCoordinator.java | 232 +++++++++--------- .../devices/xwatch/XWatchService.java | 68 ++--- 2 files changed, 150 insertions(+), 150 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchCoordinator.java index 207cc3fb2..821206651 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchCoordinator.java @@ -15,124 +15,124 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -package nodomain.freeyourgadget.gadgetbridge.devices.xwatch; - -import android.app.Activity; -import android.content.Context; -import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import nodomain.freeyourgadget.gadgetbridge.GBException; -import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; -import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; -import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; -import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; -import nodomain.freeyourgadget.gadgetbridge.entities.Device; -import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; -import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; -import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; -import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; - -public class XWatchCoordinator extends AbstractDeviceCoordinator { - @NonNull - @Override - public DeviceType getSupportedType(GBDeviceCandidate candidate) { - String name = candidate.getDevice().getName(); - if (name != null && name.startsWith("XWatch")) { - return DeviceType.XWATCH; - } - return DeviceType.UNKNOWN; - } - - @Override - protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { - - } - - @Override - public DeviceType getDeviceType() { - return DeviceType.XWATCH; - } - - @Nullable - @Override - public Class getPairingActivity() { - return null; - } - - @Override - public boolean supportsActivityDataFetching() { - return true; - } - - @Override - public boolean supportsActivityTracking() { - return true; - } - - @Override - public SampleProvider getSampleProvider(GBDevice device, DaoSession session) { - return new XWatchSampleProvider(device, session); - } - - @Override - public InstallHandler findInstallHandler(Uri uri, Context context) { - return null; - } - - @Override - public boolean supportsScreenshots() { - return false; - } - - @Override - public boolean supportsAlarmConfiguration() { - return true; - } - - @Override - public boolean supportsSmartWakeup(GBDevice device) { - return false; - } - - @Override - public boolean supportsHeartRateMeasurement(GBDevice device) { - return false; - } - - @Override - public String getManufacturer() { - return "Generic"; - } - - @Override - public boolean supportsAppsManagement() { - return false; - } - - @Override - public Class getAppsManagementActivity() { - return null; - } - - @Override - public boolean supportsCalendarEvents() { - return false; - } - - @Override - public boolean supportsRealtimeData() { - return false; - } - - @Override - public boolean supportsWeather() { - return false; - } +package nodomain.freeyourgadget.gadgetbridge.devices.xwatch; + +import android.app.Activity; +import android.content.Context; +import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import nodomain.freeyourgadget.gadgetbridge.GBException; +import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; +import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; +import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; +import nodomain.freeyourgadget.gadgetbridge.entities.Device; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate; +import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; + +public class XWatchCoordinator extends AbstractDeviceCoordinator { + @NonNull + @Override + public DeviceType getSupportedType(GBDeviceCandidate candidate) { + String name = candidate.getDevice().getName(); + if (name != null && name.startsWith("XWatch")) { + return DeviceType.XWATCH; + } + return DeviceType.UNKNOWN; + } + + @Override + protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { + + } + + @Override + public DeviceType getDeviceType() { + return DeviceType.XWATCH; + } + + @Nullable + @Override + public Class getPairingActivity() { + return null; + } + + @Override + public boolean supportsActivityDataFetching() { + return true; + } + + @Override + public boolean supportsActivityTracking() { + return true; + } + + @Override + public SampleProvider getSampleProvider(GBDevice device, DaoSession session) { + return new XWatchSampleProvider(device, session); + } + + @Override + public InstallHandler findInstallHandler(Uri uri, Context context) { + return null; + } + + @Override + public boolean supportsScreenshots() { + return false; + } + + @Override + public boolean supportsAlarmConfiguration() { + return true; + } + + @Override + public boolean supportsSmartWakeup(GBDevice device) { + return false; + } + + @Override + public boolean supportsHeartRateMeasurement(GBDevice device) { + return false; + } + + @Override + public String getManufacturer() { + return "Generic"; + } + + @Override + public boolean supportsAppsManagement() { + return false; + } + + @Override + public Class getAppsManagementActivity() { + return null; + } + + @Override + public boolean supportsCalendarEvents() { + return false; + } + + @Override + public boolean supportsRealtimeData() { + return false; + } + + @Override + public boolean supportsWeather() { + return false; + } @Override public boolean supportsFindDevice() { return true; } -} +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchService.java index aafcde504..63deb4b46 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/xwatch/XWatchService.java @@ -14,37 +14,37 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -package nodomain.freeyourgadget.gadgetbridge.devices.xwatch; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class XWatchService { - public static final UUID UUID_NOTIFY = UUID.fromString("0000fff7-0000-1000-8000-00805f9b34fb"); - public static final UUID UUID_SERVICE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb"); - public static final UUID UUID_WRITE = UUID.fromString("0000fff6-0000-1000-8000-00805f9b34fb"); - - public static final byte COMMAND_CONNECTED = 0x01; - public static final byte COMMAND_ACTION_BUTTON = 0x4c; - public static final byte COMMAND_ACTIVITY_DATA = 0x43; - public static final byte COMMAND_ACTIVITY_TOTALS = 0x46; - - private static final Map XWATCH_DEBUG; - - static { - XWATCH_DEBUG = new HashMap<>(); - - XWATCH_DEBUG.put(UUID_NOTIFY, "Read data"); - XWATCH_DEBUG.put(UUID_WRITE, "Write data"); - XWATCH_DEBUG.put(UUID_SERVICE, "Get service"); - } - - public static String lookup(UUID uuid, String fallback) { - String name = XWATCH_DEBUG.get(uuid); - if (name == null) { - name = fallback; - } - return name; - } -} +package nodomain.freeyourgadget.gadgetbridge.devices.xwatch; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class XWatchService { + public static final UUID UUID_NOTIFY = UUID.fromString("0000fff7-0000-1000-8000-00805f9b34fb"); + public static final UUID UUID_SERVICE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb"); + public static final UUID UUID_WRITE = UUID.fromString("0000fff6-0000-1000-8000-00805f9b34fb"); + + public static final byte COMMAND_CONNECTED = 0x01; + public static final byte COMMAND_ACTION_BUTTON = 0x4c; + public static final byte COMMAND_ACTIVITY_DATA = 0x43; + public static final byte COMMAND_ACTIVITY_TOTALS = 0x46; + + private static final Map XWATCH_DEBUG; + + static { + XWATCH_DEBUG = new HashMap<>(); + + XWATCH_DEBUG.put(UUID_NOTIFY, "Read data"); + XWATCH_DEBUG.put(UUID_WRITE, "Write data"); + XWATCH_DEBUG.put(UUID_SERVICE, "Get service"); + } + + public static String lookup(UUID uuid, String fallback) { + String name = XWATCH_DEBUG.get(uuid); + if (name == null) { + name = fallback; + } + return name; + } +} From cfddba0e4d762127c03538e01b88aeab652f060d Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 17 Sep 2018 22:11:15 +0200 Subject: [PATCH 43/65] Remove unused field and redundant casts --- .../activities/charts/LiveActivityFragment.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index 0d8a7dcf2..ded591e60 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -85,7 +85,6 @@ public class LiveActivityFragment extends AbstractChartFragment { private final Steps mSteps = new Steps(); private ScheduledExecutorService pulseScheduler; private int maxStepsResetCounter; - private List heartRateValues; private LineDataSet mHeartRateSet; private int mHeartRate; private int mMaxHeartRate = 0; @@ -266,14 +265,13 @@ public class LiveActivityFragment extends AbstractChartFragment { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { IntentFilter filterLocal = new IntentFilter(); filterLocal.addAction(DeviceService.ACTION_REALTIME_SAMPLES); - heartRateValues = new ArrayList<>(); tsTranslation = new TimestampTranslation(); View rootView = inflater.inflate(R.layout.fragment_live_activity, container, false); - mStepsPerMinuteCurrentChart = (CustomBarChart) rootView.findViewById(R.id.livechart_steps_per_minute_current); - mTotalStepsChart = (CustomBarChart) rootView.findViewById(R.id.livechart_steps_total); - mStepsPerMinuteHistoryChart = (BarLineChartBase) rootView.findViewById(R.id.livechart_steps_per_minute_history); + mStepsPerMinuteCurrentChart = rootView.findViewById(R.id.livechart_steps_per_minute_current); + mTotalStepsChart = rootView.findViewById(R.id.livechart_steps_total); + mStepsPerMinuteHistoryChart = rootView.findViewById(R.id.livechart_steps_per_minute_history); totalStepsEntry = new BarEntry(1, 0); stepsPerMinuteEntry = new BarEntry(1, 0); From d3fd203c6c3c7752fa8d0e15f515f1df7a86e46a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 17 Sep 2018 22:28:13 +0200 Subject: [PATCH 44/65] Avoid possible NPE --- .../freeyourgadget/gadgetbridge/util/TimePreference.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/TimePreference.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/TimePreference.java index 043cc4697..f549963f3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/TimePreference.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/TimePreference.java @@ -85,7 +85,11 @@ public class TimePreference extends DialogPreference { time = getPersistedString(defaultValue.toString()); } } else { - time = defaultValue.toString(); + if (defaultValue != null) { + time = defaultValue.toString(); + } else { + time = "00:00"; + } } String[] pieces = time.split(":"); From 6d4d92fd8828290d8b1521c28d9d448a7528480b Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 17 Sep 2018 23:01:01 +0200 Subject: [PATCH 45/65] Live Activity: don't enable notifications every second This caused the BLE queue to fill up more and more. --- .../service/devices/huami/HuamiSupport.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index a90a174e8..aa3fafceb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -179,6 +179,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { private boolean isMusicAppStarted = false; private MusicSpec bufferMusicSpec = null; private MusicStateSpec bufferMusicStateSpec = null; + private boolean heartRateNotifyEnabled; public HuamiSupport() { this(LOG); @@ -207,6 +208,7 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { @Override protected TransactionBuilder initializeDevice(TransactionBuilder builder) { try { + heartRateNotifyEnabled = false; boolean authenticate = needsAuth; needsAuth = false; byte authFlags = HuamiService.AUTH_BYTE; @@ -871,9 +873,12 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { } try { TransactionBuilder builder = performInitialized("Enable realtime heart rate measurement"); - BluetoothGattCharacteristic heartrateCharacteristic = getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT); - if (heartrateCharacteristic != null) { - builder.notify(heartrateCharacteristic, enable); + if (heartRateNotifyEnabled != enable) { + BluetoothGattCharacteristic heartrateCharacteristic = getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT); + if (heartrateCharacteristic != null) { + builder.notify(heartrateCharacteristic, enable); + heartRateNotifyEnabled = enable; + } } if (enable) { builder.write(characteristicHRControlPoint, stopHeartMeasurementManual); From 6ea9cc29bd817b5b6e92d714fd551b044c616700 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 17 Sep 2018 23:06:04 +0200 Subject: [PATCH 46/65] Updated changelog for 0.30.0 release --- CHANGELOG.md | 2 +- app/src/main/res/xml/changelog_master.xml | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15353a0cb..41bb28a34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ * Mi Band 3: Support for night mode configuration * Huami devices: fix seldom activity/sports synchronization problem (#1264) * Preferences: Make minimum heart rate configurable (lower values will be disregarded) -* Preferences: Group language settings * Preferences: Configure minimum time between notifications +* Preferences: Group language settings * Attempt to fix BLE connection issues on Samsung S devices * Week sleep and steps charts: display balance (actual value vs. desired value) * Live Activity: show current/maximum heart rate, display minute steps and total steps and more improvements diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml index 17e67ec87..6b627f792 100644 --- a/app/src/main/res/xml/changelog_master.xml +++ b/app/src/main/res/xml/changelog_master.xml @@ -1,5 +1,23 @@ + + Amazfit Bip + Mi Band 3: Support for right to left display (configurable) (#976) + Add Arabic, Bengali Farsi, Persian, Scandinavian transliteration + Add support for some Roidmi FM receivers + Mi Band 3: Allow enabling the "Workout" menu item + Mi Band 3: Support for night mode configuration + Huami devices: fix seldom activity/sports synchronization problem (#1264) + Preferences: Make minimum heart rate configurable (lower values will be disregarded) + Preferences: Configure minimum time between notifications + Preferences: Group language settings + Attempt to fix BLE connection issues on Samsung S devices + Week sleep and steps charts: display balance (actual value vs. desired value) + Live Activity: show current/maximum heart rate, display minute steps and total steps and more improvements + Live Activity: fix discrepancy between number of steps in Gadgetbridge and wearable device + Fix missing caller ID for incoming calls on Android 9 + Support for easy sharing of log files via the Debug screen + Misc small bugfixes + Mi Band 3: Support setting language to to German, Italian, French, Polish, Japanese, Korean (read wiki) Mi Band 3: Support flashing latest RES files From b1e122cbda25881b2afd53371ea60003e6785e52 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Mon, 17 Sep 2018 23:09:35 +0200 Subject: [PATCH 47/65] Bump version --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0392369ad..9ab629e63 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,8 +25,8 @@ android { targetSdkVersion 27 // Note: always bump BOTH versionCode and versionName! - versionName "0.29.1" - versionCode 137 + versionName "0.30.0" + versionCode 138 vectorDrawables.useSupportLibrary = true } buildTypes { From c6d8086d32d719af90ca0e8f563ad992594ffcb2 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Mon, 17 Sep 2018 23:11:42 +0200 Subject: [PATCH 48/65] add fastlane changelog --- .../metadata/android/en-US/changelogs/138.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 fastlane/metadata/android/en-US/changelogs/138.txt diff --git a/fastlane/metadata/android/en-US/changelogs/138.txt b/fastlane/metadata/android/en-US/changelogs/138.txt new file mode 100644 index 000000000..12e961dbe --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/138.txt @@ -0,0 +1,16 @@ +* Amazfit Bip + Mi Band 3: Support for right to left display (configurable) (#976) +* Add Arabic, Bengali Farsi, Persian, Scandinavian transliteration +* Add support for some Roidmi FM receivers +* Mi Band 3: Allow enabling the "Workout" menu item +* Mi Band 3: Support for night mode configuration +* Huami devices: fix seldom activity/sports synchronization problem (#1264) +* Preferences: Make minimum heart rate configurable (lower values will be disregarded) +* Preferences: Configure minimum time between notifications +* Preferences: Group language settings +* Attempt to fix BLE connection issues on Samsung S devices +* Week sleep and steps charts: display balance (actual value vs. desired value) +* Live Activity: show current/maximum heart rate, display minute steps and total steps and more improvements +* Live Activity: fix discrepancy between number of steps in Gadgetbridge and wearable device +* Fix missing caller ID for incoming calls on Android 9 +* Support for easy sharing of log files via the Debug screen +* Misc small bugfixes From 9e44a7ad6dde01b869231d89783b3176c96ead5d Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Thu, 20 Sep 2018 00:03:45 +0200 Subject: [PATCH 49/65] Add .gitattributes for consistent eol handling --- .gitattributes | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..42736eec0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.java text +*.gradle text +*.md text +*.properties text +*.xml text + +# Declare files that will always have CRLF line endings on checkout. +#*.sln text eol=crlf + +# Denote all files that are truly binary and should not be modified. +#*.png binary +#*.jpg binary From 60397c88c00d5d41286d756418eeb165f729bcde Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 23 Sep 2018 11:27:35 +0200 Subject: [PATCH 50/65] Avoid possible NPE --- .../freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java index 542e92fb8..7fe901f43 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java @@ -522,7 +522,9 @@ public final class BtLEQueue { private void checkWaitingCharacteristic(BluetoothGattCharacteristic characteristic, int status) { if (status != BluetoothGatt.GATT_SUCCESS) { - LOG.debug("failed btle action, aborting transaction: " + characteristic.getUuid() + getStatusString(status)); + if (characteristic != null) { + LOG.debug("failed btle action, aborting transaction: " + characteristic.getUuid() + getStatusString(status)); + } mAbortTransaction = true; } if (characteristic != null && BtLEQueue.this.mWaitCharacteristic != null && characteristic.getUuid().equals(BtLEQueue.this.mWaitCharacteristic.getUuid())) { From ab748eb5b19017019b9c4442897ee79a58104e67 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Mon, 17 Sep 2018 08:39:27 +0000 Subject: [PATCH 51/65] Translated using Weblate (Hebrew) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index be7550450..57a1987fa 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -647,4 +647,5 @@ עודף צעדים: %1$d אין נתונים + דופק נוכחי / מרבי: %1$d ‏/ %2$d From 73f0309c84a795d18c1ce7a3454770f94b96317d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Sun, 16 Sep 2018 23:02:11 +0000 Subject: [PATCH 52/65] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegian?= =?UTF-8?q?=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 99.1% (573 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 24773bcfe..fb3b128d5 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -675,4 +675,26 @@ FM-frekvens Ugyldig frekvens Skriv inn en frekvens mellom 87.5 og 108.0 +Høyre-til-venstre + Skru på dette hvis din enhet ikke har støtte for språk som vises fra høyre til venstre. + Maksimal linjelengde for høyre-til-venstre + Når høyre-til-venstre er påslått, deles teksten inn i linjer. Endre denne verdien hvis linjene er for lange/korte. + + %1$s batteri snart tomt + %1$s batteri snart tomt: %2$s + Søvnmangel: %1$s + Sovet for lenge: %1$s + Ikke nok steg: %1$d + For mange steg: %1$d + Nåværende / maksimal puls: %1$d /%2$d + Diagraminnstillinger + Makspuls + Minimumspuls + + Kontekstuell arabisk + Skru på dette for kontekstuell arabisk støtte + Høyre-til-venstre -støtte + Ingen data + + Språk og stedsinnstillinger From c168f24c2d1b0fc421bb6b821492994e9e2522c4 Mon Sep 17 00:00:00 2001 From: Full Name Date: Mon, 17 Sep 2018 16:31:43 +0000 Subject: [PATCH 53/65] Translated using Weblate (Czech) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/ --- app/src/main/res/values-cs/strings.xml | 160 +++++++++++++++++++++---- 1 file changed, 136 insertions(+), 24 deletions(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 2e6dd51a4..0bb4f73e7 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -5,7 +5,7 @@ Nastavení Ladění Ukončit - Načíst data + Synchronizovat Monitor spánku (alfa) Najít zařízení Pořídit snímek displeje @@ -44,31 +44,31 @@ Instalátor FW/App Instaluje firmvér %s do Mi Band místo stávajícího. - Instaluje firmvér %1$s a %2$s do Mi Band místo stávajícího. - Tento firmvér byl testován a je kompatibilní s Gadgetbridge. + Instaluje %1$s a %2$s firmvér, místo stávajícího. + Tento firmvér byl testován a je známa jeho kompatibilita s Gadgetbridge. Tento firmvér nebyl testován a nemusí být kompatibilní s Gadgetbridge. \n \nNedoporučujeme jej nahrávat do Mi Band! - Pokud budete prokračovat a vše bude fungovat běžně i potom, upozorněte vývojáře Gadgetbridge, aby označili tento firmvér: %s jako vyzkoušený + Chcete-li stále pokračovat a bude-li vše správně fungovat i po aktualizaci, oznamte vývojářům Gadgetbridge, aby označili tuto verzi firmvéru: %s jako funkční.. Nastavení - Základní nastavení - Připojit zařízení pokud je zapnutý BT + Obecná nastavení + Připojit Gadgetbridge k zařízení při zapnutí Bluetooth Spouštět automaticky Automatické znovupřipojení - Preferovaný přehrávač zvuků + Preferovaný přehrávač hudby Výchozí Datum a čas - Nastavit čas - Nastavit čas během připojení a při změně času v Androidu + Synchronizovat čas + Synchronizovat čas během připojení k zařízení a při změně času v Androidu Téma Světlé Tmavé Jazyk Skrýt notifikace Gadgetbridge Ikona ve stavové liště a notifikace na zamčeném displeji budou zobrazeny - Ikona ve stavové liště a notifikace na zamčeném displeji nebudou zobrazeny - Notifikace + Ikona ve stavové liště a notifikace na zamčeném displeji budou skryty + Upozornění Opakování Volání SMS @@ -77,7 +77,7 @@ Přístup k notifikacím Upozornění i při zapnuté obrazovce Nerušit - Neposílat nechtěné notifikace v režimu Nerušit + Neposílat nechtěná upozornění v režimu Nerušit Přepsání diakritiky Toto zapněte, pokud vaše zařízení nepodporuje písma pro vás jazyk Vždy @@ -217,7 +217,7 @@ Notifikace SMS Nastavení vibrací Obecné notifikace - Notifikace emailu + Upozornění emailu Notifikace volání Konverzace Navigace @@ -237,7 +237,7 @@ So Chytré buzení Nepodařilo se nastavit budík, zkuste to znovu! - Budík zaslán do zařízení! + Čas buzení odeslán do zařízení. Chybí data, provést stažení? Stahnout data %1$s z %2$s Cílový počet kroků na den @@ -279,7 +279,7 @@ Pokud není přenos dat potvrzen náramku, potom nebudou smazána. Užitečné pokud je GB používán dohromady s jinou aplikací. Zachová data o aktivitě v Mi Band i po synchronizaci. Užitečné pokud je GB používán dohromady s jinou aplikací. Použít režim z nízkým zpožděním pro aktualizace firmwaru - Může to pomoci u zařízení, kde aktualizace firmwaru selhala + Může to pomoci u zařízení, kde aktualizace firmwaru selhala. Historie kroků Aktuálně kroků/min Celkem kroků @@ -297,7 +297,7 @@ Budíky pro nadcházející události Použít sledování tepu pro zlepšení detekce spánku Časový posun zařízení v hodinách (pro zjišťování spánku směnařů) - Mi2: formát data + Formát data Čas Čas a dátum Zapnout displej při zvednutí @@ -350,7 +350,7 @@ Vibrace Párování Pebble - Dialog párování by se měl objevit na vašem zařízení s Androidem. Pokud se to nestane, zkontrolujte panel notifikací a potvrďte párování. Potom potvrďte párování na Pebble + Dialog párování by se měl objevit na vašem zařízení s Androidem. Pokud se to nestane, zkontrolujte panel notifikací a potvrďte párování. Poté potvrďte párování na Pebble. Ujistěte se, že tento skin je povolen v aplikaci pro oznámení počasí pro získávání informací v Pebble.\n\nNení třeba nic nastavovat.\n\nAplikaci pro počasí Pebble je možné povolit ve správě aplikací.\n\nPodporované ciferníky ukáží počasí automaticky. Zapnout párování BT Toto vypněte v případě problémů s připojením @@ -435,13 +435,13 @@ \nDĚLÁTE TO NA VLASTNÍ NEBEZPEČÍ! "Firmware Amazfit Bipu %1$s" Připojit - Chystáte se nainstalovat firmvér %s do vašeho Amazfit Cor. + Chystáte se nainstalovat firmvér %s do vašeho Amazfit Cor. +\n +\nProsím, ujistěte se, že jste nainstalovali soubor .fw a potom soubor .res. Vaše hodinky se po instalaci souboru .fw restartují. +\n +\nPoznámka: Nemusíte instalovat soubor .res, pokud je stejný jako nainstalován dříve. \n -\nProsím, ujistěte se, že jste nainstalovali soubor .fw a potom soubor .res. Vaše hodinky se po instalaci souboru .fw restartují. -\n -\nPoznámka: Nemusíte instalovat soubor .res, pokud je stejný jako nainstalován dříve. -\n -\n NETESTOVÁNO, MŮŽE UMRTVIT VAŠE ZAŘÍZENÍ, DĚLÁTE TO NA VLASTNÍ NEBEZPEČÍ! +\nPOKRAČUJTE NA VLASTNÍ NEBEZPEČÍ! Zapnout možnost potažení vlevo/vpravo v grafech aktivit Počasí @@ -473,7 +473,7 @@ Aktivity Webový pohled - Otevřít na telefonu + Otevřít na Android zařízení Ztlumit Znova @@ -532,4 +532,116 @@ Kompas Nastavení Alipay +Změnit barvu LED + Změnit FM frekvenci + Kalibrovat zařízení + + + Seznam všech zakázaných upozornění + Seznam všech povolených upozornění + + + Chystáte se nainstalovat firmvér %s do vašeho Mi Band 3. +\n +\nProsím, ujistěte se, že jste nainstalovali soubor .fw a potom soubor .res. Vaše hodinky se po instalaci souboru .fw restartují. +\n +\nPoznámka: Nemusíte instalovat soubor .res, pokud je stejný jako nainstalován dříve. +\n +\nNETESTOVÁNO, MŮŽE POŠKODIT VAŠE ZAŘÍZENÍ, POKRAČUJTE NA VLASTNÍ NEBEZPEČÍ! + Minimální doba mezi upozorněními + Zprava doleva + Povolte, podporuje-li vaše zařízení jazyky zprava doleva + Maximální délka řádku pro zprava doleva + Je-li zapnuta podpora pro zleva doprava, text je rozdělen do řádků. Změňte tuto hodnotu jsou-li řádky příliš dlouhé/krátké. + + ID115 nastavení + Orientace displeje + + Synchronizovat automaticky + Synchronizovat při odemčení obrazovky. Musí být nastaven zámek obrazovky! + Minimální doba mezi synchronizacemi + Synchronizovat každých %d minut + + Mi Band 2 nastavení + Mi Band 3 nastavení + Amazfit Cor nastavenís + Na šířku + Na výšku + Po zavibrování stiskněte tlačítko, nebo se zařízením zatřeste. + + %1$s nízký stav baterie + %1$s baterie vybitá: %2$s + Nedostatek spánku: %1$s + Příliš mnoho spánku: %1$s + Bez omezení + 5 vteřin + 10 vteřin + 20 vteřin + 30 vteřin + 1 minuta + 5 minut + 10 minut + 30 minut + + Příliš málo kroků: %1$d + Příliš mnoho kroků: %1$d + Aktuální / Maximální tepová frekvence: %1$d / %2$d + Spánek od %1$s do %2$s + Bez spánku + Odemčení obrazovky zařízení + Přejeďte prstem pro odemčení obrazovky zařízení + Noční režim + Nižší automatická intenzita displeje v noci + + Norsky Bokmål + Rusky + Německy + Italsky + Francouzky + Polsky + Korejsky + Japonsky + + Nastavení grafů + Maximální tepová frekvence + Minimální tepová frekvence + + Ok + + Při západu slunce + Záznamy aktivit + Běhací pás + Mi Band 3 + Q8 + MyKronoz ZeTime + ID115 + Watch 9 + Roidmi + Roidmi 3 + + Upozornění + Hudba + Více + + Minuty: + Hodiny: + Vteřiny: + Nastavit čas aktuálně zobrazený na zařízení. + Kalibrovat + Párování Watch 9 + Kalibrace Watch 9 + Kontextuální Arabština + Zapnout podporu pro kontextuální arabštinu + Podpora zprava doleva + Sdílet záznam + Prosím nezapomeňte, že ladící záznamy Gadgetbridge mohou obsahovat osobní informace, zahrnující například zdravotní data, identifikátory (MAC adresu), hudební preference a podobně. Tyto informace můžete vymazat před odesláním souboru do veřejného reportu. + Upozornění! + Žádná data + + Barva LED + + Frekvence FM + Neplatná frekvence + Nastavte frekvenci mezi 87.5 a 108.0 + Jazyk a místní nastavení From 4602e7a1db8a4bb3d6a27ab7eab944e9668ffb2a Mon Sep 17 00:00:00 2001 From: Full Name Date: Wed, 19 Sep 2018 18:41:31 +0000 Subject: [PATCH 54/65] Translated using Weblate (Czech) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/cs/ --- app/src/main/res/values-cs/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 0bb4f73e7..4e7a1d5ac 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -464,7 +464,7 @@ Každých 30 minut Jednou za hodinu - Export databáze selhal! Zkontrolujte svá nastavení. + Export databáze selhal! Zkontrolujte nastavení. Automaticky Zjednodušená Čínština Tradiční Čísština From aba21647f5a2fcff80c83106d8b74ceb7ec9211e Mon Sep 17 00:00:00 2001 From: postsorino Date: Wed, 19 Sep 2018 18:09:17 +0000 Subject: [PATCH 55/65] Translated using Weblate (Greek) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/el/ --- app/src/main/res/values-el/strings.xml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 11db0ccb0..e279ba533 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -685,4 +685,25 @@ Παρακαλώ εισάγετε συχνότητα από 87.5 έως 108.0 "Από δεξιά προς αριστερά " "Ενεργοποιήστε αυτή την επιλογή αν η συσκευή σας δεν έχει υποστήριξη για γλώσσες που γράφονται από δεξιά " - + Μέγιστο μήκος γραμμής στις γλώσσες που γράφονται από δεξιά + Όταν η γραφή από δεξιά είναι ενεργοποιημένη , το κείμενο χωρίζεται σε γραμμές. Αλλάξτε αυτή τη τιμή αν οι γραμμές είναι πολύ μακριές ή κοντές. + + %1$s χαμηλή μπαταρία + %1$s χαμηλή μπαταρία: %2$s +\n + Έλλειψη ύπνου: %1$s + Παραπάνω ύπνος: %1$s + Λιγότερα βήματα: %1$d + Περισσότερα βήματα: %1$d + Τωρινοί / Μέγιστοι παλμοί: %1$d / %2$d + "Ρυθμίσεις γραφήματος " + Μέγιστοι παλμοί + Ελάχιστοι παλμοί + + Συμφραζόμενα Αραβικά + Ενεργοποιήστε αυτή την επιλογή για υποστήριξη συμφραζόμενων Αραβικών + Υποστήριξη γλωσσών γραφής από τα δεξιά + Χωρίς δεδομένα + + Ρυθμίσεις γλώσσας και περιοχής + From 0ff52f8e7a49f0eb0fed90f04f476472c3b597c4 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Thu, 20 Sep 2018 04:05:45 +0000 Subject: [PATCH 56/65] Translated using Weblate (Hebrew) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 57a1987fa..2bef64896 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -633,9 +633,9 @@ דופק מזערי מימין לשמאל - הפעל אפשרות זו אם להתקן אין תמיכה בשפות הנכתבות מימין לשמאל + יש להפעיל אפשרות זו אם ההתקן לא יכול להציג שפות מימין לשמאל גודל שורה מרבי מימין לשמאל - כאשר התמיכה בכתיבה מימין לשמאל מופעלת, הטקסט מופרד לשורות. שנה ערך זה אם השורות קצרות/ארוכות מדי. + קיצור או הארכת השורות של טקסט מימין לשמאל ערבית מחוברת יש להפעיל אפשרות זו כדי לתמוך בערבית מחוברת From c7e2c16247f6e74e5ae8b6460f9d69ae3c854533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Thu, 20 Sep 2018 06:36:46 +0000 Subject: [PATCH 57/65] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegian?= =?UTF-8?q?=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 99.1% (573 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index fb3b128d5..600be9e8a 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -676,9 +676,9 @@ Ugyldig frekvens Skriv inn en frekvens mellom 87.5 og 108.0 Høyre-til-venstre - Skru på dette hvis din enhet ikke har støtte for språk som vises fra høyre til venstre. + Skru på dette hvis din enhet ikke kan vise høyre til venstre-språk. Maksimal linjelengde for høyre-til-venstre - Når høyre-til-venstre er påslått, deles teksten inn i linjer. Endre denne verdien hvis linjene er for lange/korte. + Strekker eller korter ned linjene høyre-til-venstre tekst inndeles i. %1$s batteri snart tomt %1$s batteri snart tomt: %2$s From ee1fa190d6420755a9a513690d3352660c9bfc4c Mon Sep 17 00:00:00 2001 From: Louis-Marie Croisez Date: Thu, 20 Sep 2018 12:59:47 +0000 Subject: [PATCH 58/65] Translated using Weblate (French) Currently translated at 94.4% (546 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/ --- app/src/main/res/values-fr/strings.xml | 74 ++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f58ee5174..b141f49fb 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -62,7 +62,7 @@ Par défaut Date et heure Synchroniser l\'heure - Synchroniser l\'heure à l\'appareil lors de la connexion et lorsque l\'heure ou le fuseau horaire changent sur Android + Synchroniser l\'heure sur l\'appareil lors de la connexion, et lorsque l\'heure ou le fuseau horaire changent sur Android Thème Clair Sombre @@ -79,7 +79,7 @@ Support des notifications génériques ...y compris quand l\'écran est allumé Ne Pas Déranger - Arrêter l’envoi des notifications non désirées en mode Ne Pas Déranger + Les notifications non-sollicitées sont suspendues dans ce mode Transcription Activez ceci si votre appareil ne supporte pas la police de caractères Toujours @@ -242,7 +242,7 @@ Sam Réveil intelligent Une erreur s\'est produite lors du paramétrage des alarmes, veuillez réessayer ! - Alarmes envoyées à l\'appareil ! + Alarmes envoyées à l\'appareil. Aucune donnée. Synchroniser l\'appareil ? Sur le point de transférer %1$s de données à partir de %2$s Objectif de pas par jour @@ -566,4 +566,72 @@ NOTE : la base de données sera bien évidement plus grande ! Notifications Musique Suite +Changer la couleur de la LED + Changer la fréquence FM + Calibrer votre appareil + + + Temps minimum entre deux notifications + De droite à gauche + Cocher ceci si votre appareil n\'est pas compatible avec les langues \"droite-à-gauche\" + Longueur max. d\'une ligne en mode Droite-à-Gauche + Lorsque votre bracelet vibre, secouez-le ou pressez son bouton. + + %1$s niveau de batterie bas + %1$s niveau de batterie bas: %2$s + Manque de sommeil: %1$s + Excès de sommeil: %1$s + Sans limite + 5 secondes + 10 secondes + 20 secondes + 30 secondes + 1 minute + 5 minutes + 10 minutes + 30 minutes + + Manque d\'activité: %1$d + Trop d\'activité: %1$d + Mesure cardiaque actuelle / maximum: %1$d / %2$d + Vous avez dormi de %1$s à %2$s + Vous n\'avez pas dormi + Glisser le doigt vers le haut pour débloquer l\'écran du bracelet + Mode nuit + Diminuer la luminosité de l\'écran du bracelet automatiquement lorsqu\'il fait sombre + + Allemand + Italien + Français + Polonais + Koréen + Japonais + + Paramètres des graphiques + Fréquence cardiaque maximum + Fréquence cardiaque minimum + + Ok + + Au coucher du soleil + Watch 9 + Minutes: + Heures: + Secondes: + Régler l\'heure que votre appareil indique actuellement. + Calibrer + Appairage de la Watch 9 + Calibration de la Watch 9 + Support Droite-à-Gauche + Partager les logs + Veuillez garder en tête que les fichiers logs de Gadgetbridge peuvent contenir des tas d\'informations personnelles, incluant entre autre des données relatives à la santé, des identifiants uniques (telles que des adresses MAC), des préférences musicales, etc. Pensez à modifier le fichier et retirer ces informations personnelles avant toute publication sur un rapport de bug public. + Attention! + Pas de données + + Couleur de la LED + + Fréquence FM + Fréquence non-valide + Veuillez introduire une fréquence entre 87.5 et 108.0 + Paramètres de langue et de région From b1b318a18b13eb005348519757f3570f9c707bcb Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 23 Sep 2018 12:00:56 +0200 Subject: [PATCH 59/65] Amazfit Bip: Allow flashing latest gps firmware from Mi Fit 3.5.1.1 (Mili_dth.gps) This file seems to be for the Bip2, but firmwares.json also refereces this for the Bip. And it seems to work. --- .../devices/huami/amazfitbip/AmazfitBipFirmwareInfo.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipFirmwareInfo.java index 17ee1b594..eb1511a83 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipFirmwareInfo.java @@ -45,6 +45,11 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { (byte) 0x8c, 0x36, 0x2e, (byte) 0x8c, (byte) 0x9c, 0x08, 0x54, (byte) 0xa6 }; + private static final byte[] GPS_HEADER5 = new byte[]{ + (byte) 0xec, 0x51, 0x73, 0x22 , 0x60 ,0x02 ,0x14, (byte) 0xb7, + (byte) 0xb5, (byte) 0xea, 0x4b, 0x22 , 0x5d, 0x23, (byte) 0xe5, 0x4f + }; + // this is the same as Cor private static final byte[] FW_HEADER = new byte[]{ 0x00, (byte) 0x98, 0x00, 0x20, (byte) 0xA5, 0x04, 0x00, 0x20, (byte) 0xAD, 0x04, 0x00, 0x20, (byte) 0xC5, 0x04, 0x00, 0x20 @@ -123,6 +128,7 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(8784, "9565,dfbd8fa,0,0,"); crcToVersion.put(16716, "9565,dfbd8faf42,0"); crcToVersion.put(54154, "9567,8b05506,0,0,"); + crcToVersion.put(15717, "15974,e61dd16,126"); // font crcToVersion.put(61054, "8"); @@ -141,7 +147,7 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { } return HuamiFirmwareType.RES; } - if (ArrayUtils.startsWith(bytes, GPS_HEADER) || ArrayUtils.startsWith(bytes, GPS_HEADER2) || ArrayUtils.startsWith(bytes, GPS_HEADER3) || ArrayUtils.startsWith(bytes, GPS_HEADER4)) { + if (ArrayUtils.startsWith(bytes, GPS_HEADER) || ArrayUtils.startsWith(bytes, GPS_HEADER2) || ArrayUtils.startsWith(bytes, GPS_HEADER3) || ArrayUtils.startsWith(bytes, GPS_HEADER4) || ArrayUtils.startsWith(bytes, GPS_HEADER5)) { return HuamiFirmwareType.GPS; } if (ArrayUtils.startsWith(bytes, GPS_ALMANAC_HEADER)) { From 659316a40203c6491f928fedd19d0cbdf3e8941f Mon Sep 17 00:00:00 2001 From: mesnevi Date: Sat, 22 Sep 2018 14:11:41 +0000 Subject: [PATCH 60/65] Translated using Weblate (Russian) Currently translated at 100.0% (578 of 578 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 525e3401a..e9ab76bf1 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -275,8 +275,8 @@ Расстояние Жизненная активность Шагов сегодня, цель: %1$s - Недопройдено %1$d шагов. - Пройдено на %1$d шагов больше. + Не хватает: %1$d шагов + Пройдено на %1$d шагов больше Не подтверждать передачу данных об активности Если данные об активности не будут переданы на устройство, оно не будет очищено. Полезно, если GB используется с другими приложениями. Хранить данные о деятельности на Mi Band, даже после синхронизации. Полезно, если Mi Band используется совместно с другими приложениями. @@ -641,4 +641,12 @@ Максимальный пульс Минимальный пульс - +Справа налево + Включите, если ваше устройство поддерживает ввод справа налево + Максимальная длина строки при вводе справа налево + Изменяет длину строк, на которые разбит текст при вводе справа налево + + Контекстные формы для арабского языка + Включает поддержку контекстных форм арабского языка + Поддержка ввода справа налево + From e62fe363911c0189bb9df1b4bd573faaea8efa1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Fri, 28 Sep 2018 15:50:11 +0100 Subject: [PATCH 61/65] Roidmi 3: Fix and enable support --- .../adapter/GBDeviceAdapterv2.java | 17 ++++++++---- .../devices/roidmi/Roidmi1Coordinator.java | 5 ---- .../devices/roidmi/Roidmi3Coordinator.java | 3 +-- .../devices/roidmi/RoidmiCoordinator.java | 5 ++++ .../gadgetbridge/impl/GBDevice.java | 8 ++++++ .../service/AbstractDeviceSupport.java | 2 +- .../devices/roidmi/Roidmi3Protocol.java | 26 ++++++++++--------- 7 files changed, 41 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java index e9b057f05..9c38d606e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/GBDeviceAdapterv2.java @@ -146,7 +146,7 @@ public class GBDeviceAdapterv2 extends RecyclerView.Adapter 0) { builder.setAllowPresets(true); - builder.setShowColorShades(false); - builder.setPresets(coordinator.getColorPresets()); + builder.setPresets(presets); } ColorPickerDialog dialog = builder.create(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi1Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi1Coordinator.java index 47351dd01..caba200a6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi1Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi1Coordinator.java @@ -49,9 +49,4 @@ public class Roidmi1Coordinator extends RoidmiCoordinator { public DeviceType getDeviceType() { return DeviceType.ROIDMI; } - - @Override - public int[] getColorPresets() { - return RoidmiConst.COLOR_PRESETS; - } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi3Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi3Coordinator.java index 10c351844..81fb6b2e9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi3Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/Roidmi3Coordinator.java @@ -36,8 +36,7 @@ public class Roidmi3Coordinator extends RoidmiCoordinator { String name = device.getName(); if (name != null && name.contains("Roidmi Music Blue C")) { - LOG.warn("Found a Roidmi 3, but support is disabled."); - return DeviceType.UNKNOWN; // TODO Roidmi 3 is not working atm + return DeviceType.ROIDMI3; } } catch (Exception ex) { LOG.error("unable to check device support", ex); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/RoidmiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/RoidmiCoordinator.java index 39d7ce76e..2b6fa4295 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/RoidmiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/roidmi/RoidmiCoordinator.java @@ -132,4 +132,9 @@ public abstract class RoidmiCoordinator extends AbstractDeviceCoordinator { public boolean supportsLedColor() { return true; } + + @Override + public int[] getColorPresets() { + return RoidmiConst.COLOR_PRESETS; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java index 2adc2ae71..766ad799b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDevice.java @@ -274,6 +274,7 @@ public class GBDevice implements Parcelable { setFirmwareVersion(null); setFirmwareVersion2(null); setRssi(RSSI_UNKNOWN); + resetExtraInfos(); if (mBusyTask != null) { unsetBusyTask(); } @@ -403,6 +404,13 @@ public class GBDevice implements Parcelable { mExtraInfos.put(key, info); } + /** + * Deletes all the extra infos + */ + public void resetExtraInfos() { + mExtraInfos = null; + } + /** * Ranges from 0-100 (percent), or -1 if unknown * diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index dd969d237..1f995e4ca 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -216,7 +216,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { protected void handleGBDeviceEvent(GBDeviceEventLEDColor colorEvent) { Context context = getContext(); - LOG.info("Got event for LED Color"); + LOG.info("Got event for LED Color: #" + Integer.toHexString(colorEvent.color).toUpperCase()); if (gbDevice == null) { return; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/roidmi/Roidmi3Protocol.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/roidmi/Roidmi3Protocol.java index a4d6412e7..38d192837 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/roidmi/Roidmi3Protocol.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/roidmi/Roidmi3Protocol.java @@ -24,6 +24,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInf import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFmFrequency; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventLEDColor; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.BatteryState; import nodomain.freeyourgadget.gadgetbridge.util.GB; public class Roidmi3Protocol extends RoidmiProtocol { @@ -40,7 +41,7 @@ public class Roidmi3Protocol extends RoidmiProtocol { private static final byte[] COMMAND_GET_VOLTAGE = new byte[]{0x06, (byte) 0x81}; private static final byte[] COMMAND_SET_COLOR = new byte[]{0x02, 0x01, 0x00, 0x00, 0x00}; - private static final byte[] COMMAND_SET_FREQUENCY = new byte[]{0x05, (byte) 0x81, 0x09, 0x64}; + private static final byte[] COMMAND_SET_FREQUENCY = new byte[]{0x05, 0x01, 0x09, 0x64}; private static final byte[] COMMAND_DENOISE_ON = new byte[]{0x05, 0x06, 0x12}; private static final byte[] COMMAND_DENOISE_OFF = new byte[]{0x05, 0x06, 0x00}; @@ -58,7 +59,7 @@ public class Roidmi3Protocol extends RoidmiProtocol { return null; } - if (calcChecksum(res) != res[res.length - 2]) { + if (calcChecksum(res) != res[res.length - 1]) { LOG.info("Invalid response checksum"); return null; } @@ -68,21 +69,22 @@ public class Roidmi3Protocol extends RoidmiProtocol { return null; } - if (res[1] != (byte) 0x81) { - LOG.error("Unrecognized response" + GB.hexdump(res, 0, res.length)); - return null; + if (res[2] != (byte) 0x81) { + LOG.warn("Potentially unsupported response: " + GB.hexdump(res, 0, res.length)); } if (res[1] == RESPONSE_VOLTAGE) { String voltageHex = GB.hexdump(res, 3, 2); - float voltage = Float.valueOf(voltageHex) / 10.0f; + float voltage = Float.valueOf(voltageHex) / 100.0f; LOG.debug("Got voltage: " + voltage); GBDeviceEventBatteryInfo evBattery = new GBDeviceEventBatteryInfo(); + evBattery.state = BatteryState.NO_BATTERY; + evBattery.level = GBDevice.BATTERY_UNKNOWN; evBattery.voltage = voltage; return new GBDeviceEvent[]{evBattery}; } else if (res[1] == RESPONSE_COLOR) { - LOG.debug("Got color: " + GB.hexdump(res, 3, 3)); - int color = res[3] << 16 | res[4] << 8 | res[4]; + LOG.debug("Got color: #" + GB.hexdump(res, 3, 3)); + int color = 0xFF000000 | ((res[3] << 16) & 0xFF0000) | ((res[4] << 8) & 0xFF00) | (res[5] & 0xFF); GBDeviceEventLEDColor evColor = new GBDeviceEventLEDColor(); evColor.color = color; return new GBDeviceEvent[]{evColor}; @@ -94,7 +96,7 @@ public class Roidmi3Protocol extends RoidmiProtocol { evFrequency.frequency = frequency; return new GBDeviceEvent[]{evFrequency}; } else { - LOG.error("Unrecognized response" + GB.hexdump(res, 0, res.length)); + LOG.error("Unrecognized response: " + GB.hexdump(res, 0, res.length)); return null; } } @@ -103,9 +105,9 @@ public class Roidmi3Protocol extends RoidmiProtocol { public byte[] encodeLedColor(int color) { byte[] cmd = COMMAND_SET_COLOR.clone(); - cmd[2] = (byte) color; + cmd[2] = (byte) (color >> 16); cmd[3] = (byte) (color >> 8); - cmd[4] = (byte) (color >> 16); + cmd[4] = (byte) color; return encodeCommand(cmd); } @@ -144,7 +146,7 @@ public class Roidmi3Protocol extends RoidmiProtocol { } public byte[] encodeGetVoltage() { - return COMMAND_GET_VOLTAGE; + return encodeCommand(COMMAND_GET_VOLTAGE); } public byte[] encodeDenoise(boolean enabled) { From c203023fea28dd263a447c2197568955bddafad4 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Fri, 28 Sep 2018 22:15:10 +0200 Subject: [PATCH 62/65] Update build tools to 3.2.0 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index ea23aab55..e1aec6bd7 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.4' + classpath 'com.android.tools.build:gradle:3.2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From c92ed132cfc54acf1d601fe41f4f86ee09abccad Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Fri, 28 Sep 2018 22:17:54 +0200 Subject: [PATCH 63/65] Update gradle to 4.10.2 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a69b4079b..5c2db3913 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip From 045c0840e3fb31bc03b8115fa4d3a7d1319ccd23 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 29 Sep 2018 00:01:53 +0200 Subject: [PATCH 64/65] Update build-tools to 28.0.2 --- .travis.yml | 2 +- app/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf293dad1..616bc59d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ android: - tools # The BuildTools version used by your project - - build-tools-27.0.3 + - build-tools-28.0.2 # The SDK version used to compile your project - android-27 diff --git a/app/build.gradle b/app/build.gradle index 9ab629e63..d48ca5237 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetCompatibility JavaVersion.VERSION_1_7 } compileSdkVersion 27 - buildToolsVersion "27.0.3" + buildToolsVersion "28.0.2" defaultConfig { applicationId "nodomain.freeyourgadget.gadgetbridge" From 56477efcdfa96e239a3d6b46f5d1b617a1955917 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 29 Sep 2018 21:49:13 +0200 Subject: [PATCH 65/65] Specify new path to classes for findbugs after gradle update --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index d48ca5237..71251a875 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -143,7 +143,7 @@ task findbugs(type: FindBugs) { effort = "default" reportLevel = "medium" excludeFilter = new File("${project.rootDir}/config/findbugs/findbugs-filter.xml") - classes = files("${project.rootDir}/app/build/intermediates/classes") + classes = files("${project.rootDir}/app/build/intermediates/javac/release/compileReleaseJavaWithJavac/classes") source = fileTree("src/main/java/") classpath = files() reports {