From d07ca6faa6b3debfe5d465d2db2e80c0e6fecbf7 Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 25 Aug 2019 09:55:23 +0200 Subject: [PATCH] Mi Band 4: Fix location not being updated on the Band Also move generic code from AmazfitBipSupport to HuamiSupport where is belongs Fixes #1609 --- .../service/devices/huami/HuamiSupport.java | 190 ++++++++++++++++- .../huami/amazfitbip/AmazfitBipSupport.java | 195 +----------------- 2 files changed, 190 insertions(+), 195 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java index 9d0c5b14d..b8f1f7624 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/HuamiSupport.java @@ -42,11 +42,13 @@ import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.Set; +import java.util.SimpleTimeZone; import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import java.util.concurrent.TimeUnit; +import cyanogenmod.weather.util.WeatherUtils; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.Logging; import nodomain.freeyourgadget.gadgetbridge.R; @@ -66,6 +68,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiConst; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService; +import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiWeatherConditions; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService; import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2FWHelper; import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband3.MiBand3Coordinator; @@ -95,6 +98,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; 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.AbstractBTLEDeviceSupport; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; @@ -762,9 +766,8 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { } + private void sendMusicStateToDevice() { - - if (characteristicChunked == null) { return; } @@ -1584,7 +1587,190 @@ public class HuamiSupport extends AbstractBTLEDeviceSupport { @Override public void onSendWeather(WeatherSpec weatherSpec) { + // FIXME: currently HuamiSupport *is* MiBand2 support, so return if we are using Mi Band 2 + if (gbDevice.getType() == DeviceType.MIBAND2) { + return; + } + 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; + } + + MiBandConst.DistanceUnit unit = HuamiCoordinator.getDistanceUnit(); + 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); + + int currentTemp = weatherSpec.currentTemp - 273; + if (unit == MiBandConst.DistanceUnit.IMPERIAL) { + currentTemp = (int) WeatherUtils.celsiusToFahrenheit(currentTemp); + } + buf.put((byte) currentTemp); + + if (supportsConditionString) { + buf.put(weatherSpec.currentCondition.getBytes()); + buf.put((byte) 0); + } + + if (characteristicChunked != null) { + writeToChunked(builder, 1, buf.array()); + } else { + builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); + } + + builder.queue(getQueue()); + } catch (Exception ex) { + LOG.error("Error sending current weather", ex); + } + + try { + TransactionBuilder builder; + builder = performInitialized("Sending air quality index"); + int length = 8; + String aqiString = "(n/a)"; + 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); + } + + if (characteristicChunked != null) { + writeToChunked(builder, 1, buf.array()); + } else { + builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); + } + + builder.queue(getQueue()); + } catch (IOException ex) { + LOG.error("Error sending air quality"); + } + + try { + TransactionBuilder builder = performInitialized("Sending weather forecast"); + + 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); + + buf.order(ByteOrder.LITTLE_ENDIAN); + buf.put((byte) 1); + buf.putInt(weatherSpec.timestamp); + buf.put((byte) (tz_offset_hours * 4)); + + buf.put(NR_DAYS); + + byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode); + buf.put(condition); + buf.put(condition); + + int todayMaxTemp = weatherSpec.todayMaxTemp - 273; + int todayMinTemp = weatherSpec.todayMinTemp - 273; + if (unit == MiBandConst.DistanceUnit.IMPERIAL) { + todayMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMaxTemp); + todayMinTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMinTemp); + } + buf.put((byte) todayMaxTemp); + buf.put((byte) todayMinTemp); + + if (supportsConditionString) { + buf.put(weatherSpec.currentCondition.getBytes()); + buf.put((byte) 0); + } + + for (WeatherSpec.Forecast forecast : weatherSpec.forecasts) { + condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.conditionCode); + buf.put(condition); + buf.put(condition); + + int forecastMaxTemp = forecast.maxTemp - 273; + int forecastMinTemp = forecast.minTemp - 273; + if (unit == MiBandConst.DistanceUnit.IMPERIAL) { + forecastMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMaxTemp); + forecastMinTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMinTemp); + } + buf.put((byte) forecastMaxTemp); + buf.put((byte) forecastMinTemp); + + if (supportsConditionString) { + buf.put(Weather.getConditionString(forecast.conditionCode).getBytes()); + buf.put((byte) 0); + } + } + + if (characteristicChunked != null) { + writeToChunked(builder, 1, buf.array()); + } else { + builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); + } + + builder.queue(getQueue()); + } catch (Exception ex) { + LOG.error("Error sending weather forecast", ex); + } + + try { + TransactionBuilder builder; + builder = performInitialized("Sending forecast location"); + + int length = 2 + weatherSpec.location.getBytes().length; + ByteBuffer buf = ByteBuffer.allocate(length); + buf.order(ByteOrder.LITTLE_ENDIAN); + buf.put((byte) 8); + buf.put(weatherSpec.location.getBytes()); + buf.put((byte) 0); + + + if (characteristicChunked != null) { + writeToChunked(builder, 4, buf.array()); + } else { + builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); + } + + builder.queue(getQueue()); + } catch (Exception ex) { + LOG.error("Error sending current forecast location", ex); + } } private HuamiSupport setDateDisplay(TransactionBuilder builder) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java index e67c6532e..469e360c7 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitbip/AmazfitBipSupport.java @@ -28,39 +28,30 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.Set; -import java.util.SimpleTimeZone; import java.util.UUID; -import cyanogenmod.weather.util.WeatherUtils; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper; import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService; -import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiWeatherConditions; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipFWHelper; import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService; -import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.model.RecordedDataTypes; -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; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile; import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiIcon; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiSupport; -import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.HuamiFetchDebugLogsOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.FetchActivityOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.FetchSportsSummaryOperation; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.operations.HuamiFetchDebugLogsOperation; import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy; import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; -import nodomain.freeyourgadget.gadgetbridge.util.Version; public class AmazfitBipSupport extends HuamiSupport { @@ -248,187 +239,6 @@ public class AmazfitBipSupport extends HuamiSupport { builder.write(getCharacteristic(HuamiService.UUID_CHARACTERISTIC_3_CONFIGURATION), command); } - @Override - public void onSendWeather(WeatherSpec weatherSpec) { - 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; - } - - MiBandConst.DistanceUnit unit = HuamiCoordinator.getDistanceUnit(); - 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); - - int currentTemp = weatherSpec.currentTemp - 273; - if (unit == MiBandConst.DistanceUnit.IMPERIAL) { - currentTemp = (int) WeatherUtils.celsiusToFahrenheit(currentTemp); - } - buf.put((byte) currentTemp); - - if (supportsConditionString) { - buf.put(weatherSpec.currentCondition.getBytes()); - buf.put((byte) 0); - } - - if (characteristicChunked != null) { - writeToChunked(builder, 1, buf.array()); - } else { - builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); - } - - builder.queue(getQueue()); - } catch (Exception ex) { - LOG.error("Error sending current weather", ex); - } - - if (gbDevice.getType() != DeviceType.AMAZFITCOR) { - try { - TransactionBuilder builder; - builder = performInitialized("Sending air quality index"); - int length = 8; - String aqiString = "(n/a)"; - 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); - } - - if (characteristicChunked != null) { - writeToChunked(builder, 1, buf.array()); - } else { - builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); - } - - builder.queue(getQueue()); - } catch (IOException ex) { - LOG.error("Error sending air quality"); - } - } - - try { - TransactionBuilder builder = performInitialized("Sending weather forecast"); - - 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); - - buf.order(ByteOrder.LITTLE_ENDIAN); - buf.put((byte) 1); - buf.putInt(weatherSpec.timestamp); - buf.put((byte) (tz_offset_hours * 4)); - - buf.put(NR_DAYS); - - byte condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode); - buf.put(condition); - buf.put(condition); - - int todayMaxTemp = weatherSpec.todayMaxTemp - 273; - int todayMinTemp = weatherSpec.todayMinTemp - 273; - if (unit == MiBandConst.DistanceUnit.IMPERIAL) { - todayMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMaxTemp); - todayMinTemp = (int) WeatherUtils.celsiusToFahrenheit(todayMinTemp); - } - buf.put((byte) todayMaxTemp); - buf.put((byte) todayMinTemp); - - if (supportsConditionString) { - buf.put(weatherSpec.currentCondition.getBytes()); - buf.put((byte) 0); - } - - for (WeatherSpec.Forecast forecast : weatherSpec.forecasts) { - condition = HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.conditionCode); - buf.put(condition); - buf.put(condition); - - int forecastMaxTemp = forecast.maxTemp - 273; - int forecastMinTemp = forecast.minTemp - 273; - if (unit == MiBandConst.DistanceUnit.IMPERIAL) { - forecastMaxTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMaxTemp); - forecastMinTemp = (int) WeatherUtils.celsiusToFahrenheit(forecastMinTemp); - } - buf.put((byte) forecastMaxTemp); - buf.put((byte) forecastMinTemp); - - if (supportsConditionString) { - buf.put(Weather.getConditionString(forecast.conditionCode).getBytes()); - buf.put((byte) 0); - } - } - - if (characteristicChunked != null) { - writeToChunked(builder, 1, buf.array()); - } else { - builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); - } - - builder.queue(getQueue()); - } catch (Exception ex) { - LOG.error("Error sending weather forecast", ex); - } - - if (gbDevice.getType() == DeviceType.AMAZFITCOR) { - try { - TransactionBuilder builder; - builder = performInitialized("Sending forecast location"); - - int length = 2 + weatherSpec.location.getBytes().length; - ByteBuffer buf = ByteBuffer.allocate(length); - buf.order(ByteOrder.LITTLE_ENDIAN); - buf.put((byte) 8); - buf.put(weatherSpec.location.getBytes()); - buf.put((byte) 0); - - builder.write(getCharacteristic(AmazfitBipService.UUID_CHARACTERISTIC_WEATHER), buf.array()); - builder.queue(getQueue()); - } catch (Exception ex) { - LOG.error("Error sending current forecast location", ex); - } - } - } - @Override public void onFetchRecordedData(int dataTypes) { try { @@ -439,8 +249,7 @@ public class AmazfitBipSupport extends HuamiSupport { new FetchSportsSummaryOperation(this).perform(); } else if (dataTypes == RecordedDataTypes.TYPE_DEBUGLOGS) { new HuamiFetchDebugLogsOperation(this).perform(); - } - else { + } else { LOG.warn("fetching multiple data types at once is not supported yet"); } } catch (IOException ex) {