From 8c49f5437474fde71dc19c48de180776679f5bbd Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sat, 28 Dec 2019 14:11:42 +0100 Subject: [PATCH] Da Fit: Add weather sync --- .../devices/dafit/DaFitConstants.java | 37 +++++++++++++ .../devices/dafit/DaFitDeviceCoordinator.java | 2 +- .../devices/dafit/DaFitWeatherForecast.java | 38 ++++++++++++++ .../devices/dafit/DaFitWeatherToday.java | 52 +++++++++++++++++++ .../devices/dafit/DaFitDeviceSupport.java | 35 ++++++++++++- 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherForecast.java create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherToday.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java index 7b86ce2e3..32d4021de 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitConstants.java @@ -332,4 +332,41 @@ public class DaFitConstants { return NOTIFICATION_TYPE_MESSAGE_OTHER; } } + + + // Weather types + public static final byte WEATHER_CLOUDY = 0; + public static final byte WEATHER_FOGGY = 1; + public static final byte WEATHER_OVERCAST = 2; + public static final byte WEATHER_RAINY = 3; + public static final byte WEATHER_SNOWY = 4; + public static final byte WEATHER_SUNNY = 5; + public static final byte WEATHER_SANDSTORM = 6; // aka "wind", according to the image + public static final byte WEATHER_HAZE = 7; // it's basically very big fog :P + // NOTE: values > 7 give random glitchy crap as images :D + + public static byte openWeatherConditionToDaFitConditionId(int openWeatherMapCondition) { + int openWeatherMapGroup = openWeatherMapCondition / 100; + switch (openWeatherMapGroup) { + case 2: // thunderstorm + case 3: // drizzle + case 5: // rain + return DaFitConstants.WEATHER_RAINY; + case 6: // snow + return DaFitConstants.WEATHER_SNOWY; + case 7: // fog + return DaFitConstants.WEATHER_FOGGY; + case 8: // clear / clouds + if (openWeatherMapCondition <= 801) // few clouds + return DaFitConstants.WEATHER_SUNNY; + if (openWeatherMapCondition >= 804) // overcast clouds + return DaFitConstants.WEATHER_CLOUDY; + return DaFitConstants.WEATHER_OVERCAST; + case 9: // extreme + default: + if (openWeatherMapCondition == 905) // windy + return DaFitConstants.WEATHER_SANDSTORM; + return DaFitConstants.WEATHER_HAZE; + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitDeviceCoordinator.java index cc1a484bd..a46a76d4d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitDeviceCoordinator.java @@ -150,7 +150,7 @@ public class DaFitDeviceCoordinator extends AbstractDeviceCoordinator { @Override public boolean supportsWeather() { - return false; + return true; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherForecast.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherForecast.java new file mode 100644 index 000000000..e33964014 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherForecast.java @@ -0,0 +1,38 @@ +/* Copyright (C) 2019 krzys_h + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.devices.dafit; + +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; + +public class DaFitWeatherForecast { + public final byte conditionId; + public final byte minTemp; + public final byte maxTemp; + + public DaFitWeatherForecast(byte conditionId, byte minTemp, byte maxTemp) { + this.conditionId = conditionId; + this.minTemp = minTemp; + this.maxTemp = maxTemp; + } + + public DaFitWeatherForecast(WeatherSpec.Forecast forecast) + { + conditionId = DaFitConstants.openWeatherConditionToDaFitConditionId(forecast.conditionCode); + minTemp = (byte)(forecast.minTemp - 273); // Kelvin -> Celcius + maxTemp = (byte)(forecast.maxTemp - 273); // Kelvin -> Celcius + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherToday.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherToday.java new file mode 100644 index 000000000..fe4e78144 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/dafit/DaFitWeatherToday.java @@ -0,0 +1,52 @@ +/* Copyright (C) 2019 krzys_h + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.devices.dafit; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; +import nodomain.freeyourgadget.gadgetbridge.util.StringUtils; + +public class DaFitWeatherToday { + public final byte conditionId; + public final byte currentTemp; + public final Short pm25; // (*) + public final String lunar_or_festival; // (*) + public final String city; // (*) + + public DaFitWeatherToday(byte conditionId, byte currentTemp, @Nullable Short pm25, @NonNull String lunar_or_festival, @NonNull String city) { + if (lunar_or_festival.length() != 4) + throw new IllegalArgumentException("lunar_or_festival"); + if (city.length() != 4) + throw new IllegalArgumentException("city"); + this.conditionId = conditionId; + this.currentTemp = currentTemp; + this.pm25 = pm25; + this.lunar_or_festival = lunar_or_festival; + this.city = city; + } + + public DaFitWeatherToday(WeatherSpec weatherSpec) + { + conditionId = DaFitConstants.openWeatherConditionToDaFitConditionId(weatherSpec.currentConditionCode); + currentTemp = (byte)(weatherSpec.currentTemp - 273); // Kelvin -> Celcius + pm25 = null; + lunar_or_festival = StringUtils.pad("", 4); + city = StringUtils.pad(weatherSpec.location.substring(0, 4), 4); + } +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java index 5331a0ed7..95ec2f948 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/dafit/DaFitDeviceSupport.java @@ -47,6 +47,8 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallContro import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventMusicControl; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo; import nodomain.freeyourgadget.gadgetbridge.devices.dafit.DaFitConstants; +import nodomain.freeyourgadget.gadgetbridge.devices.dafit.DaFitWeatherForecast; +import nodomain.freeyourgadget.gadgetbridge.devices.dafit.DaFitWeatherToday; import nodomain.freeyourgadget.gadgetbridge.devices.dafit.DaFitSampleProvider; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.DaFitActivitySample; @@ -952,7 +954,38 @@ public class DaFitDeviceSupport extends AbstractBTLEDeviceSupport { @Override public void onSendWeather(WeatherSpec weatherSpec) { - // TODO + try { + TransactionBuilder builder = performInitialized("onSendWeather"); + + DaFitWeatherToday weatherToday = new DaFitWeatherToday(weatherSpec); + ByteBuffer packetWeatherToday = ByteBuffer.allocate(weatherToday.pm25 != null ? 21 : 19); + packetWeatherToday.put(weatherToday.pm25 != null ? (byte)1 : (byte)0); + packetWeatherToday.put(weatherToday.conditionId); + packetWeatherToday.put(weatherToday.currentTemp); + if (weatherToday.pm25 != null) + packetWeatherToday.putShort(weatherToday.pm25); + packetWeatherToday.put(weatherToday.lunar_or_festival.getBytes("unicodebigunmarked")); + packetWeatherToday.put(weatherToday.city.getBytes("unicodebigunmarked")); + sendPacket(builder, DaFitPacketOut.buildPacket(DaFitConstants.CMD_SET_WEATHER_TODAY, packetWeatherToday.array())); + + ByteBuffer packetWeatherForecast = ByteBuffer.allocate(7 * 3); + for(int i = 0; i < 7; i++) + { + DaFitWeatherForecast forecast; + if (weatherSpec.forecasts.size() > i) + forecast = new DaFitWeatherForecast(weatherSpec.forecasts.get(i)); + else + forecast = new DaFitWeatherForecast(DaFitConstants.WEATHER_HAZE, (byte)-100, (byte)-100); // I don't think there is a way to send less (my watch shows only tomorrow anyway...) + packetWeatherForecast.put(forecast.conditionId); + packetWeatherForecast.put(forecast.minTemp); + packetWeatherForecast.put(forecast.maxTemp); + } + sendPacket(builder, DaFitPacketOut.buildPacket(DaFitConstants.CMD_SET_WEATHER_FUTURE, packetWeatherForecast.array())); + + builder.queue(getQueue()); + } catch (IOException e) { + e.printStackTrace(); + } } @Override