From 2fc3a6df568d069846b02e99492ea411028dadc1 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 11 Nov 2017 00:34:00 +0100 Subject: [PATCH 01/55] update also build tools for travis travis will still fail, beacause it sucks --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5cb8117f3..b68866071 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ android: - tools # The BuildTools version used by your project - - build-tools-25.0.2 + - build-tools-26.0.2 # The SDK version used to compile your project - android-25 From a839a88e40909b566cb70cfbb8aacd4b1684d393 Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 11 Nov 2017 00:49:31 +0100 Subject: [PATCH 02/55] Attempt to fix travis with new com.android.tools.build:gradle:3.0.0 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index b68866071..321897f5f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,7 @@ android: # Additional components - extra-android-m2repository + - extra-google-m2repository - addon-google_apis-google-19 # Specify at least one system image, From 7b3e929cd401a3a1df20458acd1509246171e4ea Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sat, 11 Nov 2017 00:55:05 +0100 Subject: [PATCH 03/55] Another attempt at fixing travis build --- .travis.yml | 1 - build.gradle | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 321897f5f..b68866071 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,6 @@ android: # Additional components - extra-android-m2repository - - extra-google-m2repository - addon-google_apis-google-19 # Specify at least one system image, diff --git a/build.gradle b/build.gradle index 830c326a5..1426c3420 100644 --- a/build.gradle +++ b/build.gradle @@ -3,6 +3,7 @@ buildscript { repositories { jcenter() + google() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0' From 2f443ad41989c5326121b3f4d64ce88a2dad0730 Mon Sep 17 00:00:00 2001 From: Zhong Jianxin Date: Wed, 16 Aug 2017 09:58:00 +0800 Subject: [PATCH 04/55] Allow WeChat notifications It seems WeChat always mark its notifications as LocalOnly. The reason may be to avoid double notifications when using Android Wear watches, since WeChat has a standalone Android Wear app. Do not ignore WeChat notifications even if they're marked as LocalOnly. --- .../externalevents/NotificationListener.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 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 0a3d5576c..181f045d0 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -394,7 +394,7 @@ public class NotificationListener extends NotificationListenerService { } return shouldIgnoreSource(sbn.getPackageName()) || shouldIgnoreNotification( - sbn.getNotification()); + sbn.getNotification(), sbn.getPackageName()); } @@ -432,15 +432,18 @@ public class NotificationListener extends NotificationListenerService { return false; } - private boolean shouldIgnoreNotification(Notification notification) { + private boolean shouldIgnoreNotification(Notification notification, String source) { MediaSessionCompat.Token mediaSession = NotificationCompat.getMediaSession(notification); //try to handle media session notifications if (mediaSession != null && handleMediaSessionNotification(mediaSession)) return true; + NotificationType type = AppNotificationType.getInstance().get(source); //ignore notifications marked as LocalOnly https://developer.android.com/reference/android/app/Notification.html#FLAG_LOCAL_ONLY - if (NotificationCompat.getLocalOnly(notification)) + if (NotificationCompat.getLocalOnly(notification) && + //WeChat always marks its notifications as LocalOnly, do not ignore them + type != NotificationType.WECHAT) return true; Prefs prefs = GBApplication.getPrefs(); From 82ad7abf62422fa69c906a0e5a79b84307a8efe4 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 11 Nov 2017 23:36:38 +0100 Subject: [PATCH 05/55] Mi Band 2/Bip/Cor: Only enable notification on realtime hr characteristic when live activity is used --- .../service/devices/miband2/MiBand2Support.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java index 37b866a9a..e10cd3504 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java @@ -271,10 +271,6 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_3_CONFIGURATION), enable); builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_6_BATTERY_INFO), enable); builder.notify(getCharacteristic(MiBand2Service.UUID_CHARACTERISTIC_DEVICEEVENT), enable); - BluetoothGattCharacteristic heartrateCharacteristic = getCharacteristic(GattCharacteristic.UUID_CHARACTERISTIC_HEART_RATE_MEASUREMENT); - if (heartrateCharacteristic != null) { - builder.notify(heartrateCharacteristic, enable); - } return this; } @@ -752,11 +748,15 @@ public class MiBand2Support 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 (enable) { builder.write(characteristicHRControlPoint, stopHeartMeasurementManual); builder.write(characteristicHRControlPoint, startHeartMeasurementContinuous); } else { - builder.write(getCharacteristic(MiBandService.UUID_CHARACTERISTIC_HEART_RATE_CONTROL_POINT), stopHeartMeasurementContinuous); + builder.write(characteristicHRControlPoint, stopHeartMeasurementContinuous); } builder.queue(getQueue()); enableRealtimeSamplesTimer(enable); From fb0a4ed73873c58bca7ed9ee1a1aa1f13aac4d5a Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Sun, 12 Nov 2017 01:18:42 +0100 Subject: [PATCH 06/55] Another attempt at fixing another issue with new tools.build gradle:3.0.0 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b68866071..be891d615 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ android: components: # Uncomment the lines below if you want to # use the latest revision of Android SDK Tools - # - platform-tools + - platform-tools - tools # The BuildTools version used by your project From 5a77f224f4ff271cea2b2b3f09155be7b36af8c6 Mon Sep 17 00:00:00 2001 From: Davis Mosenkovs Date: Sat, 11 Nov 2017 21:55:16 +0200 Subject: [PATCH 07/55] Mi Band 2: whitelist firmware 1.0.1.54 Firmware version 1.0.1.54 is marked as recommended on wiki (Mi Band Firmware Information). --- .../gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java index 014792bfe..3538d3335 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java @@ -55,6 +55,7 @@ public class Mi2FirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(32450, "1.0.1.28"); crcToVersion.put(51770, "1.0.1.34"); crcToVersion.put(3929, "1.0.1.39"); + crcToVersion.put(47364 , "1.0.1.54"); // fonts crcToVersion.put(45624, "Font"); From 383d1d943103846910c9e808976b6248363e5ab6 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 09:18:06 +0100 Subject: [PATCH 08/55] Try to disable pre dexing for travis --- app/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 5f7f4dfac..c336df31c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,6 +36,9 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + dexOptions { + preDexLibraries = System.getenv('TRAVIS_BUILD_NUMBER') ? true : false + } lintOptions { abortOnError ABORT_ON_CHECK_FAILURE From 35a72d34c15f9581e9d34b6df903b437459f302c Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 11:01:29 +0100 Subject: [PATCH 09/55] update libraries and try to work around build issues See https://github.com/tony19/logback-android/issues/73 --- app/build.gradle | 21 ++++++++++----------- build.gradle | 1 + 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c336df31c..d79a31494 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -36,9 +36,6 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - dexOptions { - preDexLibraries = System.getenv('TRAVIS_BUILD_NUMBER') ? true : false - } lintOptions { abortOnError ABORT_ON_CHECK_FAILURE @@ -67,14 +64,16 @@ dependencies { testCompile "org.robolectric:robolectric:3.3.2" compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.3.1' - compile 'com.android.support:cardview-v7:25.3.1' - compile 'com.android.support:recyclerview-v7:25.3.1' - compile 'com.android.support:support-v4:25.3.1' - compile 'com.android.support:gridlayout-v7:25.3.1' - compile 'com.android.support:design:25.3.1' - compile 'com.android.support:palette-v7:25.3.1' - compile 'com.github.tony19:logback-android-classic:1.1.1-6' + compile 'com.android.support:appcompat-v7:25.4.0' + compile 'com.android.support:cardview-v7:25.4.0' + compile 'com.android.support:recyclerview-v7:25.4.0' + compile 'com.android.support:support-v4:25.4.0' + compile 'com.android.support:gridlayout-v7:25.4.0' + compile 'com.android.support:design:25.4.0' + compile 'com.android.support:palette-v7:25.4.0' + compile('com.github.tony19:logback-android-classic:1.1.1-6') { + exclude group: 'com.google.android', module: 'android' + } compile 'org.slf4j:slf4j-api:1.7.7' compile 'com.github.PhilJay:MPAndroidChart:v3.0.2' compile 'com.github.pfichtner:durationformatter:0.1.1' diff --git a/build.gradle b/build.gradle index 1426c3420..c41c322f1 100644 --- a/build.gradle +++ b/build.gradle @@ -19,5 +19,6 @@ allprojects { maven { url "https://jitpack.io" } + google() } } From 9c29c01116586d0b3173ba002e31995c247cfb38 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 12:55:02 +0100 Subject: [PATCH 10/55] update more dependencies --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d79a31494..2cafd8481 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -60,8 +60,8 @@ dependencies { // testCompile 'ch.qos.logback:logback-classic:1.1.3' // testCompile 'ch.qos.logback:logback-core:1.1.3' testCompile 'junit:junit:4.12' - testCompile "org.mockito:mockito-core:1.9.5" - testCompile "org.robolectric:robolectric:3.3.2" + testCompile "org.mockito:mockito-core:1.10.19" + testCompile "org.robolectric:robolectric:3.5.1" compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:25.4.0' @@ -74,7 +74,7 @@ dependencies { compile('com.github.tony19:logback-android-classic:1.1.1-6') { exclude group: 'com.google.android', module: 'android' } - compile 'org.slf4j:slf4j-api:1.7.7' + compile 'org.slf4j:slf4j-api:1.7.12' compile 'com.github.PhilJay:MPAndroidChart:v3.0.2' compile 'com.github.pfichtner:durationformatter:0.1.1' compile 'de.cketti.library.changelog:ckchangelog:1.2.2' From 6a8700201f758ba189162a56747fffb12ffbf06c Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 13:13:56 +0100 Subject: [PATCH 11/55] fix resource bug when running tests with robolectric --- gradle.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8c1449720..0b19e8f87 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,4 +16,5 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file +# org.gradle.parallel=true +android.enableAapt2=false From d25da968048a001c4daf3c6d43d575510783f297 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 22:02:00 +0100 Subject: [PATCH 12/55] Pebble: log some errors during JSON encoding/decoding --- .../gadgetbridge/service/devices/pebble/PebbleKitSupport.java | 2 +- .../gadgetbridge/service/devices/pebble/PebbleProtocol.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java index 9e51761a8..0184e9524 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java @@ -85,7 +85,7 @@ class PebbleKitSupport { sendAppMessageAck(transaction_id); // } } catch (JSONException e) { - e.printStackTrace(); + LOG.error("failed decoding JSON", e); } break; case PEBBLEKIT_ACTION_APP_ACK: 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 68ed2e9f0..3a06615d8 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 @@ -2023,6 +2023,7 @@ public class PebbleProtocol extends GBDeviceProtocol { break; } } catch (JSONException e) { + LOG.error("error decoding JSON", e); return null; } } From 97fda2434dac64767137b4696e3fddbd8f494090 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 22:10:40 +0100 Subject: [PATCH 13/55] Pebble: prevent potential NPE, and add more loggins in PebbleKit code --- .../service/devices/pebble/PebbleKitSupport.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java index 0184e9524..3119a6a55 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleKitSupport.java @@ -45,9 +45,9 @@ class PebbleKitSupport { private static final String PEBBLEKIT_ACTION_APP_STOP = "com.getpebble.action.app.STOP"; private static final String PEBBLEKIT_ACTION_DL_RECEIVE_DATA_NEW = "com.getpebble.action.dl.RECEIVE_DATA_NEW"; - private static final String PEBBLEKIT_ACTION_DL_RECEIVE_DATA = "com.getpebble.action.dl.RECEIVE_DATA"; + //private static final String PEBBLEKIT_ACTION_DL_RECEIVE_DATA = "com.getpebble.action.dl.RECEIVE_DATA"; private static final String PEBBLEKIT_ACTION_DL_ACK_DATA = "com.getpebble.action.dl.ACK_DATA"; - private static final String PEBBLEKIT_ACTION_DL_REQUEST_DATA = "com.getpebble.action.dl.REQUEST_DATA"; + //private static final String PEBBLEKIT_ACTION_DL_REQUEST_DATA = "com.getpebble.action.dl.REQUEST_DATA"; private static final String PEBBLEKIT_ACTION_DL_FINISH_SESSION = "com.getpebble.action.dl.FINISH_SESSION_NEW"; private static final Logger LOG = LoggerFactory.getLogger(PebbleKitSupport.class); @@ -62,6 +62,10 @@ class PebbleKitSupport { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + if (action == null) { + LOG.warn("got empty action from PebbleKit Intent - ignoring"); + return; + } LOG.info("Got action: " + action); UUID uuid; switch (action) { @@ -101,7 +105,9 @@ class PebbleKitSupport { case PEBBLEKIT_ACTION_DL_ACK_DATA: LOG.info("GOT DL DATA ACK"); break; - + default: + LOG.warn("Unhandled PebbleKit action: " + action); + break; } } }; From 7ffcc44378e9226955cc5582b76e3ac88e68768c Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 22:28:54 +0100 Subject: [PATCH 14/55] Pebble: fix nasty crash when appmessage id is > 127 This is a regression since Gadgetbridge 0.22.0 Potentially fixes the following: - #868 - #876 - #884 NOTE: Java has no unisgned, java has no unsigned, java has no unsigned. Java has no unisgned, java has no unsigned, java has no unsigned. Java has no unisgned, java has no unsigned, java has no unsigned. --- .../gadgetbridge/service/devices/pebble/PebbleProtocol.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 3a06615d8..e9d6a21dd 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 @@ -1986,7 +1986,7 @@ public class PebbleProtocol extends GBDeviceProtocol { } } - idLookup[last_id] = ext_id; + idLookup[last_id & 0xff] = ext_id; return buf.array(); } @@ -2633,14 +2633,14 @@ public class PebbleProtocol extends GBDeviceProtocol { LOG.info("got APPLICATIONMESSAGE/LAUNCHER (EP " + endpoint + ") NACK"); } GBDeviceEventAppMessage evtAppMessage = null; - if (endpoint == ENDPOINT_APPLICATIONMESSAGE && idLookup[last_id] != null) { + if (endpoint == ENDPOINT_APPLICATIONMESSAGE && idLookup[last_id & 0xff] != null) { evtAppMessage = new GBDeviceEventAppMessage(); if (pebbleCmd == APPLICATIONMESSAGE_ACK) { evtAppMessage.type = GBDeviceEventAppMessage.TYPE_ACK; } else { evtAppMessage.type = GBDeviceEventAppMessage.TYPE_NACK; } - evtAppMessage.id = idLookup[last_id]; + evtAppMessage.id = idLookup[last_id & 0xff]; evtAppMessage.appUUID = currentRunningApp; } devEvts = new GBDeviceEvent[]{evtAppMessage}; From 6dd4358b726cd8d6a5e9bf799f6ef2702076d371 Mon Sep 17 00:00:00 2001 From: mesnevi Date: Fri, 10 Nov 2017 09:56:20 +0000 Subject: [PATCH 15/55] Translated using Weblate (Russian) Currently translated at 75.7% (322 of 425 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 150 ++++++++++++++++--------- 1 file changed, 96 insertions(+), 54 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 283c294fa..183238c49 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -7,7 +7,7 @@ Выход Синхронизировать Анализ сна (АЛЬФА) - Найти устройство... + Найти устройство Сделать снимок экрана Отключиться Удалить устройство @@ -15,13 +15,13 @@ Устройство и вся связанная с ним информация будут удалены! Открыть панель навигации Закрыть панель навигации - Выполните долгое нажатие на карту для разъединения. + Чтобы разъединиться, нажмите на карточку устройства и удержите Разъединение Соединение Сделать снимок устройства Отладка - App Manager + Управление приложением Приложения в памяти Установленные приложения Установленный циферблаты @@ -43,7 +43,7 @@ Установщик прошивки/приложений - Вы собираетесь установить прошивку %s заместо текущей на вашем Mi Band. + "Вы собираетесь установить прошивку %s на ваш Mi Band вместо текущей." Вы собираетесь установить прошивки %1$s и %2$s вместо текущей на вашем Mi Band. Эта прошивка была проверена и совместима с Gadgetbridge. Эта прошивка не протестирована и может быть несовместима с Gadgetbridge.\n\nНе рекомендуется устанавливать её на ваш Mi Band! @@ -55,7 +55,7 @@ Запускать автоматически Переподключаться автоматически Предпочтительный музыкальный плеер - По-умолчанию + По умолчанию Дата и время Синхронизировать время при подключении Синхронизировать время при подключении к устройству, а также при изменении времени или временной зоны в системе @@ -77,10 +77,10 @@ Не беспокоить Предотвращать отправку нежелательных уведомлений в режиме \"Не беспокоить\" Транслитерация - всегда + Всегда Включите эту функцию, если ваше устройство не имеет поддержки шрифта на вашем языке - когда экран выключен - никогда + Когда экран выключен + Никогда Конфиденциальность Вызов режима конфиденциальности Отображать имя и номер @@ -103,10 +103,10 @@ Синхронизация с Morpheuz Поддержка исходящих вызовов При отключении данного пункта, Pebble 2/LE также не будет вибрировать при исходящих вызовах - Разрешить доступ приложениям третьих лиц + Разрешить доступ посторонним приложениям Добавить экспериментальную поддержку приложений Android, использующих PebbleKit Восход и закат солнца - Показывать время восхода и захода солнца в зависимости от местоположения на временной шкале pebble + Показывать время восхода и захода солнца в зависимости от местоположения на временной шкале Pebble Синхронизация календаря Отображать события календаря на временной шкале pebble Автоматическое удаление отклонённых уведомлений @@ -124,7 +124,7 @@ Пожалуйста, включите сетевое расположение Месторасположение определено Принудительный протокол уведомлений - Эта настройка заставляет принудительно использовать самый новый протокол уведомлений, зависящий от версии прошивки. ВКЛЮЧАЙТЕ, ТОЛЬКО ЕСЛИ ЗНАЕТЕ НА ЧТО ВЫ ИДЁТЕ. + Эта настройка принудительно использует самый новый протокол уведомлений, (зависит от версии прошивки). ВКЛЮЧАЙТЕ, ЕСЛИ ТОЧНО ЗНАЕТЕ, ЗАЧЕМ ВАМ ЭТО! Включить непроверенные функции Включить функции, которые не протестированы. ВКЛЮЧАЙТЕ НА СВОЙ СТРАХ И РИСК! Всегда отдавать предпочтение BLE @@ -141,25 +141,25 @@ Продолжительность работы экрана Измерение сердечного ритма в течение всего дня Настройки HPlus/Makibes - нет соединения - соединение - соединено - неизвестное состояние + Нет соединения + Соединение + Соединено + Непонятное состояние (неизвестно) Тест - Тест уведомлений + Тестовое уведомлений Это тестовое уведомление от Gadgetbridge Bluetooth не поддерживается. Bluetooth отключён. - Коснитесь подключённого устройства для вызова Менеджера приложений + Коснитесь подключённого устройства для вызова Управления приложениями Коснитесь подключённого устройства для показа Активностей Коснитесь подключённого устройства для Вибрации Коснитесь подключённого устройства для соединения - Не удалось соединиться. Неверен адрес BT? + Не удалось соединиться. Невереный адрес Bluetooth? Gadgetbridge запущен - установки бинарного файла %1$d/%2$d - установка не удалась! - установка завершена + установка бинарного файла %1$d/%2$d + Установка не удалась + Установка завершена ВЫ ПЫТАЕТЕСЬ УСТАНОВИТЬ ПРОШИВКУ, ПРОДОЛЖАЙТЕ НА СВОЙ СТРАХ И РИСК.\n\n\n Эта прошивка для ревизии устройства: %s Вы собираетесь установить приложение:\n\n\n%1$s версия %2$s от %3$s\n Недоступно @@ -177,7 +177,7 @@ Привязываюсь к %1$s (%2$s) Невозможно выполнить сопряжение с %1$s (%2$s) Выполняется привязка: %1$s (%2$s) - Уже привязан к %1$s (%2$s), выполняется соединение... + Уже привязан к %1$s (%2$s), выполняется соединение… MAC-адрес не был передан, сопряжение не удалось. Настройки устройства Настройки Mi Band @@ -219,7 +219,7 @@ Навигация Социальные сети Найти потерянное устройство - Отмените, чтобы остановить вибро + Отмените, чтобы прекратить вибрацию. Ваша активность Завести Будильник Завести будильник @@ -242,8 +242,8 @@ Подключиться не удалось: %1$s Не удалось найти обработчик для установки этого файла. Не удалось установить данный файл: %1$s - Не удалось установить данную прошивку: она не совпадает с версией устройства вашего Pebble - Пожалуйста подождите, идёт определение статуса установки... + Не удалось установить прошивку: она не совпадает с версией вашего устройства Pebble. + Пожалуйста подождите, проверяется статус установки… Низкий заряд устройства! %1$s осталось заряда: %2$s%% Последний раз устройство заряжалось: %s \n @@ -253,7 +253,7 @@ Сон сегодня, цель: %1$s Шагов в неделю Ваша активность и сон - Обновление прошивки... + Обновление прошивки… Файл не может быть установлен, устройство не готово. Версия прошивки Mi Band: %1$s Совместимая версия @@ -266,7 +266,7 @@ Проблема с передачей прошивки. НЕ ПЕРЕЗАГРУЖАЙТЕ ваш Mi Band! Проблема с передачей метаданных прошивки Установка прошивки завершена - Установка прошивки завершена, устройство перезагружается... + Установка прошивки завершена, устройство перезагружается… Запись прошивки завершилась неудачей Шаги Калории @@ -308,71 +308,113 @@ Вес в кг Авторизация Требуется авторизация - Zzz + Хрр Добавить виджет Желаемая продолжительность сна Будильник был установлен на %1$02d:%2$02d Версия устройства: %1$s Версия ПО: %1$s Ошибка создания каталога для лог-файлов: %1$s - HR: - Обновление прошивки в процессе + "Версия устройства: " + Происходит обновление прошивки Прошивка не отправлена Пульс Пульс Хранить необработанные записи в базе данных - Если флажок установлен, данные сохраняются «как есть» и доступны для последующей интерпретации. NB: база данных будет занимать больше места в этом случае! + Если флажок установлен, данные сохраняются как есть, в дальнейшем их можно обрабатывать. Обратите внимание: в этом случае база данных будет занимать больше места! Управление базой данных Управление базой данных - Операции с базой данных используют на вашем устройстве следующий путь. \n Этот путь доступен для других приложений Android и вашего компьютера. \n Вы можете найти вашу экспортированную базу данных (или разместить базу данных, которую вы хотите импортировать) здесь: - Удаление устаревшей базой данных - Невозможно получить доступ к пути экспорта. Обратитесь пожалуйста к разработчикам. + "Операции с базой данных используют этот путь на вашем устройстве. +\nОн доступен для других приложений Android и вашего компьютера. +\nВы можете найти экспортированную базу данных (или разместить базу данных, которую вы хотите импортировать) здесь:" + Удаление устаревшей базы данных + Нет доступа к пути экспорта. Обратитесь, пожалуйста, к разработчикам. Экспортировано в: %1$s Ошибка экспорта базы данных: %1$s Ошибка экспорта настроек: %1$s Импортировать данные? - Действительно перезаписать текущую базу данных? Все ваши текущие данные по вашей активности (если они есть) будут потеряны. + Точно перезаписать текущую базу данных? Все текущие данные вашей активности (если они есть) будут утеряны. Импорт успешно завершён. - Ошибка импорта БД: %1$s + Ошибка импорта базы данных: %1$s Ошибка импорта настроек: %1$s Удалить данные по вашей активности? - Действительно удалить всю базу данных? Все данные о вашей активности и информация о ваших устройствах будут потеряны. + Действительно удалить всю базу данных? Все данные о вашей активности и информация о ваших устройствах будут утеряны. Данные успешно удалены. - Не удалось удалить базу данных. - Удалить данные по вашей активности? - Вы действительно хотите удалить устаревшие данные по вашей активности? Все данные о вашей активности, которые не были импортированы, будут потеряны. + Удалить базу данных не получилось. + Удалить данные по предыдущей активности? + Точно удалить устаревшие данные по вашей активности? Все не импортированные данные об активности будут утеряны. Устаревшие данные по вашей активности успешно удалены. - Не удалось удалить устаревшие данные по вашей активности. + Удалить устаревшие данные по вашей активности не получилось. Перезаписать Отмена Удалить Вибрация - Pebble Сопряжение - На вашем Android устройстве должно появиться всплывающее окно с предложением сопряжения устройств. Если этого не произошло, загляните в ящик уведомлений и примите запрос на сопряжение. После этого примите запрос сопряжения на вашем Pebble - Убедитесь, что оболочка выбрана в приложении «Уведомление о погоде», чтобы получать информацию о погоде на вашем Pebble.\n\nНикакой настройки здесь не требуется.\n\nВы можете включить приложение погоды вашего Pebble из управления приложениями.\n\nПоддерживаемые циферблаты покажут погоду автоматически. + Сопряжение с Pebble + На вашем Android устройстве должно появиться всплывающее окно с запросом на сопряжение устройств. Если этого не произошло, загляните в ящик уведомлений и примите запрос на сопряжение. После этого примите запрос сопряжения на вашем устройстве Pebble + Чтобы получать информацию о погоде на вашем Pebble, убедитесь, что выбрали эту тему в приложении «Уведомление о погоде». +\n +\nДополнительная настройка не нужна. +\n +\nВключить приложение погоды на вашем Pebble можно из \"Управления приложениями\". +\n +\nПоддерживаемые циферблаты покажут погоду автоматически. Включить сопряжение по Bluetooth - Выключите данный пункт, если у вас возникли проблемы с подключением - Метрическая система - Приоритетный - 24ч - 12ч + Отключите, если вам не удалось подключиться + Метрическая система мер + Английская система мер + 24 ч + 12 ч Будильник (%1$s) - Вы нашли! - Mi2: Формат Времени - Вам необходимо установить версию %1$s до того как установить данную прошивку! + Нашёлся! + Mi2: Формат времени + До того как установить эту прошивку, нужно установить предыдущую версию %1$s! Текстовые уведомления = 1.0.1.28 и установленный Mili_pro.ft* .]]> Выкл. Попытка сопряжения с %1$s - Не удалось выполнить привязку к %1$s + Не удалось выполнить привязку к %1$s. Попытка соединения с: %1$s Включить Bluetooth для обнаружения устройств. Привязка к %1$s успешно выполнена. Выполнить сопряжение с %1$s ? - Выберите \"Сопряжение\" для сопряжения ваших устройств, если этого сделать не получилось, попробуйте снова без сопряжения. + Выберите \"Сопряжение\" для сопряжения ваших устройств. Если не получилось, попробуйте снова без сопряжения. Сопряжение Не выполнять сопряжение +Пожертвовать + Cоединение + Заблокированные календари + + "Вы собираетесь установить прошивку %s на ваш Amazfit Bip. +\n +\nПеред этим, пожалуйста, установите файл .gps, файл .res и последним — .fw файл. После установки .fw файла устройство перезагрузится. +\n +\nОбратите внимание: если файлы .gps и .res такие же, как в текущей версии, их не нужно переустанавливать. +\n +\nВы действуете на свой страх и риск!" + Вы собираетесь установить прошивку %s на ваш Amazonfit Cor. +\n +\nПеред этим, пожалуйста, установите файл .res и файл .fw. После установки файла .fw ваше устройство перезагрузится. +\n +\nОбратие внимание: если версия файла .res совпадает с предыдущей, его не нужно переустанавливать. +\n +\nЭту прошивку не проверяли, поэтому есть вероятность сломать ваше устройство. Действуйте на свой страх и риск! + Включить жесты \"провести направо и налево\" в графиках активности + + Заблокировать Календари + + Временной график Pebble + Включить JS в фоновом режиме + Включают, чтобы видеть погоду, заряд батарейки и т.д. на циферблате. + + Веб-отчёт активности + + Выкл. + Автоматически (определяет режим сна) + Запланировано (промежуток времени) + Открыть в устройстве + Отключить звук + Ответить From ae6f402c7d8b5a2dd91f497a64dfe2fad943a9a7 Mon Sep 17 00:00:00 2001 From: anonymous <> Date: Fri, 10 Nov 2017 10:47:48 +0000 Subject: [PATCH 16/55] Translated using Weblate (Russian) Currently translated at 75.7% (322 of 425 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 183238c49..40237251e 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -43,7 +43,7 @@ Установщик прошивки/приложений - "Вы собираетесь установить прошивку %s на ваш Mi Band вместо текущей." + Вы собираетесь установить прошивку %s вместо текущей на вашем Mi Band. Вы собираетесь установить прошивки %1$s и %2$s вместо текущей на вашем Mi Band. Эта прошивка была проверена и совместима с Gadgetbridge. Эта прошивка не протестирована и может быть несовместима с Gadgetbridge.\n\nНе рекомендуется устанавливать её на ваш Mi Band! From 2f57a504eba8439f6024fedcb83b86d60551a3ec Mon Sep 17 00:00:00 2001 From: mesnevi Date: Fri, 10 Nov 2017 15:54:49 +0000 Subject: [PATCH 17/55] Translated using Weblate (Russian) Currently translated at 100.0% (425 of 425 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 79 ++++++++++++++++++++------ 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 40237251e..0f3551f7c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -166,7 +166,7 @@ Инициализировано %1$s от %2$s Поиск устройства - Остановить поиск + Остановить поиск устройств Умный поиск Подключиться к новому устройству %1$s (%2$s) @@ -178,12 +178,12 @@ Невозможно выполнить сопряжение с %1$s (%2$s) Выполняется привязка: %1$s (%2$s) Уже привязан к %1$s (%2$s), выполняется соединение… - MAC-адрес не был передан, сопряжение не удалось. + MAC-адреса нет, сопряжение не удалось. Настройки устройства - Настройки Mi Band - мужской - женский - другой + Настройки Mi Band и Amazfit + Мужчина + Женщина + Другой слева справа Не предоставлено действительных данных пользователя. Используются данные по-умолчанию. @@ -194,13 +194,13 @@ Изображение устройства Имя/псевдоним Количество вибраций - Анализ сна - Сохранять файл журнала - Инициализация + Анализ фаз сна + Сохранять файлы журнала + Запускается Получение данных активности От %1$s до %2$s Носите на левой или правой руке? - Профиль вибро + Профиль настроек вибрации Стаккато Короткий Средний @@ -211,9 +211,9 @@ Вибро Попробовать SMS-уведомление - Настройки вибро + Настройки вибрации Общие уведомления - Уведомление по электронной почте + Уведомление электронной почты Уведомления о входящем звонке Чат Навигация @@ -223,7 +223,7 @@ Ваша активность Завести Будильник Завести будильник - Свойства будильника + Настройки будильника Вс Пн Вт @@ -252,7 +252,7 @@ Сон за неделю Сон сегодня, цель: %1$s Шагов в неделю - Ваша активность и сон + Ваши активность и сон Обновление прошивки… Файл не может быть установлен, устройство не готово. Версия прошивки Mi Band: %1$s @@ -284,7 +284,7 @@ История шагов за минуту Начните вашу активность Активность - Неглубокий сон + Быстрый сон Глубокий сон Не носилось Не подключен. @@ -297,7 +297,7 @@ Смещение времени в часах (для тех, кто работает по ночам) Mi2: Формат даты Время - + Время и дата Активировать экран при подъёме Готов к передачи данных с %1$s Ожидание переподключения @@ -313,7 +313,7 @@ Желаемая продолжительность сна Будильник был установлен на %1$02d:%2$02d Версия устройства: %1$s - Версия ПО: %1$s + Версия прошивки: %1$s Ошибка создания каталога для лог-файлов: %1$s "Версия устройства: " Происходит обновление прошивки @@ -417,4 +417,47 @@ Открыть в устройстве Отключить звук Ответить - +Настройки Amazfit Bip + Зоны скорости + Всего минут + Шагов в минуту + + Прошивка Amazfit Bip версии %1$s + Прошивка Amazfit Cor версии %1$s + Часы + Пульс + Заряд батарейки + Действия кнопки + Настройте действия при нажатии на кнопку вашего Mi Band 2 + Нажатий на кнопку + Количество нажатий, необходимое чтобы запустить трансляцию сообщений + Сообщение для трансляции + Заданное количество нажатий для трансляции сообщения выполнено + Включить действия при нажатии на кнопку + Включить действия для заданного количества нажатий на кнопку + Включить вибрацию браслета + Включить вибрацию браслета в ответ на исполняющееся при нажатии действие + Максимальная задержка между нажатиями + Максимальная задержка между нажатиями в миллисекундах + Задержка после действия при нажатии + Задержка при выполнении заданного количества нажатий для однократного действия (число указано в button_id). Это число равно нулю для действий без задержки + Уведомления о достижении цели + Когда выполнена дневная норма шагов, браслет вибрирует + Что показывать на экране + Выберите, что показывать на экране браслета + Поверните запястье, чтобы переключиться на другую информацию + Не беспокоить + Браслет не будет получать уведомления, даже если включён + Напоминания о низкой активности + Когда вы мало двигаетесь, браслет время от времени вибрирует + Период низкой активности (в минутах) + Отключить уведомления о низкой активности во время режима \"Не беспокоить\" + Начало режим \"Не беспокоить\" + Окончание режима \"Не беспокоить\" + + Автоматически + Упрощённый китайский язык + Традиционный китайский язык + Английский язык + + From a9aad41f7f8b74e573a1ecde686d8dce15f22b43 Mon Sep 17 00:00:00 2001 From: Andreas Kromke Date: Fri, 10 Nov 2017 16:25:04 +0000 Subject: [PATCH 18/55] Translated using Weblate (German) Currently translated at 98.8% (420 of 425 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/ --- app/src/main/res/values-de/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 1a99dc039..e82f48da6 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -441,4 +441,6 @@ \n \nNICHT GETESTET, DIES KÖNNTE DEIN GERÄT UNBENUTZBAR MACHEN, INSTALLATION AUF EIGENE GEFAHR! Anzahl an Tastendrücken + Seitwärts-Wischgesten in der Statistik-Anzeige + From 6ce598fa30032982b4900ced2fad785753dd40a9 Mon Sep 17 00:00:00 2001 From: Yaron Shahrabani Date: Sat, 11 Nov 2017 05:40:32 +0000 Subject: [PATCH 19/55] Translated using Weblate (Hebrew) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/he/ --- app/src/main/res/values-he/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 719cf6433..ef2cd0442 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -456,4 +456,11 @@ סינית מסורתית אנגלית + מדד דופק ליום + פעם בדקה + כל 5 דקות + כל 10 דקות + כל חצי שעה + פעם בשעה + From 3552ea8c15c30da1a6ee15464b181cec496942ae Mon Sep 17 00:00:00 2001 From: naofum Date: Sat, 11 Nov 2017 05:54:03 +0000 Subject: [PATCH 20/55] Translated using Weblate (Japanese) Currently translated at 75.8% (327 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ja/ --- app/src/main/res/values-ja/strings.xml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index fc55edd07..9042ea856 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -441,4 +441,19 @@ Amazfit Cor ファームウェア %1$s Web View アクティビティ + チャートアクティビティで左/右のスワイプを有効にする + + Amazfit Bip 設定 + 終日心拍数計測 + 1分間に 1 回 + 5 分ごと + 10 分ごと + 30 分ごと + 1 時間に 1 回 + + 自動 + 簡体中国語 + 繁体中国語 + 英語 + From ee1f08e8f6f19fc1d7d4183bf4a72cddc9449da3 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sun, 12 Nov 2017 12:59:48 +0000 Subject: [PATCH 21/55] Translated using Weblate (Spanish) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/es/ --- app/src/main/res/values-es/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8248a6e79..07c345d87 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -451,4 +451,11 @@ Chino tradicional Inglés + Medición de pulso todo el día + Una vez por minuto + Cada 5 minutos + Cada 10 minutos + Cada 30 minutos + Cada hora + From 5f65cd36bb7e1b5284950e1cc0416eedb739a649 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sun, 12 Nov 2017 13:03:18 +0000 Subject: [PATCH 22/55] Translated using Weblate (French) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/fr/ --- app/src/main/res/values-fr/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 1c4727a30..4efa738b5 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -455,4 +455,11 @@ NOTE: la base de données sera bien évidement plus grande ! Chinois traditionnel Anglais + Mesure du pouls toute la journée + Une fois par minute + Toutes les 5 minutes + Toutes les 10 minutes + Toutes les 30 minutes + Une fois par heure + From 25528b152ffffbefdc24f1d9306334b7bbc71049 Mon Sep 17 00:00:00 2001 From: Vladislav Serkov Date: Sun, 12 Nov 2017 20:58:06 +0000 Subject: [PATCH 23/55] Translated using Weblate (Russian) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 0f3551f7c..45a8248e7 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -460,4 +460,11 @@ Традиционный китайский язык Английский язык + Измерение пульса в течение целого дня + раз в минуту + раз в 5 минут + раз в 10 минут + раз в полчаса + раз в час + From 73c18a381e2ca2e8ae9d950a4856b737240dd64a Mon Sep 17 00:00:00 2001 From: Vladislav Serkov Date: Sun, 12 Nov 2017 21:12:51 +0000 Subject: [PATCH 24/55] Translated using Weblate (Russian) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 45a8248e7..60124d582 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -154,7 +154,7 @@ Коснитесь подключённого устройства для вызова Управления приложениями Коснитесь подключённого устройства для показа Активностей Коснитесь подключённого устройства для Вибрации - Коснитесь подключённого устройства для соединения + Коснитесь устройства для соединения Не удалось соединиться. Невереный адрес Bluetooth? Gadgetbridge запущен установка бинарного файла %1$d/%2$d @@ -214,7 +214,7 @@ Настройки вибрации Общие уведомления Уведомление электронной почты - Уведомления о входящем звонке + Уведомления о входящих звонках Чат Навигация Социальные сети @@ -222,7 +222,7 @@ Отмените, чтобы прекратить вибрацию. Ваша активность Завести Будильник - Завести будильник + Настроить будильники Настройки будильника Вс Пн @@ -289,7 +289,7 @@ Не носилось Не подключен. Все будильники отключены - Храните данные о деятельности на устройстве + Хранить данные об активности на устройстве Несовместимая прошивка Эта прошивка не совместима с устройством Резервные сигналы для предстоящих событий @@ -342,7 +342,7 @@ Данные успешно удалены. Удалить базу данных не получилось. Удалить данные по предыдущей активности? - Точно удалить устаревшие данные по вашей активности? Все не импортированные данные об активности будут утеряны. + Точно удалить старые данные об активности? Все не импортированные данные об активности будут утеряны. Устаревшие данные по вашей активности успешно удалены. Удалить устаревшие данные по вашей активности не получилось. Перезаписать @@ -435,7 +435,7 @@ Заданное количество нажатий для трансляции сообщения выполнено Включить действия при нажатии на кнопку Включить действия для заданного количества нажатий на кнопку - Включить вибрацию браслета + Включить вибрацию Включить вибрацию браслета в ответ на исполняющееся при нажатии действие Максимальная задержка между нажатиями Максимальная задержка между нажатиями в миллисекундах From 9cedf63a5ae61cdecae7edfc2eb242a455e2b3b7 Mon Sep 17 00:00:00 2001 From: Jonas Date: Sun, 12 Nov 2017 13:01:50 +0000 Subject: [PATCH 25/55] Translated using Weblate (Spanish) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/es/ --- app/src/main/res/values-es/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 07c345d87..97444a4eb 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -452,7 +452,7 @@ Inglés Medición de pulso todo el día - Una vez por minuto + Cada minuto Cada 5 minutos Cada 10 minutos Cada 30 minutos From 20208ca7a358e9cca4d9d283d6ed79d8b91e267f Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 23:27:01 +0100 Subject: [PATCH 26/55] Work around non-working outlook notifications See #851 --- .../gadgetbridge/externalevents/NotificationListener.java | 6 ++++-- 1 file changed, 4 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 181f045d0..7ecdeb32a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/NotificationListener.java @@ -441,10 +441,12 @@ public class NotificationListener extends NotificationListenerService { NotificationType type = AppNotificationType.getInstance().get(source); //ignore notifications marked as LocalOnly https://developer.android.com/reference/android/app/Notification.html#FLAG_LOCAL_ONLY + //some Apps always mark their notifcations as read-only if (NotificationCompat.getLocalOnly(notification) && - //WeChat always marks its notifications as LocalOnly, do not ignore them - type != NotificationType.WECHAT) + type != NotificationType.WECHAT && + type != NotificationType.OUTLOOK) { return true; + } Prefs prefs = GBApplication.getPrefs(); if (!prefs.getBoolean("notifications_generic_whenscreenon", false)) { From 92c9d347a63650eae2c1911a9518dee606f5c220 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Tue, 14 Nov 2017 23:36:13 +0100 Subject: [PATCH 27/55] bump version, add changelog --- CHANGELOG.md | 6 ++++++ app/build.gradle | 4 ++-- app/src/main/res/xml/changelog_master.xml | 6 ++++++ fastlane/metadata/android/en-US/changelogs/112.txt | 4 ++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/112.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 40b10e5f8..7f4c40660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ### Changelog +#### Version 0.22.4 +* Mi Band 2/Bip/Cor: Whole day HR support +* Mi Band 2/Bip/Cor: Prevent writing a lot of HR samples to the database when not using the live activity feature +* Pebble: Fix some nasty crashes which occur since 0.22.0 +* Workround for non-working notifcations from wechat and outlook + #### Version 0.22.3 * Amazfit Bip: Allow flashing watchfaces * Amazfit Cor: Fix flashing new .res files diff --git a/app/build.gradle b/app/build.gradle index 2cafd8481..e2967aa1f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,8 +26,8 @@ android { targetSdkVersion 25 // note: always bump BOTH versionCode and versionName! - versionName "0.22.3" - versionCode 111 + versionName "0.22.4" + versionCode 112 vectorDrawables.useSupportLibrary = true } buildTypes { diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml index 645396b52..5e93b37b0 100644 --- a/app/src/main/res/xml/changelog_master.xml +++ b/app/src/main/res/xml/changelog_master.xml @@ -1,5 +1,11 @@ + + Mi Band 2/Bip/Cor: Whole day HR support + Mi Band 2/Bip/Cor: Prevent writing a lot of HR samples to the database when not using the live activity feature + Pebble: Fix some nasty crashes which occur since 0.22.0 + Workround for non-working notifcations from wechat and outlook + Amazfit Bip: Allow flashing watchfaces Amazfit Cor: Fix flashing new .res files diff --git a/fastlane/metadata/android/en-US/changelogs/112.txt b/fastlane/metadata/android/en-US/changelogs/112.txt new file mode 100644 index 000000000..cd91d1333 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/112.txt @@ -0,0 +1,4 @@ +* Mi Band 2/Bip/Cor: Whole day HR support +* Mi Band 2/Bip/Cor: Prevent writing a lot of HR samples to the database when not using the live activity feature +* Pebble: Fix some nasty crashes which occur since 0.22.0 +* Workround for non-working notifcations from wechat and outlook From 797ad096dc884cc2a6804d372a82ccaee656bf9e Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sun, 19 Nov 2017 16:39:44 +0100 Subject: [PATCH 28/55] Don't add the fetch activity action button on KK Fixes #886 Add accent color also on first notification creation #759 --- .../java/nodomain/freeyourgadget/gadgetbridge/util/GB.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 e124276a0..47aedf82e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GB.java @@ -96,7 +96,7 @@ public class GB { deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_DISCONNECT); PendingIntent disconnectPendingIntent = PendingIntent.getService(context, 0, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT); builder.addAction(R.drawable.ic_notification_disconnected, context.getString(R.string.controlcenter_disconnect), disconnectPendingIntent); - if (DeviceHelper.getInstance().getCoordinator(device).supportsActivityDataFetching()) { + if (GBApplication.isRunningLollipopOrLater() && DeviceHelper.getInstance().getCoordinator(device).supportsActivityDataFetching()) { //for some reason this fails on KK deviceCommunicationServiceIntent.setAction(DeviceService.ACTION_FETCH_ACTIVITY_DATA); PendingIntent fetchPendingIntent = PendingIntent.getService(context, 1, deviceCommunicationServiceIntent, PendingIntent.FLAG_ONE_SHOT); builder.addAction(R.drawable.ic_action_fetch_activity_data, context.getString(R.string.controlcenter_fetch_activity_data), fetchPendingIntent); @@ -122,6 +122,7 @@ public class GB { .setContentText(text) .setSmallIcon(R.drawable.ic_notification_disconnected) .setContentIntent(getContentIntent(context)) + .setColor(context.getResources().getColor(R.color.accent)) .setOngoing(true); if (GBApplication.getPrefs().getString("last_device_address", null) != null) { Intent deviceCommunicationServiceIntent = new Intent(context, DeviceCommunicationService.class); From c325ba1a22e60ef6ab6624b648d6f41f36f2417a Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 19 Nov 2017 23:46:24 +0100 Subject: [PATCH 29/55] Amazfit Bip: show find phone events (not yet supported) --- .../service/devices/huami/HuamiDeviceEvent.java | 4 +++- .../service/devices/miband2/MiBand2Support.java | 13 ++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiDeviceEvent.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiDeviceEvent.java index db087979c..7a643eacf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiDeviceEvent.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiDeviceEvent.java @@ -24,8 +24,10 @@ public class HuamiDeviceEvent { public static final byte BUTTON_PRESSED = 0x04; public static final byte START_NONWEAR = 0x06; public static final byte CALL_REJECT = 0x07; - public static final byte CALL_ACCEPT = 0x09; + public static final byte FIND_PHONE_START = 0x08; + public static final byte CALL_IGNORE = 0x09; public static final byte ALARM_TOGGLED = 0x0a; public static final byte BUTTON_PRESSED_LONG = 0x0b; public static final byte TICK_30MIN = 0x0e; // unsure + public static final byte FIND_PHONE_STOP = 0x0f; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java index e10cd3504..b05bba84a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/MiBand2Support.java @@ -923,9 +923,10 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { callCmd.event = GBDeviceEventCallControl.Event.REJECT; evaluateGBDeviceEvent(callCmd); break; - case HuamiDeviceEvent.CALL_ACCEPT: - callCmd.event = GBDeviceEventCallControl.Event.ACCEPT; - evaluateGBDeviceEvent(callCmd); + case HuamiDeviceEvent.CALL_IGNORE: + LOG.info("ignore call (not yet supported)"); + //callCmd.event = GBDeviceEventCallControl.Event.IGNORE; + //evaluateGBDeviceEvent(callCmd); break; case HuamiDeviceEvent.BUTTON_PRESSED: LOG.info("button pressed"); @@ -952,6 +953,12 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport { case HuamiDeviceEvent.TICK_30MIN: LOG.info("Tick 30 min (?)"); break; + case HuamiDeviceEvent.FIND_PHONE_START: + LOG.info("find phone started (not yet supported)"); + break; + case HuamiDeviceEvent.FIND_PHONE_STOP: + LOG.info("find phone stopped (not yet supported)"); + break; default: LOG.warn("unhandled event " + value[0]); } From 36e50bddb02f30b17a854637e171c6773704f698 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 19 Nov 2017 23:47:06 +0100 Subject: [PATCH 30/55] remove obsolete comment --- .../gadgetbridge/devices/miband/MiBand2SampleProvider.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java index be6c7cd15..29fb3eeae 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java @@ -27,12 +27,6 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind; public class MiBand2SampleProvider extends AbstractMiBandSampleProvider { -// these come from Mi1 -// public static final int TYPE_LIGHT_SLEEP = 5; -// public static final int TYPE_ACTIVITY = -1; -// public static final int TYPE_UNKNOWN = -1; -// public static final int TYPE_NONWEAR = 3; -// public static final int TYPE_CHARGING = 6; // observed the following values so far: From b4bbd0323c139db1a39ec3d0a55503a999637b16 Mon Sep 17 00:00:00 2001 From: Zhong Jianxin Date: Tue, 14 Nov 2017 17:31:07 +0800 Subject: [PATCH 31/55] Combine multipart SMS message into messages by sender When receive SMS message, instead of generating multiple notifications by PDU size, after this change, there will be only one notification for each sender. --- .../externalevents/SMSReceiver.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java index 321514490..7056b20b9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/SMSReceiver.java @@ -26,6 +26,9 @@ import android.os.Bundle; import android.os.PowerManager; import android.telephony.SmsMessage; +import java.util.LinkedHashMap; +import java.util.Map; + import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; @@ -54,12 +57,22 @@ public class SMSReceiver extends BroadcastReceiver { if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); if (pdus != null) { - for (Object pdu1 : pdus) { - byte[] pdu = (byte[]) pdu1; - SmsMessage message = SmsMessage.createFromPdu(pdu); - notificationSpec.body = message.getDisplayMessageBody(); - notificationSpec.phoneNumber = message.getOriginatingAddress(); - if (notificationSpec.phoneNumber != null) { + int pduSize = pdus.length; + Map messageMap = new LinkedHashMap<>(); + SmsMessage[] messages = new SmsMessage[pduSize]; + for (int i = 0; i < pduSize; i++) { + messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]); + String originatingAddress = messages[i].getOriginatingAddress(); + if (!messageMap.containsKey(originatingAddress)) { + messageMap.put(originatingAddress, new StringBuilder()); + } + messageMap.get(originatingAddress).append(messages[i].getMessageBody()); + } + for (Map.Entry entry : messageMap.entrySet()) { + String originatingAddress = entry.getKey(); + if (originatingAddress != null) { + notificationSpec.body = entry.getValue().toString(); + notificationSpec.phoneNumber = originatingAddress; switch (GBApplication.getGrantedInterruptionFilter()) { case NotificationManager.INTERRUPTION_FILTER_ALL: break; From 879272deb7956ff4e3ba3aa68f86cae7dcd79233 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Wed, 29 Nov 2017 23:57:36 +0100 Subject: [PATCH 32/55] Weather: refactoring and support forecast for more than one day --- .../externalevents/AlarmReceiver.java | 7 +- .../WeatherNotificationReceiver.java | 6 +- .../gadgetbridge/impl/GBDeviceService.java | 11 +-- .../gadgetbridge/model/DeviceService.java | 11 +-- .../gadgetbridge/model/WeatherSpec.java | 98 ++++++++++++++++++- .../service/DeviceCommunicationService.java | 47 +++++---- .../devices/amazfitbip/AmazfitBipSupport.java | 19 ++-- .../AppMessageHandlerTimeStylePebble.java | 7 +- .../devices/pebble/PebbleProtocol.java | 14 ++- .../pebble/webview/CurrentPosition.java | 24 ++++- .../devices/pebble/webview/JSInterface.java | 4 +- .../notification/ParcelableWeather2.java | 90 ++++++----------- 12 files changed, 209 insertions(+), 129 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java index 3b02d63a3..6a5823beb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/AlarmReceiver.java @@ -54,7 +54,12 @@ public class AlarmReceiver extends BroadcastReceiver { PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, new Intent("DAILY_ALARM"), 0); AlarmManager am = (AlarmManager) (context.getSystemService(Context.ALARM_SERVICE)); - am.setInexactRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + 10000, AlarmManager.INTERVAL_DAY, pendingIntent); + if (am != null) { + am.setInexactRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + 10000, AlarmManager.INTERVAL_DAY, pendingIntent); + } + else { + LOG.warn("could not get alarm manager!"); + } } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java index 809ebe0f5..8a02294df 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java @@ -35,7 +35,7 @@ public class WeatherNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if (!intent.getAction().contains("WEATHER_UPDATE_2")) { + if (intent.getAction() == null || !intent.getAction().contains("WEATHER_UPDATE_2")) { LOG.info("Wrong action"); return; } @@ -58,9 +58,7 @@ public class WeatherNotificationReceiver extends BroadcastReceiver { weatherSpec.currentConditionCode = weather.currentConditionCode; weatherSpec.todayMaxTemp = weather.todayHighTemp; weatherSpec.todayMinTemp = weather.todayLowTemp; - weatherSpec.tomorrowConditionCode = weather.forecastConditionCode; - weatherSpec.tomorrowMaxTemp = weather.forecastHighTemp; - weatherSpec.tomorrowMinTemp = weather.forecastLowTemp; + weatherSpec.forecasts = weather.forecasts; Weather.getInstance().setWeatherSpec(weatherSpec); GBApplication.deviceService().onSendWeather(weatherSpec); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java index f7c2e09a0..9e9210ccc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/impl/GBDeviceService.java @@ -373,16 +373,7 @@ public class GBDeviceService implements DeviceService { @Override public void onSendWeather(WeatherSpec weatherSpec) { Intent intent = createIntent().setAction(ACTION_SEND_WEATHER) - .putExtra(EXTRA_WEATHER_TIMESTAMP, weatherSpec.timestamp) - .putExtra(EXTRA_WEATHER_LOCATION, weatherSpec.location) - .putExtra(EXTRA_WEATHER_CURRENTTEMP, weatherSpec.currentTemp) - .putExtra(EXTRA_WEATHER_CURRENTCONDITIONCODE, weatherSpec.currentConditionCode) - .putExtra(EXTRA_WEATHER_CURRENTCONDITION, weatherSpec.currentCondition) - .putExtra(EXTRA_WEATHER_TODAYMAXTEMP, weatherSpec.todayMaxTemp) - .putExtra(EXTRA_WEATHER_TODAYMINTEMP, weatherSpec.todayMinTemp) - .putExtra(EXTRA_WEATHER_TOMORROWMAXTEMP, weatherSpec.tomorrowMaxTemp) - .putExtra(EXTRA_WEATHER_TOMORROWMINTEMP, weatherSpec.tomorrowMinTemp) - .putExtra(EXTRA_WEATHER_TOMORROWCONDITIONCODE, weatherSpec.tomorrowConditionCode); + .putExtra(EXTRA_WEATHER, weatherSpec); invokeService(intent); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java index f9e9575b1..1e68558c5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/DeviceService.java @@ -104,16 +104,7 @@ public interface DeviceService extends EventHandler { String EXTRA_BOOLEAN_ENABLE = "enable_realtime_steps"; String EXTRA_INTERVAL_SECONDS = "interval_seconds"; - String EXTRA_WEATHER_TIMESTAMP = "weather_timestamp"; - String EXTRA_WEATHER_LOCATION = "weather_location"; - String EXTRA_WEATHER_CURRENTTEMP = "weather_currenttemp"; - String EXTRA_WEATHER_CURRENTCONDITIONCODE = "weather_currentconditioncode"; - String EXTRA_WEATHER_CURRENTCONDITION = "currentcondition"; - String EXTRA_WEATHER_TODAYMAXTEMP = "weather_todaymaxtemp"; - String EXTRA_WEATHER_TODAYMINTEMP = "weather_todaymintemp"; - String EXTRA_WEATHER_TOMORROWMAXTEMP = "weather_tomorrowmaxtemp"; - String EXTRA_WEATHER_TOMORROWMINTEMP = "weather_tomorrowmintemp"; - String EXTRA_WEATHER_TOMORROWCONDITIONCODE = "weather_tomorrowconditioncode"; + String EXTRA_WEATHER = "weather"; /** * Use EXTRA_REALTIME_SAMPLE instead diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java index a728afa05..267c5c98a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java @@ -16,8 +16,24 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.model; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + // FIXME: document me and my fields, including units -public class WeatherSpec { +public class WeatherSpec implements Parcelable { + public static final Creator CREATOR = new Creator() { + @Override + public WeatherSpec createFromParcel(Parcel in) { + return new WeatherSpec(in); + } + + @Override + public WeatherSpec[] newArray(int size) { + return new WeatherSpec[size]; + } + }; public int timestamp; public String location; public int currentTemp; @@ -25,7 +41,81 @@ public class WeatherSpec { public String currentCondition; public int todayMaxTemp; public int todayMinTemp; - public int tomorrowMaxTemp; - public int tomorrowMinTemp; - public int tomorrowConditionCode; + public ArrayList forecasts = new ArrayList<>(); + + public WeatherSpec() { + + } + + protected WeatherSpec(Parcel in) { + timestamp = in.readInt(); + location = in.readString(); + currentTemp = in.readInt(); + currentConditionCode = in.readInt(); + currentCondition = in.readString(); + todayMaxTemp = in.readInt(); + todayMinTemp = in.readInt(); + in.readList(forecasts, Forecast.class.getClassLoader()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(timestamp); + dest.writeString(location); + dest.writeInt(currentTemp); + dest.writeInt(currentConditionCode); + dest.writeString(currentCondition); + dest.writeInt(todayMaxTemp); + dest.writeInt(todayMinTemp); + dest.writeList(forecasts); + } + + public static class Forecast implements Parcelable { + public static final Creator CREATOR = new Creator() { + @Override + public Forecast createFromParcel(Parcel in) { + return new Forecast(in); + } + + @Override + public Forecast[] newArray(int size) { + return new Forecast[size]; + } + }; + public int minTemp; + public int maxTemp; + public int conditionCode; + + public Forecast() { + } + + public Forecast(int minTemp, int maxTemp, int conditionCode) { + this.minTemp = minTemp; + this.maxTemp = maxTemp; + this.conditionCode = conditionCode; + } + + Forecast(Parcel in) { + minTemp = in.readInt(); + maxTemp = in.readInt(); + conditionCode = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(minTemp); + dest.writeInt(maxTemp); + dest.writeInt(conditionCode); + } + } } 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 1276b1a29..f50ce7723 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -50,6 +50,7 @@ import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothPairingRequestReceiver; +//import nodomain.freeyourgadget.gadgetbridge.externalevents.CMWeatherReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.CalendarReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.MusicPlaybackReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.PebbleReceiver; @@ -149,16 +150,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOT import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOTIFICATION_TYPE; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_VIBRATION_INTENSITY; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_CURRENTCONDITION; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_CURRENTCONDITIONCODE; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_CURRENTTEMP; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_LOCATION; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_TIMESTAMP; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_TODAYMAXTEMP; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_TODAYMINTEMP; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_TOMORROWCONDITIONCODE; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_TOMORROWMAXTEMP; -import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER_TOMORROWMINTEMP; +import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_WEATHER; public class DeviceCommunicationService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener { private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class); @@ -182,6 +174,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere private AlarmReceiver mAlarmReceiver = null; private CalendarReceiver mCalendarReceiver = null; + //private CMWeatherReceiver mCMWeatherReceiver = null; private Random mRandom = new Random(); private final String[] mMusicActions = { @@ -214,7 +207,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action.equals(GBDevice.ACTION_DEVICE_CHANGED)) { + if (GBDevice.ACTION_DEVICE_CHANGED.equals(action)) { GBDevice device = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE); if (mGBDevice != null && mGBDevice.equals(device)) { mGBDevice = device; @@ -540,18 +533,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere break; } case ACTION_SEND_WEATHER: { - WeatherSpec weatherSpec = new WeatherSpec(); - weatherSpec.timestamp = intent.getIntExtra(EXTRA_WEATHER_TIMESTAMP, 0); - weatherSpec.location = intent.getStringExtra(EXTRA_WEATHER_LOCATION); - weatherSpec.currentTemp = intent.getIntExtra(EXTRA_WEATHER_CURRENTTEMP, 0); - weatherSpec.currentConditionCode = intent.getIntExtra(EXTRA_WEATHER_CURRENTCONDITIONCODE, 0); - weatherSpec.currentCondition = intent.getStringExtra(EXTRA_WEATHER_CURRENTCONDITION); - weatherSpec.todayMaxTemp = intent.getIntExtra(EXTRA_WEATHER_TODAYMAXTEMP, 0); - weatherSpec.todayMinTemp = intent.getIntExtra(EXTRA_WEATHER_TODAYMINTEMP, 0); - weatherSpec.tomorrowMaxTemp = intent.getIntExtra(EXTRA_WEATHER_TOMORROWMAXTEMP, 0); - weatherSpec.tomorrowMinTemp = intent.getIntExtra(EXTRA_WEATHER_TOMORROWMINTEMP, 0); - weatherSpec.tomorrowConditionCode = intent.getIntExtra(EXTRA_WEATHER_TOMORROWCONDITIONCODE, 0); - mDeviceSupport.onSendWeather(weatherSpec); + WeatherSpec weatherSpec = intent.getParcelableExtra(EXTRA_WEATHER); + if (weatherSpec != null) { + mDeviceSupport.onSendWeather(weatherSpec); + } break; } } @@ -674,6 +659,12 @@ public class DeviceCommunicationService extends Service implements SharedPrefere filter.addAction(AlarmClockReceiver.ALARM_DONE_ACTION); registerReceiver(mAlarmClockReceiver, filter); } + /* + if (mCMWeatherReceiver == null) { + mCMWeatherReceiver = new CMWeatherReceiver(); + registerReceiver(mCMWeatherReceiver, new IntentFilter("HOURLY_ALARM")); + } + */ } else { if (mPhoneCallReceiver != null) { unregisterReceiver(mPhoneCallReceiver); @@ -708,6 +699,12 @@ public class DeviceCommunicationService extends Service implements SharedPrefere unregisterReceiver(mAlarmClockReceiver); mAlarmClockReceiver = null; } + /* + if (mCMWeatherReceiver != null) { + unregisterReceiver(mCMWeatherReceiver); + mCMWeatherReceiver = null; + } + */ } } @@ -725,7 +722,9 @@ public class DeviceCommunicationService extends Service implements SharedPrefere setDeviceSupport(null); NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - nm.cancel(GB.NOTIFICATION_ID); // need to do this because the updated notification won't be cancelled when service stops + if (nm != null) { + nm.cancel(GB.NOTIFICATION_ID); // need to do this because the updated notification won't be cancelled when service stops + } } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index 2fda8ca7a..0fe9486e3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -137,7 +137,7 @@ public class AmazfitBipSupport extends MiBand2Support { supportsConditionString = true; } - final byte NR_DAYS = 2; + final byte NR_DAYS = (byte) (1 + weatherSpec.forecasts.size()); int bytesPerDay = 4; int conditionsLength = 0; if (supportsConditionString) { @@ -164,14 +164,17 @@ public class AmazfitBipSupport extends MiBand2Support { buf.put(weatherSpec.currentCondition.getBytes()); buf.put((byte) 0); // } - condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.tomorrowConditionCode); - buf.put(condition); - buf.put(condition); - buf.put((byte) (weatherSpec.tomorrowMaxTemp - 273)); - buf.put((byte) (weatherSpec.tomorrowMinTemp - 273)); - if (supportsConditionString) { - buf.put((byte) 0); // not yet in weatherspec + for (WeatherSpec.Forecast forecast : weatherSpec.forecasts) { + condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.conditionCode); + + buf.put(condition); + buf.put(condition); + buf.put((byte) (forecast.maxTemp - 273)); + buf.put((byte) (forecast.minTemp - 273)); + if (supportsConditionString) { + buf.put((byte) 0); // not yet in weatherspec + } } builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerTimeStylePebble.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerTimeStylePebble.java index 243081a6e..b31241ab4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerTimeStylePebble.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerTimeStylePebble.java @@ -141,7 +141,12 @@ class AppMessageHandlerTimeStylePebble extends AppMessageHandler { pairs.add(new Pair<>(messageKeys.get("WeatherUseNightIcon"), (Object) (isNight ? 1 : 0))); pairs.add(new Pair<>(messageKeys.get("WeatherTemperature"), (Object) (weatherSpec.currentTemp - 273))); pairs.add(new Pair<>(messageKeys.get("WeatherCondition"), (Object) (getIconForConditionCode(weatherSpec.currentConditionCode, isNight)))); - pairs.add(new Pair<>(messageKeys.get("WeatherForecastCondition"), (Object) (getIconForConditionCode(weatherSpec.tomorrowConditionCode, isNight)))); + + if (weatherSpec.forecasts.size() > 0) { + WeatherSpec.Forecast tomorrow = weatherSpec.forecasts.get(0); + pairs.add(new Pair<>(messageKeys.get("WeatherForecastCondition"), (Object) (getIconForConditionCode(tomorrow.conditionCode, isNight)))); + } + pairs.add(new Pair<>(messageKeys.get("WeatherForecastHighTemp"), (Object) (weatherSpec.todayMaxTemp - 273))); pairs.add(new Pair<>(messageKeys.get("WeatherForecastLowTemp"), (Object) (weatherSpec.todayMinTemp - 273))); 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 e9d6a21dd..c5c7750e2 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 @@ -1227,8 +1227,16 @@ public class PebbleProtocol extends GBDeviceProtocol { short currentTemp = (short) (weatherSpec.currentTemp - 273); short todayMax = (short) (weatherSpec.todayMaxTemp - 273); short todayMin = (short) (weatherSpec.todayMinTemp - 273); - short tomorrowMax = (short) (weatherSpec.tomorrowMaxTemp - 273); - short tomorrowMin = (short) (weatherSpec.tomorrowMinTemp - 273); + short tomorrowMax = 0; + short tomorrowMin = 0; + int tomorrowConditionCode = 0; + if (weatherSpec.forecasts.size() > 0) { + WeatherSpec.Forecast tomorrow = weatherSpec.forecasts.get(0); + tomorrowMax = (short) (tomorrow.maxTemp - 273); + tomorrowMin = (short) (tomorrow.minTemp - 273); + tomorrowConditionCode = tomorrow.conditionCode; + } + String units = GBApplication.getPrefs().getString(SettingsActivity.PREF_MEASUREMENT_SYSTEM, GBApplication.getContext().getString(R.string.p_unit_metric)); if (units.equals(GBApplication.getContext().getString(R.string.p_unit_imperial))) { currentTemp = (short) (currentTemp * 1.8f + 32); @@ -1261,7 +1269,7 @@ public class PebbleProtocol extends GBDeviceProtocol { buf.put(Weather.mapToPebbleCondition(weatherSpec.currentConditionCode)); buf.putShort(todayMax); buf.putShort(todayMin); - buf.put(Weather.mapToPebbleCondition(weatherSpec.tomorrowConditionCode)); + buf.put(Weather.mapToPebbleCondition(tomorrowConditionCode)); buf.putShort(tomorrowMax); buf.putShort(tomorrowMin); buf.putInt(weatherSpec.timestamp); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/CurrentPosition.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/CurrentPosition.java index d1e961dca..89efb96d4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/CurrentPosition.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/CurrentPosition.java @@ -30,13 +30,16 @@ import org.slf4j.LoggerFactory; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; -class CurrentPosition { +public class CurrentPosition { private static final Logger LOG = LoggerFactory.getLogger(CurrentPosition.class); + private Location lastKnownLocation; + private float latitude, longitude; + long timestamp; double altitude; - float latitude, longitude, accuracy, speed; + float accuracy, speed; float getLatitude() { return latitude; @@ -46,10 +49,19 @@ class CurrentPosition { return longitude; } - CurrentPosition() { + public Location getLastKnownLocation() { + return lastKnownLocation; + } + + public CurrentPosition() { Prefs prefs = GBApplication.getPrefs(); this.latitude = prefs.getFloat("location_latitude", 0); this.longitude = prefs.getFloat("location_longitude", 0); + + lastKnownLocation = new Location("preferences"); + lastKnownLocation.setLatitude(this.latitude); + lastKnownLocation.setLongitude(this.longitude); + LOG.info("got longitude/latitude from preferences: " + latitude + "/" + longitude); this.timestamp = System.currentTimeMillis() - 86400000; //let accessor know this value is really old @@ -58,10 +70,14 @@ class CurrentPosition { prefs.getBoolean("use_updated_location_if_available", false)) { LocationManager locationManager = (LocationManager) GBApplication.getContext().getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria(); - String provider = locationManager.getBestProvider(criteria, false); + String provider = null; + if (locationManager != null) { + provider = locationManager.getBestProvider(criteria, false); + } if (provider != null) { Location lastKnownLocation = locationManager.getLastKnownLocation(provider); if (lastKnownLocation != null) { + this.lastKnownLocation = lastKnownLocation; this.timestamp = lastKnownLocation.getTime(); this.timestamp = System.currentTimeMillis() - 1000; //TODO: request updating the location and don't fake its age diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/JSInterface.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/JSInterface.java index 6e972e5a8..7ba1b4fc9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/JSInterface.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/JSInterface.java @@ -227,8 +227,8 @@ public class JSInterface { geoPosition.put("timestamp", currentPosition.timestamp); - coords.put("latitude", currentPosition.latitude); - coords.put("longitude", currentPosition.longitude); + coords.put("latitude", currentPosition.getLatitude()); + coords.put("longitude", currentPosition.getLongitude()); coords.put("accuracy", currentPosition.accuracy); coords.put("altitude", currentPosition.altitude); coords.put("speed", currentPosition.speed); diff --git a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java index 70870a08d..a44ac0757 100644 --- a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java +++ b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java @@ -26,7 +26,10 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; + import nodomain.freeyourgadget.gadgetbridge.model.Weather; +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; public class ParcelableWeather2 implements Parcelable { private static final Logger LOG = LoggerFactory.getLogger(ParcelableWeather2.class); @@ -42,12 +45,9 @@ public class ParcelableWeather2 implements Parcelable { private String[] currentConditionType = null; public int currentConditionCode = 3200; - private String[] forecastConditionType = null; - public int forecastConditionCode = 3200; public int todayLowTemp = 0; public int todayHighTemp = 0; - public int forecastLowTemp = 0; - public int forecastHighTemp = 0; + public ArrayList forecasts = new ArrayList<>(); public JSONObject reconstructedWeather = null; public JSONObject reconstructedForecast = null; @@ -98,21 +98,23 @@ public class ParcelableWeather2 implements Parcelable { e.printStackTrace(); } LOG.debug("Weather JSON for WEBVIEW: " + reconstructedWeather.toString()); - //fetch immediate next forecast - if (--conditions > 0) { - int timeOffset = 86400000; //manually determined - reconstructedForecast = new JSONObject(); - JSONArray list = new JSONArray(); - JSONObject city = new JSONObject(); + //fetch forecasts + int timeOffset = 0; + + JSONArray list = new JSONArray(); + JSONObject city = new JSONObject(); + while (--conditions > 0) { + timeOffset += 86400000; //manually determined JSONObject item = new JSONObject(); condition = new JSONObject(); main = new JSONObject(); weather = new JSONArray(); Bundle forecastBundle = in.readBundle(); - forecastConditionType = forecastBundle.getStringArray("weather_condition_types"); - forecastConditionCode = weatherConditionTypesToOpenWeatherMapIds(forecastConditionType[0]); - forecastLowTemp = forecastBundle.getInt("weather_low_temp"); - forecastHighTemp = forecastBundle.getInt("weather_high_temp"); + String[] forecastConditionType = forecastBundle.getStringArray("weather_condition_types"); + int forecastConditionCode = weatherConditionTypesToOpenWeatherMapIds(forecastConditionType[0]); + int forecastLowTemp = forecastBundle.getInt("weather_low_temp"); + int forecastHighTemp = forecastBundle.getInt("weather_high_temp"); + forecasts.add(new WeatherSpec.Forecast(forecastLowTemp, forecastHighTemp, forecastConditionCode)); try { condition.put("id", forecastConditionCode); condition.put("main", forecastBundle.getString("weather_condition_text")); @@ -125,58 +127,29 @@ public class ParcelableWeather2 implements Parcelable { main.put("temp_max", forecastHighTemp); //forecast - //"city":{"id":3181913,"name":"Bolzano","coord":{"lat":46.4927,"lon":11.3336},"country":"IT"} - city.put("name", location); - city.put("country", "World"); - reconstructedForecast.put("city", city); item.put("dt", (time / 1000) + timeOffset); item.put("main", main); item.put("weather", weather); list.put(item); } catch (JSONException e) { - e.printStackTrace(); + LOG.error("error while construction JSON", e); } - - // get the rest - while (--conditions > 0) { - conditionBundle = in.readBundle(); - conditionBundle.getString("weather_condition_text"); - weatherConditionTypesToOpenWeatherMapIds(conditionBundle.getStringArray("weather_condition_types")[0]); - conditionBundle.getInt("weather_current_temp"); - item = new JSONObject(); - condition = new JSONObject(); - main = new JSONObject(); - weather = new JSONArray(); - timeOffset += 86400000; - try { - condition.put("id", weatherConditionTypesToOpenWeatherMapIds(conditionBundle.getStringArray("weather_condition_types")[0])); - condition.put("main", conditionBundle.getString("weather_condition_text")); - condition.put("icon", Weather.mapToOpenWeatherMapIcon(weatherConditionTypesToOpenWeatherMapIds(conditionBundle.getStringArray("weather_condition_types")[0]))); - weather.put(condition); - - main.put("temp", conditionBundle.getInt("weather_current_temp")); - main.put("humidity", conditionBundle.getInt("weather_humidity_value")); - main.put("temp_min", conditionBundle.getInt("weather_low_temp")); - main.put("temp_max", conditionBundle.getInt("weather_high_temp")); - - item.put("dt", (time / 1000) + timeOffset); - item.put("main", main); - item.put("weather", weather); - list.put(item); - } catch (JSONException e) { - e.printStackTrace(); - } - } - try { - reconstructedForecast.put("cnt", list.length()); - reconstructedForecast.put("list", list); - - } catch (JSONException e) { - e.printStackTrace(); - } - LOG.debug("Forecast JSON for WEBVIEW: " + reconstructedForecast.toString()); } + try { + //"city":{"id":3181913,"name":"Bolzano","coord":{"lat":46.4927,"lon":11.3336},"country":"IT"} + city.put("name", location); + city.put("country", "World"); + + reconstructedForecast = new JSONObject(); + reconstructedForecast.put("city", city); + reconstructedForecast.put("cnt", list.length()); + reconstructedForecast.put("list", list); + + } catch (JSONException e) { + LOG.error("error while construction JSON", e); + } + LOG.debug("Forecast JSON for WEBVIEW: " + reconstructedForecast.toString()); } } @@ -309,4 +282,5 @@ public class ParcelableWeather2 implements Parcelable { } return 3200; } + } From 0befc1a95e46db2099339651233c7ea26d4caf93 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 30 Nov 2017 10:24:31 +0100 Subject: [PATCH 33/55] Weather refactoring No longer save an instance of ParcelableWeather2, rely on our WeatherSpec instead which now has all forecast data and save reconstructed owm weather json in Weather --- .../WeatherNotificationReceiver.java | 25 +++---- .../gadgetbridge/model/Weather.java | 28 ++++--- .../gadgetbridge/model/WeatherSpec.java | 2 +- .../pebble/AppMessageHandlerPebStyle.java | 4 +- .../devices/pebble/webview/GBWebClient.java | 10 +-- .../notification/ParcelableWeather2.java | 75 ++++++++----------- 6 files changed, 68 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java index 8a02294df..102bd22a5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/WeatherNotificationReceiver.java @@ -39,26 +39,21 @@ public class WeatherNotificationReceiver extends BroadcastReceiver { LOG.info("Wrong action"); return; } - ParcelableWeather2 weather = null; + ParcelableWeather2 parcelableWeather2 = null; try { - weather = intent.getParcelableExtra("ru.gelin.android.weather.notification.EXTRA_WEATHER"); + parcelableWeather2 = intent.getParcelableExtra("ru.gelin.android.weather.notification.EXTRA_WEATHER"); } catch (RuntimeException e) { - e.printStackTrace(); + LOG.error("cannot get ParcelableWeather2", e); } - if (weather != null) { - Weather.getInstance().setWeather2(weather); - LOG.info("weather in " + weather.location + " is " + weather.currentCondition + " (" + (weather.currentTemp - 273) + "°C)"); + if (parcelableWeather2 != null) { + Weather weather = Weather.getInstance(); + weather.setReconstructedOWMWeather(parcelableWeather2.reconstructedOWMWeather); + weather.setReconstructedOWMForecast(parcelableWeather2.reconstructedOWMForecast); + + WeatherSpec weatherSpec = parcelableWeather2.weatherSpec; + LOG.info("weather in " + weatherSpec.location + " is " + weatherSpec.currentCondition + " (" + (weatherSpec.currentTemp - 273) + "°C)"); - WeatherSpec weatherSpec = new WeatherSpec(); - weatherSpec.timestamp = (int) (weather.queryTime / 1000); - weatherSpec.location = weather.location; - weatherSpec.currentTemp = weather.currentTemp; - weatherSpec.currentCondition = weather.currentCondition; - weatherSpec.currentConditionCode = weather.currentConditionCode; - weatherSpec.todayMaxTemp = weather.todayHighTemp; - weatherSpec.todayMinTemp = weather.todayLowTemp; - weatherSpec.forecasts = weather.forecasts; Weather.getInstance().setWeatherSpec(weatherSpec); GBApplication.deviceService().onSendWeather(weatherSpec); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java index a5aa9daf0..d85308099 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java @@ -16,19 +16,13 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.model; -import ru.gelin.android.weather.notification.ParcelableWeather2; +import org.json.JSONObject; public class Weather { - private ParcelableWeather2 weather2 = null; private WeatherSpec weatherSpec = null; - public ParcelableWeather2 getWeather2() { - return weather2; - } - - public void setWeather2(ParcelableWeather2 weather2) { - this.weather2 = weather2; - } + private JSONObject reconstructedOWMWeather = null; + private JSONObject reconstructedOWMForecast = null; public WeatherSpec getWeatherSpec() { return weatherSpec; @@ -38,6 +32,22 @@ public class Weather { this.weatherSpec = weatherSpec; } + public JSONObject getReconstructedOWMWeather() { + return reconstructedOWMWeather; + } + + public void setReconstructedOWMWeather(JSONObject reconstructedOWMWeather) { + this.reconstructedOWMWeather = reconstructedOWMWeather; + } + + public JSONObject getReconstructedOWMForecast() { + return reconstructedOWMForecast; + } + + public void setReconstructedOWMForecast(JSONObject reconstructedOWMForecast) { + this.reconstructedOWMForecast = reconstructedOWMForecast; + } + private static final Weather weather = new Weather(); public static Weather getInstance() {return weather;} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java index 267c5c98a..8ea43c05d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/WeatherSpec.java @@ -37,7 +37,7 @@ public class WeatherSpec implements Parcelable { public int timestamp; public String location; public int currentTemp; - public int currentConditionCode; + public int currentConditionCode = 3200; public String currentCondition; public int todayMaxTemp; public int todayMinTemp; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerPebStyle.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerPebStyle.java index f2add3eb4..cd60ccff1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerPebStyle.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/AppMessageHandlerPebStyle.java @@ -28,7 +28,7 @@ import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor; import nodomain.freeyourgadget.gadgetbridge.model.Weather; -import ru.gelin.android.weather.notification.ParcelableWeather2; +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; class AppMessageHandlerPebStyle extends AppMessageHandler { public static final int KEY_AMPM_TEXT = 21; @@ -92,7 +92,7 @@ class AppMessageHandlerPebStyle extends AppMessageHandler { //WEATHER - ParcelableWeather2 weather = Weather.getInstance().getWeather2(); + WeatherSpec weather = Weather.getInstance().getWeatherSpec(); if (weather != null) { //comment the same key in the general section above! pairs.add(new Pair<>(KEY_LOCATION_SERVICE, (Object) 0)); //0 auto, 1 manual diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/GBWebClient.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/GBWebClient.java index 26888457d..311c33dca 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/GBWebClient.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/webview/GBWebClient.java @@ -132,7 +132,7 @@ public class GBWebClient extends WebViewClient { private static WebResourceResponse mimicOpenWeatherMapResponse(String type, String units) { - if (Weather.getInstance() == null || Weather.getInstance().getWeather2() == null) { + if (Weather.getInstance() == null) { LOG.warn("WEBVIEW - Weather instance is null, cannot update weather"); return null; } @@ -142,8 +142,8 @@ public class GBWebClient extends WebViewClient { try { JSONObject resp; - if ("/data/2.5/weather".equals(type) && Weather.getInstance().getWeather2().reconstructedWeather != null) { - resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedWeather.toString()); + if ("/data/2.5/weather".equals(type) && Weather.getInstance().getReconstructedOWMWeather() != null) { + resp = new JSONObject(Weather.getInstance().getReconstructedOWMWeather().toString()); JSONObject main = resp.getJSONObject("main"); @@ -152,8 +152,8 @@ public class GBWebClient extends WebViewClient { resp.put("cod", 200); resp.put("coord", coordObject(currentPosition)); resp.put("sys", sysObject(currentPosition)); -// } else if ("/data/2.5/forecast".equals(type) && Weather.getInstance().getWeather2().reconstructedForecast != null) { //this is wrong, as we only have daily data. Unfortunately it looks like daily forecasts cannot be reconstructed -// resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedForecast.toString()); +// } else if ("/data/2.5/forecast".equals(type) && Weather.getInstance().getWeather2().reconstructedOWMForecast != null) { //this is wrong, as we only have daily data. Unfortunately it looks like daily forecasts cannot be reconstructed +// resp = new JSONObject(Weather.getInstance().getWeather2().reconstructedOWMForecast.toString()); // // JSONObject city = resp.getJSONObject("city"); // city.put("coord", coordObject(currentPosition)); diff --git a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java index a44ac0757..0d136d470 100644 --- a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java +++ b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java @@ -26,8 +26,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; - import nodomain.freeyourgadget.gadgetbridge.model.Weather; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; @@ -35,22 +33,10 @@ public class ParcelableWeather2 implements Parcelable { private static final Logger LOG = LoggerFactory.getLogger(ParcelableWeather2.class); // getters and setters suck ;) + public WeatherSpec weatherSpec = new WeatherSpec(); - public long time = 0; - public long queryTime = 0; - public int version = 0; - public String location = ""; - public int currentTemp = 0; - public String currentCondition = ""; - - private String[] currentConditionType = null; - public int currentConditionCode = 3200; - public int todayLowTemp = 0; - public int todayHighTemp = 0; - public ArrayList forecasts = new ArrayList<>(); - - public JSONObject reconstructedWeather = null; - public JSONObject reconstructedForecast = null; + public JSONObject reconstructedOWMWeather = null; + public JSONObject reconstructedOWMForecast = null; private ParcelableWeather2(Parcel in) { int version = in.readInt(); @@ -59,45 +45,46 @@ public class ParcelableWeather2 implements Parcelable { } Bundle bundle = in.readBundle(); - location = bundle.getString("weather_location"); - time = bundle.getLong("weather_time"); - queryTime = bundle.getLong("weather_query_time"); + weatherSpec.location = bundle.getString("weather_location"); + long time = bundle.getLong("weather_time"); + long queryTime = bundle.getLong("weather_query_time"); + weatherSpec.timestamp = (int) (queryTime / 1000); bundle.getString("weather_forecast_url"); int conditions = bundle.getInt("weather_conditions"); if (conditions > 0) { Bundle conditionBundle = in.readBundle(); - reconstructedWeather = new JSONObject(); + reconstructedOWMWeather = new JSONObject(); JSONArray weather = new JSONArray(); JSONObject condition = new JSONObject(); JSONObject main = new JSONObject(); - currentCondition = conditionBundle.getString("weather_condition_text"); + weatherSpec.currentCondition = conditionBundle.getString("weather_condition_text"); conditionBundle.getStringArray("weather_condition_types"); - currentTemp = conditionBundle.getInt("weather_current_temp"); + weatherSpec.currentTemp = conditionBundle.getInt("weather_current_temp"); - currentConditionType = conditionBundle.getStringArray("weather_condition_types"); - currentConditionCode = weatherConditionTypesToOpenWeatherMapIds(currentConditionType[0]); - todayLowTemp = conditionBundle.getInt("weather_low_temp"); - todayHighTemp = conditionBundle.getInt("weather_high_temp"); + String[] currentConditionType = conditionBundle.getStringArray("weather_condition_types"); + weatherSpec.currentConditionCode = weatherConditionTypesToOpenWeatherMapIds(currentConditionType[0]); + weatherSpec.todayMinTemp = conditionBundle.getInt("weather_low_temp"); + weatherSpec.todayMaxTemp = conditionBundle.getInt("weather_high_temp"); try { - condition.put("id", currentConditionCode); - condition.put("main", currentCondition); - condition.put("icon", Weather.mapToOpenWeatherMapIcon(currentConditionCode)); + condition.put("id", weatherSpec.currentConditionCode); + condition.put("main", weatherSpec.currentCondition); + condition.put("icon", Weather.mapToOpenWeatherMapIcon(weatherSpec.currentConditionCode)); weather.put(condition); - main.put("temp", currentTemp); + main.put("temp", weatherSpec.currentTemp); main.put("humidity", conditionBundle.getInt("weather_humidity_value")); - main.put("temp_min", todayLowTemp); - main.put("temp_max", todayHighTemp); - main.put("name", location); + main.put("temp_min", weatherSpec.todayMinTemp); + main.put("temp_max", weatherSpec.todayMaxTemp); + main.put("name", weatherSpec.location); - reconstructedWeather.put("weather", weather); - reconstructedWeather.put("main", main); + reconstructedOWMWeather.put("weather", weather); + reconstructedOWMWeather.put("main", main); } catch (JSONException e) { e.printStackTrace(); } - LOG.debug("Weather JSON for WEBVIEW: " + reconstructedWeather.toString()); + LOG.debug("Weather JSON for WEBVIEW: " + reconstructedOWMWeather.toString()); //fetch forecasts int timeOffset = 0; @@ -114,7 +101,7 @@ public class ParcelableWeather2 implements Parcelable { int forecastConditionCode = weatherConditionTypesToOpenWeatherMapIds(forecastConditionType[0]); int forecastLowTemp = forecastBundle.getInt("weather_low_temp"); int forecastHighTemp = forecastBundle.getInt("weather_high_temp"); - forecasts.add(new WeatherSpec.Forecast(forecastLowTemp, forecastHighTemp, forecastConditionCode)); + weatherSpec.forecasts.add(new WeatherSpec.Forecast(forecastLowTemp, forecastHighTemp, forecastConditionCode)); try { condition.put("id", forecastConditionCode); condition.put("main", forecastBundle.getString("weather_condition_text")); @@ -138,18 +125,18 @@ public class ParcelableWeather2 implements Parcelable { } try { //"city":{"id":3181913,"name":"Bolzano","coord":{"lat":46.4927,"lon":11.3336},"country":"IT"} - city.put("name", location); + city.put("name", weatherSpec.location); city.put("country", "World"); - reconstructedForecast = new JSONObject(); - reconstructedForecast.put("city", city); - reconstructedForecast.put("cnt", list.length()); - reconstructedForecast.put("list", list); + reconstructedOWMForecast = new JSONObject(); + reconstructedOWMForecast.put("city", city); + reconstructedOWMForecast.put("cnt", list.length()); + reconstructedOWMForecast.put("list", list); } catch (JSONException e) { LOG.error("error while construction JSON", e); } - LOG.debug("Forecast JSON for WEBVIEW: " + reconstructedForecast.toString()); + LOG.debug("Forecast JSON for WEBVIEW: " + reconstructedOWMForecast.toString()); } } From 9dfde46bb02c35efa98790ebedcea3f80fae507f Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Thu, 30 Nov 2017 18:26:10 +0100 Subject: [PATCH 34/55] Amazfit Bip: send condition string also for forecast days String for forecasts are looked up from OWM condition ids, while the current condition string is already translated by WeatherNotification --- .../gadgetbridge/model/Weather.java | 160 ++++++++++++++++++ .../devices/amazfitbip/AmazfitBipSupport.java | 11 +- 2 files changed, 169 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java index d85308099..fd758aa86 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/Weather.java @@ -403,4 +403,164 @@ public class Weather { return -1; } } + + public static String getConditionString(int openWeatherMapCondition) { + switch (openWeatherMapCondition) { + case 200: + return "thunderstorm with light rain"; + case 201: + return "thunderstorm with rain"; + case 202: + return "thunderstorm with heavy rain"; + case 210: + return "light thunderstorm:"; + case 211: + return "thunderstorm"; + case 230: + return "thunderstorm with light drizzle"; + case 231: + return "thunderstorm with drizzle"; + case 232: + return "thunderstorm with heavy drizzle"; + case 212: + return "heavy thunderstorm"; + case 221: + return "ragged thunderstorm"; + //Group 3xx: Drizzle + case 300: + return "light intensity drizzle"; + case 301: + return "drizzle"; + case 302: + return "heavy intensity drizzle"; + case 310: + return "light intensity drizzle rain"; + case 311: + return "drizzle rain"; + case 312: + return "heavy intensity drizzle rain"; + case 313: + return "shower rain and drizzle"; + case 314: + return "heavy shower rain and drizzle"; + case 321: + return "shower drizzle"; + //Group 5xx: Rain + case 500: + return "light rain"; + case 501: + return "moderate rain"; + case 502: + return "heavy intensity rain"; + case 503: + return "very heavy rain"; + case 504: + return "extreme rain"; + case 511: + return "freezing rain"; + case 520: + return "light intensity shower rain"; + case 521: + return "shower rain"; + case 522: + return "heavy intensity shower rain"; + case 531: + return "ragged shower rain"; + //Group 6xx: Snow + case 600: + return "light snow"; + case 601: + return "snow"; + case 620: + return "light shower snow"; + case 602: + return "heavy snow"; + case 611: + return "sleet"; + case 612: + return "shower sleet"; + case 621: + return "shower snow"; + case 622: + return "heavy shower snow"; + case 615: + return "light rain and snow"; + case 616: + return "rain and snow"; + //Group 7xx: Atmosphere + case 701: + return "mist"; + case 711: + return "smoke"; + case 721: + return "haze"; + case 731: + return "sandcase dust whirls"; + case 741: + return "fog"; + case 751: + return "sand"; + case 761: + return "dust"; + case 762: + return "volcanic ash"; + case 771: + return "squalls"; + case 781: + return "tornado"; + case 900: + return "tornado"; + case 800: + return "clear sky"; + //Group 80x: Clouds + case 801: + return "few clouds"; + case 802: + return "scattered clouds"; + case 803: + return "broken clouds"; + case 804: + return "overcast clouds"; + //Group 90x: Extreme + case 901: + return "tropical storm"; + case 903: + return "cold"; + case 904: + return "hot"; + case 905: + return "windy"; + case 906: + return "hail"; + //Group 9xx: Additional + case 951: + return "calm"; + case 952: + return "light breeze"; + case 953: + return "gentle breeze"; + case 954: + return "moderate breeze"; + case 955: + return "fresh breeze"; + case 956: + return "strong breeze"; + case 957: + return "high windcase near gale"; + case 958: + return "gale"; + case 959: + return "severe gale"; + case 960: + return "storm"; + case 961: + return "violent storm"; + case 902: + return "hurricane"; + case 962: + return "hurricane"; + default: + return ""; + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index 0fe9486e3..bbaf76791 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -40,6 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; +import nodomain.freeyourgadget.gadgetbridge.model.Weather; import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertCategory; @@ -139,11 +140,16 @@ public class AmazfitBipSupport extends MiBand2Support { final byte NR_DAYS = (byte) (1 + weatherSpec.forecasts.size()); int bytesPerDay = 4; + int conditionsLength = 0; if (supportsConditionString) { bytesPerDay = 5; conditionsLength = weatherSpec.currentCondition.getBytes().length; + for (WeatherSpec.Forecast forecast : weatherSpec.forecasts) { + conditionsLength += Weather.getConditionString(forecast.conditionCode).getBytes().length; + } } + int length = 7 + bytesPerDay * NR_DAYS + conditionsLength; ByteBuffer buf = ByteBuffer.allocate(length); @@ -162,7 +168,7 @@ public class AmazfitBipSupport extends MiBand2Support { buf.put((byte) (weatherSpec.todayMinTemp - 273)); if (supportsConditionString) { buf.put(weatherSpec.currentCondition.getBytes()); - buf.put((byte) 0); // + buf.put((byte) 0); } for (WeatherSpec.Forecast forecast : weatherSpec.forecasts) { @@ -173,7 +179,8 @@ public class AmazfitBipSupport extends MiBand2Support { buf.put((byte) (forecast.maxTemp - 273)); buf.put((byte) (forecast.minTemp - 273)); if (supportsConditionString) { - buf.put((byte) 0); // not yet in weatherspec + buf.put(Weather.getConditionString(forecast.conditionCode).getBytes()); + buf.put((byte) 0); } } From 7beb79316571d99e9d59352f567338e3a531a608 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 2 Dec 2017 01:28:59 +0100 Subject: [PATCH 35/55] Amazfit Bip: Fix installation of new 0.1.0.11 firmware Also whitelist 0.0.9.49 and .59 --- .../amazfitbip/AmazfitBipFirmwareInfo.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java index d39d2f1c1..1f90a9de9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipFirmwareInfo.java @@ -36,12 +36,19 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { (byte) 0xa7, 0x26, (byte) 0xd0, (byte) 0xe6, 0x4a, 0x21, (byte) 0x88, (byte) 0xd4 }; - // guessed - at least it is the same accross current versions and different from other devices + // guessed - at least it is the same across versions from 0.0.7.x to 0.0.9.x + // and different from other devices private static final byte[] FW_HEADER = new byte[]{ 0x68, 0x46, 0x70, 0x47, 0x68, 0x46, 0x70, 0x47, 0x68, 0x46, 0x70, 0x47, 0x68, 0x46, 0x70, 0x47 }; + // guessed - this is true for 0.1.0.11 + private static final byte[] FW_HEADER_NEW = new byte[]{ + 0x60, (byte) 0xeb, 0x03, 0x0c, 0x70, 0x46, 0x31, 0x46, + 0x3a, 0x46, 0x63, 0x46, (byte) 0xbd, (byte) 0xe8, (byte) 0xf0, (byte) 0x81 + }; + private static final int FW_HEADER_OFFSET = 0x9330; private static final byte[] GPS_ALMANAC_HEADER = new byte[]{ // probably wrong @@ -63,6 +70,9 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(55420, "0.0.9.14"); crcToVersion.put(39465, "0.0.9.26"); crcToVersion.put(27394, "0.0.9.40"); + crcToVersion.put(24736, "0.0.9.49"); + crcToVersion.put(49555, "0.0.9.59"); + crcToVersion.put(26714, "0.1.0.11"); // resources crcToVersion.put(12586, "RES 0.0.8.74"); @@ -70,6 +80,7 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(59839, "RES 0.0.8.96-98"); crcToVersion.put(50401, "RES 0.0.9.14-26"); crcToVersion.put(22051, "RES 0.0.9.40"); + crcToVersion.put(46233, "RES 0.0.9.49-0.1.0.11"); // gps crcToVersion.put(61520, "GPS 9367,8f79a91,0,0,"); @@ -97,7 +108,7 @@ public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo { if (ArrayUtils.startsWith(bytes, GPS_CEP_HEADER)) { return HuamiFirmwareType.GPS_CEP; } - if (ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET)) { + if (ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET) || ArrayUtils.equals(bytes, FW_HEADER_NEW, FW_HEADER_OFFSET)) { // TODO: this is certainly not a correct validation, but it works for now return HuamiFirmwareType.FIRMWARE; } From ad559dc6cdcdd3fb2e2a0e88eb40c8a1da33a38b Mon Sep 17 00:00:00 2001 From: Vladislav Serkov Date: Fri, 17 Nov 2017 19:20:36 +0000 Subject: [PATCH 36/55] Translated using Weblate (Russian) Currently translated at 100.0% (431 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/ru/ --- app/src/main/res/values-ru/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 60124d582..d23cfed15 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -9,7 +9,7 @@ Анализ сна (АЛЬФА) Найти устройство Сделать снимок экрана - Отключиться + Отключить Удалить устройство Удалить %1$s Устройство и вся связанная с ним информация будут удалены! From 0bfef9b946e59937c3f665d673be9dbfa0ecd0f7 Mon Sep 17 00:00:00 2001 From: Vladislav Serkov Date: Fri, 17 Nov 2017 19:22:22 +0000 Subject: [PATCH 37/55] Translated using Weblate (Russian) Currently translated at 100.0% (431 of 431 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, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d23cfed15..7b4582e91 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -232,7 +232,7 @@ Пт Сб умное пробуждение - Произошла ошибка при настройке будильника, попробуйте ещё! + Произошла ошибка при настройке будильника, попробуйте ещё раз! Будильник был послан на устройство! Нет данных. Синхронизировать устройство? Будет передано %1$s данных, начиная с %2$s @@ -384,7 +384,7 @@ Сопряжение Не выполнять сопряжение Пожертвовать - Cоединение + Подключить Заблокированные календари "Вы собираетесь установить прошивку %s на ваш Amazfit Bip. @@ -442,7 +442,7 @@ Задержка после действия при нажатии Задержка при выполнении заданного количества нажатий для однократного действия (число указано в button_id). Это число равно нулю для действий без задержки Уведомления о достижении цели - Когда выполнена дневная норма шагов, браслет вибрирует + Браслет завибрирует, когда будет выполнена дневная норма шагов Что показывать на экране Выберите, что показывать на экране браслета Поверните запястье, чтобы переключиться на другую информацию From a4daeae91508004434cd3c401fca5a4956a9d6c2 Mon Sep 17 00:00:00 2001 From: Pascal Date: Fri, 17 Nov 2017 15:38:34 +0000 Subject: [PATCH 38/55] Translated using Weblate (German) Currently translated at 99.5% (429 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/de/ --- app/src/main/res/values-de/strings.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e82f48da6..27b41a3a2 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -443,4 +443,16 @@ Anzahl an Tastendrücken Seitwärts-Wischgesten in der Statistik-Anzeige + Wenn aktiviert, können Watchfaces Informationen zu Wetter, Ladezustand etc. anzeigen. + + ganztägige Pulsmessung + minütlich + alle 5 Minuten + alle 10 Minuten + alle 30 Minuten + stündlich + + automatisch + Web View Aktivität + From a4b233f42a0d629494fe5432695c09d2cfe94b42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Thu, 23 Nov 2017 09:35:58 +0000 Subject: [PATCH 39/55] =?UTF-8?q?Added=20translation=20using=20Weblate=20(?= =?UTF-8?q?Norwegian=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/values-nb-rNO/strings.xml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/src/main/res/values-nb-rNO/strings.xml diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml new file mode 100644 index 000000000..a6b3daec9 --- /dev/null +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file From aba2f5dcaa14dc73860be1cb1fb711c1c17ea43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Thu, 23 Nov 2017 14:38:44 +0000 Subject: [PATCH 40/55] =?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 9.2% (40 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 50 +++++++++++++++++++++- 1 file changed, 48 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 a6b3daec9..cf24601f1 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -1,2 +1,48 @@ - - \ No newline at end of file + +Innstillinger + Feilretting + Avslutt + Doner + Synkroniser + Søvnmonitor (Alfa) + Finn mistet enhet + Utfør skjermavbildning + Koble til + Koble fra + Slett enhet + Slett %1$s + Åpne navigasjonsskuff + Lukk navigasjonsskuf + Trykk lenge på kortet for å koble fra + Kobler fra + Kobler til + Utfører skjermavbildning av enheten + + + Feilretting + + Programbehandler + Programmer i hurtiglager + Installerte programmer + Installerte urskiver + Slett + Slett og fjern fra hurtiglager + Reinstaller + Søk i Pebble-programbutikk + Aktiver + Deaktiver + Skru på HRM + Skru av HRM + Skru på systemværprogram + Skru av systemværprogram + Installer værmeldingsprogrammet + Sett opp + Flytt til toppen + + Merknadssvarteliste + + Svartelistede kalendere + + Fastvare-/program-installerer + Du er i ferd med å installere fastvaren %s i stedet for den som er installert på ditt Mi Band nå. + From 7a765b38e6cd8843dc468b97b129fdd11f6897a7 Mon Sep 17 00:00:00 2001 From: Vitaliy Shuruta Date: Sun, 26 Nov 2017 00:53:03 +0000 Subject: [PATCH 41/55] Translated using Weblate (Ukrainian) Currently translated at 36.8% (159 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/uk/ --- app/src/main/res/values-uk/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index bfe64dc6d..700087e94 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -236,4 +236,6 @@ 24г ДП/ПП - +Пожертвувати + З\'єднати + From 761d6c0059abdfd9ea8872b0c7b63e1f4bd69195 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Mon, 27 Nov 2017 12:58:19 +0000 Subject: [PATCH 42/55] =?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 94.1% (406 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 437 ++++++++++++++++++++- 1 file changed, 436 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index cf24601f1..5d73b4fde 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -45,4 +45,439 @@ Fastvare-/program-installerer Du er i ferd med å installere fastvaren %s i stedet for den som er installert på ditt Mi Band nå. - + Gadgetbru + + Gadgetbru + Dette vil slette enheten og all tilknyttet data + Du er i ferd med å installere fastvaren %s på din Amazfit Bip. +\n +\nForsikre deg om at du installerer .gps-fastvaren, så .res-fila, og til sist .fw-fila. Armbåndsuret ditt vil starte på nytt etter at .fw-fila er installert. +\n +\nMerk: Du må ikke installere .res og .gps hvis disse er akkurat de samme som dem som allerede er installert. +\n +\nFORTSETT PÅ EGEN RISIKO! + Du er i ferd med å installere fastvaren %s på din Amazfit Cor. +\n +\nForsikre deg om at du installerer .res-fila, og så .fw-fila. Armbåndsuret ditt vil starte på nytt etter at .fw-fila er installert. +\n +\nMerk: Du må ikke installere .res og .gps hvis disse er akkurat de samme som dem som allerede er installert. +\n +\nUTESTET, KAN HAVARERE ENHETEN DIN, FORTSETT PÅ EGEN RISIKO! + Du er i ferd med å installere fastvarene %1$s og %2$s i steden for dem som er installert nå på ditt Mi Band. + Denne fastvaren har blitt testet og er kompatibel med Gadgetbru. + Denne fastvaren er utestet og er kanskje ikke kompatibel med Gadgetbru. +\n +\nDu oppfordres IKKE til å skrive den til ditt Mi Band! + Hvis du fremdeles ønsker å fortsette og ting fungerer etterpå, fortell Gadgetbru-utviklerne at de skal hvitliste fastvareversjon: %s + + Innstillinger + + Hovedinnstillinger + Koble til enhet når Blåtann slås på + Start automatisk + Koble til igjen automatisk + Foretrukken lydspiller + Forvalg + Dato og tid + Synkroniser tid + Synkroniser tid til enhet ved tilknobling og når tid eller tidssone endres på Android + + Drakt + Lys + Mørk + + Språk + + Skjul Gadgetbro-merknaden + Ikonet i statusfeltet og merknaden på låseskjermen vises + Ikonet i statusfeltet og merknaden på låseskjermen er skjult + + Merknader + Gjentakelser + Telefonsamtaler + SMS + Pebble-meldinger + Støtte for alle programmer som sender merknader til Pebble via PebbleKit. + Generisk merknadsstøtte + …også når skjermen er på + Ikke forstyrr + Stopp uønskede merkander fra å bli sendt i \"Ikke forstyrr\"-modus + Translitterasjon + Skru på hvis din enhet ikke har noen støtte for ditt språks skrift + + Alltid + Når skjermen er av + Aldri + + Personvern + Ringepersonvernsmodus + Vis navn og nummer + Skjul navn, men vis nummer + Skjul nummer, men vis navn + Skjul navn og nummer + + + Svartelist programmer + Svartelist kalendre + + Svar + Oppdater på Pebble + + Utviklervalg + Mi Band-adresse + + Pebble-innstillinger + + Aktivitetssporere + Foretrukket aktivitetssporer + Synkroniser Pebble-helse + Misfit-synkronisering + Morpheuz-synkronisering + + Støtte for utgående anrop + Å skru av dette vil også forhindre Pebble 2/LE fra å vibrere under utgående anrop + + Tillat tredjepartstilgang fra Android-programmer + Skru på eksperimentell støte for Androidprogrammer som bruker PebbleKit + + Pebble-tidslinje + Soloppgang og solnedgang + Send soloppgang og solnedgangstider basert på plasseringen til Pebble-tidslinjen + Synkroniser kalender + Send kalenderhendelser til tidslinjen + + Fjern forkastede merknader automatisk + Merknader blir automatisk fjernet fra Pebble-enheten når de forkastes fra Android-enheten + + Personvernsmodus + Normale merknader + Vis merknadsteksten utenfor skjermen + Kun vis merknadsikoner + + Plassering + Hent plassering + Breddegrad + Lengdegrad + Hold plasseringen oppdatert + Prøv å hent gjeldende plassering ved kjøring, bruk lagret plassering som andrevalg + + Skru på nettverksplassering + plassering innhentet + + Tving gjennom merknadsprotokoll + Dette valget tvinger bruk av siste merknadskotroll avhengig av fastvareversjon. KUN SKRU PÅ DETTE HVIS DU VET HVA DU GJØR! + Skru på utestede funksjoner + Skru på utestede funksjoner. KUN SKRU PÅ DETTE HVIS DU VET HVA DU GJØR! + Alltid foretrekk BLE + Bruk eksperimentell Pebble LE-støtte for alle Pebble-klokker istedenfor BT classic, som krever parring av en Pebble LE etter at noe som ikke var en LE har vært tilkoblet én gang + Pebble 2/LE GATT MTU-grense + Hvis din Pebble 2/Pebble LE ikke fungerer som forventet, prøv å sette denne grensen for å begrense MTU (gyldig rekkevidde 20-512) + Skru på bakgrunns-JS + Tillater når påskrudd, værvarsel på urskive, batteriinfo, osv. + + Forsøk på tilkoblingsgjenopprettelse + + Enheter + Tidsformat + Heldagspulsmåling + HPlus/Makibes-innstillinger + + Ikke tilkoblet + Kobler til + Tilkoblet + Ukjent tilstand + (ukjent) + Test + Send testmerknad + Dette er en testmerknad fra Gadgetbru + Blåtann støttes ikke. + Blåtann avskrudd. + Trykk på tilkoblet enhet for programbehandler + Trykk på tilkoblet enhet for aktivtet + Trykk på tilkoblet enhet for vibrasjon + Trykk på en enhet for å koble til + Kan ikke koble til. Ugyldig Blåtannsadresse? + Gadgetbro kjører + Installerer binærfil %1$d/%2$d + Installasjon mislyktes + Installert + DU PRØVER Å INSTALLERE EN FASTVARE, FORTSETT PÅ EGEN RISIKO. +\n +\nDENNE FASTVAREN ER FOR MASKINVAREVERSJON: %s + Du er i ferd med å installere følgende program: +\n +\n%1$s version %2$s av %3$s +\n + I/T + igangsatt + %1$s av %2$s + Enhetsoppdaging + + Stopp skanning + Start oppdagning + Koble til ny enhet + %1$s (%2$) + Parr enhet + Bruk parringsdialogen for Blåtann i Android til å parre enheten. + Parr ditt Mi Band + Parrer med %s… + Oppretter tilknytning til %1$s (%2$s) + Klarte ikke å parre med %1$s (%2$s) + Parring underveis: %1$s (%2$s) + Allerede tilknyttet %1$s (%2½s), tilkobler… + Ingen MAC-adresse sendt, kan ikke parre. + Enhetsspesifikke innstillinger + Mi Band / Amazfit -innstillinger + Amazfit Bip-innstillinger + Mann + Kvinne + Annet + Venstre + Høyre + Ingen gyldig brukerdata angitt, bruker testbrukerdata midlertidig. + Når ditt Mi Band vibrerer og blinker, trykk på det et par ganger på rad. + Installer + Gjør enheten din oppdagbar. Enheter som er tilkoblet vil antagelig ikke bli oppdaget. Aktiver plassering (GPS bl. a.) på Android 6+. Skru av Privacy Guard for Gadgetbru, siden det kan kræsje og medføre omstart av telefonen. Hvis ingen enhet blir funnet etter et par minutter, prøv igjen etter å ha startet din mobile enhet på nytt. + Merk: + Enhetsavbildning + Navn/alias + Vibrasjonsantall + + Søvnmonitor + Skriv loggfiler + Igangsetter + Henter aktivitetsdato + Fra %1$s til %2$s + Venstre- eller høyre-hånd? + Vibrasjonsprofil + + Stakkato + Kort + Middels + Lang + Vanndråpe + Ring + Alarmklokke + Vibrasjon + + Prøv + SMS-merknad + Vibrasjonsinnstillinger + Generisk merknad + E-postmerknad + Innkommende ringemerknad + Sludre + Navigasjon + Sosialt nettverk + + Heldagspulsmåling + én gang i minuttet + hvert femte minutt + hvert tiende minutt + hver halvtime + én gang i timen + + Fartssoner + Totalt antall minutter + Steg per minutt + + Finn tapt enhet + Avbryt for å stoppe vibrasjon. + Din aktivitet + Sett opp alarmer + Sett opp alarmer + Alarmdetaljer + Søn + Man + Tir + Ons + Tor + Fre + Lør + Smart oppvåkning + Feil ved setting av alarm, prøv igjen. + Alarmer sendt til enhet. + Ingen data. Synkroniser enhet? + I ferd med å overføre %1$d med data fra %2$s + Stegmål + Feil under kjøring av \"%1$s\" + Din aktivitet (alfa) + Kan ikke koble til: %1$s + Kan ikke finne en behandler for installasjon av denne fila. + Klarte ikke å installere gitt fil: %1$s + Klarte ikke å installere angitt fastvare. Den passer ikke for maskinvareversjonen for din Pebble. + Vent mens installasjonsstatus fastsettes… + Lite batteri på gadget! + %1$s batteri gjenstår: %2$s%% + Siste oppladning: %s +\n + Antall ladinger: %s + Din søvn + Søvn per uke + Søvn i dag, mål: %1$s + Steg per uke + Din aktivitet og søvn + Oppgraderer fastvare… + Kan ikke installere fil, enheten er ikke klar. + Mi Band-fastvare %1$s + Amazfit Bip-fastvare %1$s + Amazfit Cor-fastvare %1$s + Kompatibel versjon + Utestet versjon! + Tilkobling til enhet: %1$s + Pebble-fastvare %1$s + Korrekt maskinvareversjon + Det er ikke samsvar mellom maskinvarerevisjonene! + %1$s (%2$s) + Problem med fastvareoverføring. IKKE SKRU AV ditt Mi Band! + Problem ved overføring av fastvaremetadata + Fastvareinstallasjon fullført + Fastvareinstallasjon fullført, starter enhet på nytt… + Fastvareskriving mislyktes + Steg + Kalorier + Distanse + Klokke + Puls + Batteri + Aktivitet i sanntid + Steg i dag, mål: %1$s + Ikke send bekreftelse på aktivitetsdataoverføring + Hvis aktivitetsdataen ikke bekreftes til bandet, vil de ikke bli tømt. Nyttig hvis Gb brukes sammen med andre programmer. + Beholder aktivitetsdata på Mi Band-et, selv etter synkronisering. Nyttig hvis Gb brukes sammen med andre programmer. + Bruk lav-latens -modus for fastvareoppgraderinger + Dette kan hjelpe på enheter der fastvareoppgraderinger mislykkes. + + Steghistorikk + Gjeldende steg/min + Totalt antall steg + Historisk, steg per minutt + Start din aktivitet + Aktivitet + Lett søvn + Dyp søvn + Ikke brukt + Ikke tilkoblet. + Alle alarmer avskrudd + Behold aktivitetsdata på enhet + Ukompatibel fastvare + Fastvaren er ikke kompatibel med enheten + Alarmer å holde av for kommende hendelser + Bruk pulsmåler for å forbedre bestemmelse av søvnmønster + Mi2: Datoformat + Tid + Tid og dato + Knappevalg + Angi handlinger for Mi Band 2 knappetrykk + Antall trykk på knapp + Antall trykk på knapp for å utløse meldingskringkasting + Kringkastingsmelding å sende + Målmerknad + Båndet vil vibrere når daglig stegmål nås + Vis elementer + Velg elementene som skal vises på båndskjermen + Roter håndledd for å bytte info + Ikke forstyrr + Båndet mottar ikke merknader når det er aktivt + Inaktivitetsadvarsler + Båndet vil vibrere når du har vært inaktiv en stund + Inaktivitetsterskel (i minutter) + Skru av inaktivitetsadvarsel for en tidsperiode + Starttid + Sluttid + + Automatisk + Forenklet kinesisk + Tradisjonell kinesisk + Engelsk + + I ferd med å overføre data siden %1$s + + Venter på ny tilkobling + + Om deg + Fødselsår + Kjønn + Høyde i cm + Vekt i kg + + Autentiserer + Autentisering kreves + + Zzz + Legg til miniprogram + Foretrukket søvn i timer + En alarm ble satt for %1$02d:%2$02d + Maskinvarerevisjon: %1$s + Fastvareversjon: %1$s + Feil under opprettelse av mappe for loggfiler: %1$s + "HR: " + Fastvareoppgradering underveis + Fastvare ikke sendt + Puls + Puls + + Lagre rådata i databasen + Hvis valgt blir dataen lagret \"som den er\" og er tilgjengelig for senere fortolkning. NB: Databasen kan bli større i sådant fall! + Databasebehandling + Databasebehandling + Eksporter til: %1$s + Feil ved eksport av DB: %1$s + Feil ved eksport av innstilling: %1$s + Importer data? + Vil du virkelig overskrive gjeldende database? All nåværende aktivitetsdata (hvis noen) vil gå tapt. + Importert + Feil ved import av DB: %1$s + Feil ved import av innstilling: %1$s + Slett aktivitetsdata? + Vil du virkelig slette hele databasen? All din aktivitetsdata og informasjon om dine enheter vil gå tapt. + Data slettet. + Databasesletting mislyktes. + Slett gammel aktivitetsdatabase? + Vil du virkelig slette den gamle aktivitetsdatabasen? Aktivietetsdata som ikke ble importert vil gå tapt. + Gammel aktivitetsdata slettet. + Sletting av gammel aktivitetsdatabase mislyktes. + Overskriv + Avbryt + Slett + + Vibrasjon + + Pebble-parring + En parringslogg bør sprette opp på din Android-enhet. Hvis det ikke skjer, se i navigasjonsskuffen, og godta parringsforespørselen. Etter det godtar du parringsforespørselen på din Pebble + + Skru på Blåtannsparring + Skru dette av hvis du har problemer med å koble til + + Metrisk + Imperial + + 24t + AM/PM + + Ringeklokke + + (%1$s) + Du fant det! + Mi2: Tidsformat + Du må installere versjon %1$s før du installerer denne fastvaren! + Tekstmerknader + Trenger fastvare <=1.0.1.28 og Mili_pro.ft* installert. + Av + + Automatisk (søvnoppdagelse) + Planlagt (tidsperiode) + Prøver å parre med %1$s + Tilknytning til %1$s mislyktes umiddelbart. + Prøver å koble til: %1$s + Skru på Blåtann for å oppdage enheter. + Tilknyttet %1$s. + Parr med %1$s? + Velg \"Parr\" for å parre enhetene dine. Hvis dette mislykkes, prøv igjen uten å parre. + Parr + Ikke parr + + Åpne på telefonen + Forstum + Svar + From ed09218e59612c51ca731b0fe32c26292ea35c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Allan=20Nordh=C3=B8y?= Date: Thu, 30 Nov 2017 14:24:01 +0000 Subject: [PATCH 43/55] =?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 94.1% (406 of 431 strings) Translation: Freeyourgadget/Gadgetbridge Translate-URL: https://hosted.weblate.org/projects/freeyourgadget/gadgetbridge/nb_NO/ --- app/src/main/res/values-nb-rNO/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index 5d73b4fde..bf3c5f90d 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -458,7 +458,7 @@ Ringeklokke (%1$s) - Du fant det! + Du fant den! Mi2: Tidsformat Du må installere versjon %1$s før du installerer denne fastvaren! Tekstmerknader From 1ccc99c3bcffc729928985608849ba826ab392b3 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 2 Dec 2017 20:34:13 +0100 Subject: [PATCH 44/55] Fix broken string in Norwegian translation --- app/src/main/res/values-nb-rNO/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index bf3c5f90d..8a3c7847a 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -224,7 +224,7 @@ Oppretter tilknytning til %1$s (%2$s) Klarte ikke å parre med %1$s (%2$s) Parring underveis: %1$s (%2$s) - Allerede tilknyttet %1$s (%2½s), tilkobler… + Allerede tilknyttet %1$s (%2$s), tilkobler… Ingen MAC-adresse sendt, kan ikke parre. Enhetsspesifikke innstillinger Mi Band / Amazfit -innstillinger From eb9d321b95a771bebabc9e9c68d5eae3c19773be Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 2 Dec 2017 20:35:56 +0100 Subject: [PATCH 45/55] Use Teclast H30 code for Teclast H10 Thanks @newfla for pointing that hout Closes #867 --- .../gadgetbridge/devices/jyou/TeclastH30Coordinator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java index 84b8f5e70..0327ab0fc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java @@ -63,7 +63,7 @@ public class TeclastH30Coordinator extends AbstractDeviceCoordinator { @Override public DeviceType getSupportedType(GBDeviceCandidate candidate) { String name = candidate.getDevice().getName(); - if (name != null && name.startsWith("TECLAST_H30")) { + if (name != null && (name.startsWith("TECLAST_H30") || name.startsWith("TECLAST_H10"))) { return DeviceType.TECLASTH30; } return DeviceType.UNKNOWN; From f7f0722a1fa702fbb7e1744859c1272e83c6e96b Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 2 Dec 2017 21:25:09 +0100 Subject: [PATCH 46/55] bump version, add changelog --- CHANGELOG.md | 6 ++++++ app/build.gradle | 4 ++-- app/src/main/res/xml/changelog_master.xml | 5 +++++ fastlane/metadata/android/en-US/changelogs/113.txt | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/113.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f4c40660..0216a5ec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ### Changelog +#### Version 0.22.5 +* Unlock Teclast H10 support using the same code as H30 +* Amazfit Bip: Fix installation of 0.1.0.11 Firmware +* Amazfit Bip/Cor: Send three days of weather forecast including (untranslated) conditions +* Workaround for a crash on Android 4.4 when connecting + #### Version 0.22.4 * Mi Band 2/Bip/Cor: Whole day HR support * Mi Band 2/Bip/Cor: Prevent writing a lot of HR samples to the database when not using the live activity feature diff --git a/app/build.gradle b/app/build.gradle index e2967aa1f..790699e9c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -26,8 +26,8 @@ android { targetSdkVersion 25 // note: always bump BOTH versionCode and versionName! - versionName "0.22.4" - versionCode 112 + versionName "0.22.5" + versionCode 113 vectorDrawables.useSupportLibrary = true } buildTypes { diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml index 5e93b37b0..68d70403b 100644 --- a/app/src/main/res/xml/changelog_master.xml +++ b/app/src/main/res/xml/changelog_master.xml @@ -1,5 +1,10 @@ + + Unlock Teclast H10 support using the same code as H30 + Amazfit Bip: Fix installation of 0.1.0.11 Firmware + Amazfit Bip/Cor: Send three days of weather forecast including (untranslated) conditions + Workaround for a crash on Android 4.4 when connecting Mi Band 2/Bip/Cor: Whole day HR support Mi Band 2/Bip/Cor: Prevent writing a lot of HR samples to the database when not using the live activity feature diff --git a/fastlane/metadata/android/en-US/changelogs/113.txt b/fastlane/metadata/android/en-US/changelogs/113.txt new file mode 100644 index 000000000..888e41cdf --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/113.txt @@ -0,0 +1,5 @@ +#### Version 0.22.5 +* Unlock Teclast H10 support using the same code as H30 +* Amazfit Bip: Fix installation of 0.1.0.11 Firmware +* Amazfit Bip/Cor: Send three days of weather forecast including (untranslated) conditions +* Workaround for a crash on Android 4.4 when connecting From 3108f5c22cb1d2a01e47dcf5b04c52904fae34e3 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 2 Dec 2017 21:29:43 +0100 Subject: [PATCH 47/55] XML: the worst invention after Java --- app/src/main/res/xml/changelog_master.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/xml/changelog_master.xml b/app/src/main/res/xml/changelog_master.xml index 68d70403b..a15b476f3 100644 --- a/app/src/main/res/xml/changelog_master.xml +++ b/app/src/main/res/xml/changelog_master.xml @@ -5,6 +5,7 @@ Amazfit Bip: Fix installation of 0.1.0.11 Firmware Amazfit Bip/Cor: Send three days of weather forecast including (untranslated) conditions Workaround for a crash on Android 4.4 when connecting + Mi Band 2/Bip/Cor: Whole day HR support Mi Band 2/Bip/Cor: Prevent writing a lot of HR samples to the database when not using the live activity feature From c95b9d99e5a4360c71392af97036c9c3b2c8632a Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sat, 2 Dec 2017 23:50:56 +0100 Subject: [PATCH 48/55] remove version from fastlane changelog --- fastlane/metadata/android/en-US/changelogs/113.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/fastlane/metadata/android/en-US/changelogs/113.txt b/fastlane/metadata/android/en-US/changelogs/113.txt index 888e41cdf..2461690de 100644 --- a/fastlane/metadata/android/en-US/changelogs/113.txt +++ b/fastlane/metadata/android/en-US/changelogs/113.txt @@ -1,4 +1,3 @@ -#### Version 0.22.5 * Unlock Teclast H10 support using the same code as H30 * Amazfit Bip: Fix installation of 0.1.0.11 Firmware * Amazfit Bip/Cor: Send three days of weather forecast including (untranslated) conditions From 76de046434c358154f4c1e12ffa2cf59408008d6 Mon Sep 17 00:00:00 2001 From: michaelneu Date: Sat, 2 Dec 2017 23:54:16 +0100 Subject: [PATCH 49/55] add Facebook Messenger Lite notification support (see #883) --- .../freeyourgadget/gadgetbridge/model/AppNotificationType.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java index 5e2e63a24..e7c021201 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/model/AppNotificationType.java @@ -84,6 +84,7 @@ public class AppNotificationType extends HashMap { // Facebook Messenger put("com.facebook.orca", NotificationType.FACEBOOK_MESSENGER); + put("com.facebook.mlite", NotificationType.FACEBOOK_MESSENGER); // WhatsApp put("com.whatsapp", NotificationType.WHATSAPP); From eec0a4dc4c25c0f02bde131d5e5fe2f2a9eedf98 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Mon, 4 Dec 2017 22:31:36 +0100 Subject: [PATCH 50/55] Amazfit Bip/Cor: Send also current temperature/condition Closes #905 --- .../devices/amazfitbip/AmazfitBipSupport.java | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index bbaf76791..876421789 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -127,16 +127,46 @@ public class AmazfitBipSupport extends MiBand2Support { if (gbDevice.getFirmwareVersion() == null) { LOG.warn("Device not initialized yet, so not sending weather info"); return; + + } + boolean supportsConditionString = false; + + Version version = new Version(gbDevice.getFirmwareVersion()); + if (version.compareTo(new Version("0.0.8.74")) >= 0) { + supportsConditionString = true; + } + int tz_offset_hours = SimpleTimeZone.getDefault().getOffset(weatherSpec.timestamp * 1000L) / (1000 * 60 * 60); + try { + TransactionBuilder builder; + builder = performInitialized("Sending current temp"); + + byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode); + + int length = 8; + if (supportsConditionString) { + length += weatherSpec.currentCondition.getBytes().length + 1; + } + ByteBuffer buf = ByteBuffer.allocate(length); + buf.order(ByteOrder.LITTLE_ENDIAN); + + buf.put((byte) 2); + buf.putInt(weatherSpec.timestamp); + buf.put((byte) (tz_offset_hours * 4)); + buf.put(condition); + buf.put((byte) (weatherSpec.currentTemp - 273)); + + if (supportsConditionString) { + buf.put(weatherSpec.currentCondition.getBytes()); + buf.put((byte) 0); + } + + builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); + builder.queue(getQueue()); + } catch (IOException ignore) { } try { TransactionBuilder builder = performInitialized("Sending weather forecast"); - boolean supportsConditionString = false; - - Version version = new Version(gbDevice.getFirmwareVersion()); - if (version.compareTo(new Version("0.0.8.74")) >= 0) { - supportsConditionString = true; - } final byte NR_DAYS = (byte) (1 + weatherSpec.forecasts.size()); int bytesPerDay = 4; @@ -156,7 +186,6 @@ public class AmazfitBipSupport extends MiBand2Support { buf.order(ByteOrder.LITTLE_ENDIAN); buf.put((byte) 1); buf.putInt(weatherSpec.timestamp); - int tz_offset_hours = SimpleTimeZone.getDefault().getOffset(weatherSpec.timestamp * 1000L) / (1000 * 60 * 60); buf.put((byte) (tz_offset_hours * 4)); buf.put(NR_DAYS); From 8fbf97f713bc45bf71bb9dc91a0e9793ef2d9a14 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Fri, 8 Dec 2017 08:26:10 +0100 Subject: [PATCH 51/55] Amazfit Bip/Cor: Send fake AQI 0 to make current weather appear I have no idea why this is necessary. But at least it makes the current weather visible :/ --- .../devices/amazfitbip/AmazfitBipSupport.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java index 876421789..e56ca12fc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/amazfitbip/AmazfitBipSupport.java @@ -162,7 +162,32 @@ public class AmazfitBipSupport extends MiBand2Support { builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); builder.queue(getQueue()); - } catch (IOException ignore) { + } catch (Exception ex) { + LOG.error("Error sending current weather", ex); + } + + try { + TransactionBuilder builder; + builder = performInitialized("Sending air quality index"); + int length = 8; + String aqiString = "(fake)"; + if (supportsConditionString) { + length += aqiString.getBytes().length + 1; + } + ByteBuffer buf = ByteBuffer.allocate(length); + buf.order(ByteOrder.LITTLE_ENDIAN); + buf.put((byte) 4); + buf.putInt(weatherSpec.timestamp); + buf.put((byte) (tz_offset_hours * 4)); + buf.putShort((short) 0); + if (supportsConditionString) { + buf.put(aqiString.getBytes()); + buf.put((byte) 0); + } + builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Error sending air quality"); } try { @@ -216,7 +241,7 @@ public class AmazfitBipSupport extends MiBand2Support { builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); builder.queue(getQueue()); } catch (Exception ex) { - LOG.error("Error sending weather information to the Bip", ex); + LOG.error("Error sending weather forecast", ex); } } From d447829d6fc8de02f0c7ff94ab7e455cef8da39e Mon Sep 17 00:00:00 2001 From: cpfeiffer Date: Fri, 8 Dec 2017 23:18:11 +0100 Subject: [PATCH 52/55] Bump build:gradle to 3.0.1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c41c322f1..7c5917d4e 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0' + classpath 'com.android.tools.build:gradle:3.0.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files From ff93122ddcce595d62effb3cb7ed93a7a654a79c Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 10 Dec 2017 11:30:31 +0100 Subject: [PATCH 53/55] Amazfit Bip/Cor: parse and display firmware version for unknown versions Unfortunately that does not work for the Mi Band 2 yet --- .../devices/huami/HuamiFirmwareInfo.java | 35 ++++++++++++++++--- .../devices/miband2/Mi2FirmwareInfo.java | 11 ++++-- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java index 8ff8cbfd5..6f1eee5e9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java @@ -17,6 +17,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.huami; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Map; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; @@ -41,7 +43,11 @@ public abstract class HuamiFirmwareInfo { private HuamiFirmwareType firmwareType = HuamiFirmwareType.FIRMWARE; public String toVersion(int crc16) { - return getCrcMap().get(crc16); + String version = getCrcMap().get(crc16); + if (version == null) { + version = searchVersion(bytes); + } + return version; } public int[] getWhitelistedVersions() { @@ -52,12 +58,9 @@ public abstract class HuamiFirmwareInfo { private byte[] bytes; - private String firmwareVersion; - public HuamiFirmwareInfo(byte[] bytes) { this.bytes = bytes; crc16 = CheckSums.getCRC16(bytes); - firmwareVersion = getCrcMap().get(crc16); firmwareType = determineFirmwareType(bytes); } @@ -98,4 +101,28 @@ public abstract class HuamiFirmwareInfo { protected abstract Map getCrcMap(); protected abstract HuamiFirmwareType determineFirmwareType(byte[] bytes); + + protected String searchVersion(byte[] fwbytes) { + ByteBuffer buf = ByteBuffer.wrap(fwbytes); + buf.order(ByteOrder.BIG_ENDIAN); + while (buf.remaining() > 3) { + int word = buf.getInt(); + if (word == 0x5625642e) { + word = buf.getInt(); + if (word == 0x25642e25) { + word = buf.getInt(); + if (word == 0x642e2564) { + word = buf.getInt(); + if (word == 0x00000000) { + byte version[] = new byte[8]; + buf.get(version); + return new String(version); + } + } + } + } + } + return null; + } + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java index 3538d3335..7efa68f75 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java @@ -47,7 +47,8 @@ public class Mi2FirmwareInfo extends HuamiFirmwareInfo { private static final int FW_HEADER_OFFSET = 0x150; - protected static Map crcToVersion = new HashMap<>(); + protected static Map crcToVersion = new HashMap<>(); + static { // firmware crcToVersion.put(41899, "1.0.0.39"); @@ -55,7 +56,7 @@ public class Mi2FirmwareInfo extends HuamiFirmwareInfo { crcToVersion.put(32450, "1.0.1.28"); crcToVersion.put(51770, "1.0.1.34"); crcToVersion.put(3929, "1.0.1.39"); - crcToVersion.put(47364 , "1.0.1.54"); + crcToVersion.put(47364, "1.0.1.54"); // fonts crcToVersion.put(45624, "Font"); @@ -84,4 +85,10 @@ public class Mi2FirmwareInfo extends HuamiFirmwareInfo { protected Map getCrcMap() { return crcToVersion; } + + @Override + protected String searchVersion(byte[] fwbytes) { + // does not work for Mi Band 2 + return null; + } } From b7b96b5ab5828638c364d742247811059871a829 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 10 Dec 2017 20:30:27 +0100 Subject: [PATCH 54/55] Amazfit Bip/Cor: for untested installable files, at least display the type (res/font/gps/watchface) For res the version is also displayed (the same as noted in the wiki) --- .../devices/huami/HuamiFirmwareInfo.java | 34 +++++++++++++++++-- .../devices/miband2/Mi2FirmwareInfo.java | 2 +- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java index 6f1eee5e9..89fb07bf3 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiFirmwareInfo.java @@ -45,7 +45,37 @@ public abstract class HuamiFirmwareInfo { public String toVersion(int crc16) { String version = getCrcMap().get(crc16); if (version == null) { - version = searchVersion(bytes); + if (firmwareType == HuamiFirmwareType.FIRMWARE) { + version = searchFirmwareVersion(bytes); + } + else if (firmwareType == HuamiFirmwareType.RES) { + version = "RES " + Integer.toString(bytes[5]); + } + else if (firmwareType == HuamiFirmwareType.RES_NEW) { + version = "RES " + Integer.toString(bytes[14]); + } + } + if (version == null) { + switch (firmwareType) { + case FIRMWARE: + version = "(unknown)"; + break; + case FONT: + version = "(unknown font)"; + break; + case GPS: + version = "(unknown GPS)"; + break; + case GPS_CEP: + version = "(unknown CEP)"; + break; + case GPS_ALMANAC: + version = "(unknown ALM)"; + break; + case WATCHFACE: + version = "(unknown watchface)"; + break; + } } return version; } @@ -102,7 +132,7 @@ public abstract class HuamiFirmwareInfo { protected abstract HuamiFirmwareType determineFirmwareType(byte[] bytes); - protected String searchVersion(byte[] fwbytes) { + protected String searchFirmwareVersion(byte[] fwbytes) { ByteBuffer buf = ByteBuffer.wrap(fwbytes); buf.order(ByteOrder.BIG_ENDIAN); while (buf.remaining() > 3) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java index 7efa68f75..e5ac63dae 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/Mi2FirmwareInfo.java @@ -87,7 +87,7 @@ public class Mi2FirmwareInfo extends HuamiFirmwareInfo { } @Override - protected String searchVersion(byte[] fwbytes) { + protected String searchFirmwareVersion(byte[] fwbytes) { // does not work for Mi Band 2 return null; } From f0ac296492c9ddb6426d3c0116a8e5b151c9d883 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Mon, 11 Dec 2017 19:09:37 +0100 Subject: [PATCH 55/55] Initial support for cyanogenmod/lineage weather provider TODO: - also reconstruct json for Pebble background js fake replies - find a better location for settings - interatively display candidates when looking up location - grey out setting on non-cm/los devices --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 3 + .../activities/SettingsActivity.java | 17 ++ .../devices/DeviceCoordinator.java | 7 +- .../devices/UnknownDeviceCoordinator.java | 5 + .../devices/hplus/HPlusCoordinator.java | 5 + .../amazfitbip/AmazfitBipCoordinator.java | 5 + .../amazfitcor/AmazfitCorCoordinator.java | 5 + .../huami/miband2/MiBand2Coordinator.java | 5 + .../huami/miband2/MiBand2HRXCoordinator.java | 5 + .../devices/jyou/TeclastH30Coordinator.java | 5 + .../devices/liveview/LiveviewCoordinator.java | 7 +- .../devices/miband/MiBandCoordinator.java | 5 + .../devices/no1f1/No1F1Coordinator.java | 5 + .../devices/pebble/PebbleCoordinator.java | 5 + .../vibratissimo/VibratissimoCoordinator.java | 5 + .../externalevents/CMWeatherReceiver.java | 194 ++++++++++++++++++ .../service/DeviceCommunicationService.java | 12 +- .../notification/ParcelableWeather2.java | 15 +- app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/preferences.xml | 3 + 21 files changed, 300 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CMWeatherReceiver.java diff --git a/app/build.gradle b/app/build.gradle index 790699e9c..b02e76497 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,6 +83,7 @@ dependencies { // version contains way too much and our custom patches are in the generator only. compile 'org.greenrobot:greendao:2.2.1' compile 'org.apache.commons:commons-lang3:3.5' + compile 'org.cyanogenmod:platform.sdk:6.0' // compile project(":DaoCore") } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 49ae11746..c7e41ddc4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -19,6 +19,9 @@ + + + diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java index fb8a6b388..cc8a5144f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/SettingsActivity.java @@ -47,6 +47,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity; +import nodomain.freeyourgadget.gadgetbridge.externalevents.CMWeatherReceiver; import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; @@ -259,6 +260,21 @@ public class SettingsActivity extends AbstractSettingsActivity { } }); + pref = findPreference("weather_city"); + pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newVal) { + // reset city id and force a new lookup + GBApplication.getPrefs().getPreferences().edit().putString("weather_cityid",null).apply(); + preference.setSummary(newVal.toString()); + Intent intent = new Intent("GB_UPDATE_WEATHER"); + intent.setPackage(CMWeatherReceiver.class.getCanonicalName()); + sendBroadcast(intent); + return true; + } + + }); + // Get all receivers of Media Buttons Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); @@ -338,6 +354,7 @@ public class SettingsActivity extends AbstractSettingsActivity { PREF_USER_WEIGHT_KG, PREF_USER_SLEEP_DURATION, PREF_USER_STEPS_GOAL, + "weather_city", }; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java index 91ed1df3b..a1cdabf23 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java @@ -228,5 +228,10 @@ public interface DeviceCoordinator { * This can be live HR, steps etc. */ boolean supportsRealtimeData(); - + + /** + * Indicates whether the device supports current weather and/or weather + * forecast display. + */ + boolean supportsWeather(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java index b470c6ec4..3b9b7d9d4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java @@ -176,4 +176,9 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator { public boolean supportsRealtimeData() { return false; } + + @Override + public boolean supportsWeather() { + return false; + } } 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 157c6e54f..0cce909b3 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 @@ -98,6 +98,11 @@ public class HPlusCoordinator extends AbstractDeviceCoordinator { return true; } + @Override + public boolean supportsWeather() { + return false; + } + @Override public DeviceType getDeviceType() { return DeviceType.HPLUS; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java index 812f34cdb..449054b37 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitbip/AmazfitBipCoordinator.java @@ -63,4 +63,9 @@ public class AmazfitBipCoordinator extends HuamiCoordinator { public boolean supportsHeartRateMeasurement(GBDevice device) { return true; } + + @Override + public boolean supportsWeather() { + return true; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java index 978c27333..97dfa098e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitcor/AmazfitCorCoordinator.java @@ -63,4 +63,9 @@ public class AmazfitCorCoordinator extends HuamiCoordinator { public boolean supportsHeartRateMeasurement(GBDevice device) { return true; } + + @Override + public boolean supportsWeather() { + return true; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java index af1ce8939..e1d091102 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2Coordinator.java @@ -73,4 +73,9 @@ public class MiBand2Coordinator extends HuamiCoordinator { public boolean supportsHeartRateMeasurement(GBDevice device) { return true; } + + @Override + public boolean supportsWeather() { + return false; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2HRXCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2HRXCoordinator.java index ef5231c55..ea4f39841 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2HRXCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband2/MiBand2HRXCoordinator.java @@ -68,4 +68,9 @@ public class MiBand2HRXCoordinator extends HuamiCoordinator { return false; } + @Override + public boolean supportsWeather() { + return false; + } + } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java index 0327ab0fc..b35b1d404 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/jyou/TeclastH30Coordinator.java @@ -84,6 +84,11 @@ public class TeclastH30Coordinator extends AbstractDeviceCoordinator { return true; } + @Override + public boolean supportsWeather() { + return false; + } + @Override public DeviceType getDeviceType() { return DeviceType.TECLASTH30; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java index 13eb07305..1e3c716e1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/liveview/LiveviewCoordinator.java @@ -23,7 +23,6 @@ import android.net.Uri; import android.support.annotation.NonNull; import nodomain.freeyourgadget.gadgetbridge.GBException; -import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; @@ -35,6 +34,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; public class LiveviewCoordinator extends AbstractDeviceCoordinator { + @NonNull @Override public DeviceType getSupportedType(GBDeviceCandidate candidate) { String name = candidate.getDevice().getName(); @@ -119,6 +119,11 @@ public class LiveviewCoordinator extends AbstractDeviceCoordinator { return false; } + @Override + public boolean supportsWeather() { + return false; + } + @Override protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { // nothing to delete, yet diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java index b23be5b22..2cd04f320 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBandCoordinator.java @@ -171,6 +171,11 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator { return true; } + @Override + public boolean supportsWeather() { + return false; + } + public static boolean hasValidUserInfo() { String dummyMacAddress = MiBandService.MAC_ADDRESS_FILTER_1_1A + ":00:00:00"; try { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java index 5499d1c57..fb157b677 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/no1f1/No1F1Coordinator.java @@ -147,6 +147,11 @@ public class No1F1Coordinator extends AbstractDeviceCoordinator { return false; } + @Override + public boolean supportsWeather() { + return false; + } + @Override protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { Long deviceId = device.getId(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java index b764c63e4..eefac58cf 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/pebble/PebbleCoordinator.java @@ -155,4 +155,9 @@ public class PebbleCoordinator extends AbstractDeviceCoordinator { public boolean supportsRealtimeData() { return false; } + + @Override + public boolean supportsWeather() { + return true; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java index 84dc61a46..b43c5fb37 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/vibratissimo/VibratissimoCoordinator.java @@ -120,6 +120,11 @@ public class VibratissimoCoordinator extends AbstractDeviceCoordinator { return false; // hmmm well, it has a temperature sensor :D } + @Override + public boolean supportsWeather() { + return false; + } + @Override protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { // nothing to delete, yet diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CMWeatherReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CMWeatherReceiver.java new file mode 100644 index 000000000..2513956af --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/CMWeatherReceiver.java @@ -0,0 +1,194 @@ +package nodomain.freeyourgadget.gadgetbridge.externalevents; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import cyanogenmod.weather.CMWeatherManager; +import cyanogenmod.weather.WeatherInfo; +import cyanogenmod.weather.WeatherLocation; +import cyanogenmod.weather.util.WeatherUtils; +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.model.Weather; +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; +import nodomain.freeyourgadget.gadgetbridge.util.Prefs; + +import static cyanogenmod.providers.WeatherContract.WeatherColumns.TempUnit.FAHRENHEIT; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.WeatherCode.ISOLATED_THUNDERSHOWERS; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.WeatherCode.NOT_AVAILABLE; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.WeatherCode.SCATTERED_SNOW_SHOWERS; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.WeatherCode.SCATTERED_THUNDERSTORMS; +import static cyanogenmod.providers.WeatherContract.WeatherColumns.WeatherCode.SHOWERS; + +public class CMWeatherReceiver extends BroadcastReceiver implements CMWeatherManager.WeatherUpdateRequestListener, CMWeatherManager.LookupCityRequestListener { + + private static final Logger LOG = LoggerFactory.getLogger(CMWeatherReceiver.class); + + private WeatherLocation weatherLocation = null; + private Context mContext; + private PendingIntent mPendingIntent = null; + + public CMWeatherReceiver() { + mContext = GBApplication.getContext(); + final CMWeatherManager weatherManager = CMWeatherManager.getInstance(mContext); + if (weatherManager == null) { + return; + } + + Prefs prefs = GBApplication.getPrefs(); + + String city = prefs.getString("weather_city", null); + String cityId = prefs.getString("weather_cityid", null); + + if ((cityId == null || cityId.equals("")) && city != null && !city.equals("")) { + lookupCity(city); + } else if (city != null && cityId != null) { + weatherLocation = new WeatherLocation.Builder(cityId, city).build(); + enablePeriodicAlarm(true); + } + } + + private void lookupCity(String city) { + final CMWeatherManager weatherManager = CMWeatherManager.getInstance(mContext); + if (weatherManager == null) { + return; + } + + if (city != null && !city.equals("")) { + if (weatherManager.getActiveWeatherServiceProviderLabel() != null) { + weatherManager.lookupCity(city, this); + } + } + } + + private void enablePeriodicAlarm(boolean enable) { + if ((mPendingIntent != null && enable) || (mPendingIntent == null && !enable)) { + return; + } + + AlarmManager am = (AlarmManager) (mContext.getSystemService(Context.ALARM_SERVICE)); + if (am == null) { + LOG.warn("could not get alarm manager!"); + return; + } + + if (enable) { + mPendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("GB_UPDATE_WEATHER"), 0); + am.setInexactRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + 10000, AlarmManager.INTERVAL_HOUR, mPendingIntent); + } else { + am.cancel(mPendingIntent); + mPendingIntent = null; + } + } + + @Override + public void onReceive(Context context, Intent intent) { + Prefs prefs = GBApplication.getPrefs(); + + String city = prefs.getString("weather_city", null); + String cityId = prefs.getString("weather_cityid", null); + + if (city != null && !city.equals("") && cityId == null) { + lookupCity(city); + } else { + requestWeather(); + } + } + + private void requestWeather() { + final CMWeatherManager weatherManager = CMWeatherManager.getInstance(GBApplication.getContext()); + if (weatherManager.getActiveWeatherServiceProviderLabel() != null && weatherLocation != null) { + weatherManager.requestWeatherUpdate(weatherLocation, this); + } + } + + @Override + public void onWeatherRequestCompleted(int status, WeatherInfo weatherInfo) { + if (weatherInfo != null) { + LOG.info("weather: " + weatherInfo.toString()); + WeatherSpec weatherSpec = new WeatherSpec(); + weatherSpec.timestamp = (int) (weatherInfo.getTimestamp() / 1000); + weatherSpec.location = weatherInfo.getCity(); + + if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) { + weatherSpec.currentTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTemperature()) + 273; + weatherSpec.todayMaxTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysHigh()) + 273; + weatherSpec.todayMinTemp = (int) WeatherUtils.fahrenheitToCelsius(weatherInfo.getTodaysLow()) + 273; + } else { + weatherSpec.currentTemp = (int) weatherInfo.getTemperature() + 273; + weatherSpec.todayMaxTemp = (int) weatherInfo.getTodaysHigh() + 273; + weatherSpec.todayMinTemp = (int) weatherInfo.getTodaysLow() + 273; + } + + weatherSpec.currentConditionCode = Weather.mapToOpenWeatherMapCondition(CMtoYahooCondintion(weatherInfo.getConditionCode())); + weatherSpec.currentCondition = Weather.getConditionString(weatherSpec.currentConditionCode); + + weatherSpec.forecasts = new ArrayList<>(); + List forecasts = weatherInfo.getForecasts(); + for (int i = 1; i < forecasts.size(); i++) { + WeatherInfo.DayForecast cmForecast = forecasts.get(i); + WeatherSpec.Forecast gbForecast = new WeatherSpec.Forecast(); + if (weatherInfo.getTemperatureUnit() == FAHRENHEIT) { + gbForecast.maxTemp = (int) WeatherUtils.fahrenheitToCelsius(cmForecast.getHigh()) + 273; + gbForecast.minTemp = (int) WeatherUtils.fahrenheitToCelsius(cmForecast.getLow()) + 273; + } else { + gbForecast.maxTemp = (int) cmForecast.getHigh() + 273; + gbForecast.minTemp = (int) cmForecast.getLow() + 273; + } + gbForecast.conditionCode = Weather.mapToOpenWeatherMapCondition(CMtoYahooCondintion(cmForecast.getConditionCode())); + weatherSpec.forecasts.add(gbForecast); + } + Weather.getInstance().setWeatherSpec(weatherSpec); + GBApplication.deviceService().onSendWeather(weatherSpec); + } else { + LOG.info("request has returned null for WeatherInfo"); + } + } + + /** + * @param cmCondition + * @return + */ + private int CMtoYahooCondintion(int cmCondition) { + int yahooCondition; + if (cmCondition <= SHOWERS) { + yahooCondition = cmCondition; + } else if (cmCondition <= SCATTERED_THUNDERSTORMS) { + yahooCondition = cmCondition + 1; + } else if (cmCondition <= SCATTERED_SNOW_SHOWERS) { + yahooCondition = cmCondition + 2; + } else if (cmCondition <= ISOLATED_THUNDERSHOWERS) { + yahooCondition = cmCondition + 3; + } else { + yahooCondition = NOT_AVAILABLE; + } + return yahooCondition; + } + + @Override + public void onLookupCityRequestCompleted(int result, List list) { + if (list != null) { + weatherLocation = list.get(0); + String cityId = weatherLocation.getCityId(); + String city = weatherLocation.getCity(); + + SharedPreferences.Editor editor = GBApplication.getPrefs().getPreferences().edit(); + editor.putString("weather_city", city).apply(); + editor.putString("weather_cityid", cityId).apply(); + enablePeriodicAlarm(true); + requestWeather(); + } else { + enablePeriodicAlarm(false); + } + } +} 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 f50ce7723..3b6c00799 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -50,7 +50,7 @@ import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmClockReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.AlarmReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothPairingRequestReceiver; -//import nodomain.freeyourgadget.gadgetbridge.externalevents.CMWeatherReceiver; +import nodomain.freeyourgadget.gadgetbridge.externalevents.CMWeatherReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.CalendarReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.MusicPlaybackReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.PebbleReceiver; @@ -174,7 +174,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere private AlarmReceiver mAlarmReceiver = null; private CalendarReceiver mCalendarReceiver = null; - //private CMWeatherReceiver mCMWeatherReceiver = null; + private CMWeatherReceiver mCMWeatherReceiver = null; private Random mRandom = new Random(); private final String[] mMusicActions = { @@ -659,12 +659,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere filter.addAction(AlarmClockReceiver.ALARM_DONE_ACTION); registerReceiver(mAlarmClockReceiver, filter); } - /* - if (mCMWeatherReceiver == null) { + if (mCMWeatherReceiver == null && coordinator != null && coordinator.supportsWeather()) { mCMWeatherReceiver = new CMWeatherReceiver(); - registerReceiver(mCMWeatherReceiver, new IntentFilter("HOURLY_ALARM")); + registerReceiver(mCMWeatherReceiver, new IntentFilter("GB_UPDATE_WEATHER")); } - */ } else { if (mPhoneCallReceiver != null) { unregisterReceiver(mPhoneCallReceiver); @@ -699,12 +697,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere unregisterReceiver(mAlarmClockReceiver); mAlarmClockReceiver = null; } - /* if (mCMWeatherReceiver != null) { unregisterReceiver(mCMWeatherReceiver); mCMWeatherReceiver = null; } - */ } } diff --git a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java index 0d136d470..6707939f5 100644 --- a/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java +++ b/app/src/main/java/ru/gelin/android/weather/notification/ParcelableWeather2.java @@ -43,7 +43,7 @@ public class ParcelableWeather2 implements Parcelable { if (version != 2) { return; } - Bundle bundle = in.readBundle(); + Bundle bundle = in.readBundle(getClass().getClassLoader()); weatherSpec.location = bundle.getString("weather_location"); long time = bundle.getLong("weather_time"); @@ -52,7 +52,7 @@ public class ParcelableWeather2 implements Parcelable { bundle.getString("weather_forecast_url"); int conditions = bundle.getInt("weather_conditions"); if (conditions > 0) { - Bundle conditionBundle = in.readBundle(); + Bundle conditionBundle = in.readBundle(getClass().getClassLoader()); reconstructedOWMWeather = new JSONObject(); JSONArray weather = new JSONArray(); JSONObject condition = new JSONObject(); @@ -63,7 +63,9 @@ public class ParcelableWeather2 implements Parcelable { weatherSpec.currentTemp = conditionBundle.getInt("weather_current_temp"); String[] currentConditionType = conditionBundle.getStringArray("weather_condition_types"); - weatherSpec.currentConditionCode = weatherConditionTypesToOpenWeatherMapIds(currentConditionType[0]); + if (currentConditionType != null) { + weatherSpec.currentConditionCode = weatherConditionTypesToOpenWeatherMapIds(currentConditionType[0]); + } weatherSpec.todayMinTemp = conditionBundle.getInt("weather_low_temp"); weatherSpec.todayMaxTemp = conditionBundle.getInt("weather_high_temp"); try { @@ -96,9 +98,12 @@ public class ParcelableWeather2 implements Parcelable { condition = new JSONObject(); main = new JSONObject(); weather = new JSONArray(); - Bundle forecastBundle = in.readBundle(); + Bundle forecastBundle = in.readBundle(getClass().getClassLoader()); String[] forecastConditionType = forecastBundle.getStringArray("weather_condition_types"); - int forecastConditionCode = weatherConditionTypesToOpenWeatherMapIds(forecastConditionType[0]); + int forecastConditionCode = 0; + if (forecastConditionType != null) { + forecastConditionCode = weatherConditionTypesToOpenWeatherMapIds(forecastConditionType[0]); + } int forecastLowTemp = forecastBundle.getInt("weather_low_temp"); int forecastHighTemp = forecastBundle.getInt("weather_high_temp"); weatherSpec.forecasts.add(new WeatherSpec.Forecast(forecastLowTemp, forecastHighTemp, forecastConditionCode)); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c9feac294..334939744 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,6 +110,7 @@ Hide number but display name Hide name and number + Weather location Blacklist Apps Blacklist Calendars diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index b0d543b75..55f111cb3 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -41,6 +41,9 @@ android:key="measurement_system" android:summary="%s" android:title="@string/pref_title_unit_system" /> +