diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Coordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Coordinator.java index 245d0c66a..66a50a55a 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Coordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Coordinator.java @@ -52,8 +52,7 @@ public abstract class Huami2021Coordinator extends HuamiCoordinator { @Override public boolean supportsWeather() { - // TODO: It's supported by the devices, but not yet implemented - return false; + return true; } @Override diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Service.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Service.java index 258fa42f2..ac3a8ce8b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Service.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/Huami2021Service.java @@ -258,4 +258,10 @@ public class Huami2021Service { public static final byte CALENDAR_CMD_CREATE_EVENT_ACK = 0x08; public static final byte CALENDAR_CMD_DELETE_EVENT = 0x09; public static final byte CALENDAR_CMD_DELETE_EVENT_ACK = 0x0a; + + /** + * Weather, for {@link Huami2021Service#CHUNKED2021_ENDPOINT_WEATHER}. + */ + public static final byte WEATHER_CMD_SET_DEFAULT_LOCATION = 0x09; + public static final byte WEATHER_CMD_DEFAULT_LOCATION_ACK = 0x0a; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java index 6e0014933..4388d6509 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Support.java @@ -1049,7 +1049,7 @@ public abstract class Huami2021Support extends HuamiSupport { try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write((byte) 0x09); + baos.write(Huami2021Service.WEATHER_CMD_SET_DEFAULT_LOCATION); baos.write((byte) 0x02); // ? 2 for current, 4 for default baos.write((byte) 0x00); // ? baos.write((byte) 0x00); // ? @@ -1720,6 +1720,9 @@ public abstract class Huami2021Support extends HuamiSupport { case CHUNKED2021_ENDPOINT_ICONS: handle2021Icons(payload); return; + case CHUNKED2021_ENDPOINT_WEATHER: + handle2021Weather(payload); + return; case CHUNKED2021_ENDPOINT_WORKOUT: handle2021Workout(payload); return; @@ -2427,6 +2430,16 @@ public abstract class Huami2021Support extends HuamiSupport { } } + protected void handle2021Weather(final byte[] payload) { + switch (payload[0]) { + case WEATHER_CMD_DEFAULT_LOCATION_ACK: + LOG.info("Weather default location ACK, status = {}", payload[1]); + return; + default: + LOG.warn("Unexpected weather byte {}", String.format("0x%02x", payload[0])); + } + } + private void sendNextQueuedIconData() { if (queuedIconPackage == null) { LOG.error("No queued icon to send"); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Weather.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Weather.java index 9ca1f602e..3cffae38c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Weather.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021Weather.java @@ -120,44 +120,60 @@ public class Huami2021Weather { public List windDirection = new ArrayList<>(); public List sunRiseSet = new ArrayList<>(); public List windSpeed = new ArrayList<>(); - public List moonRiseSet = new ArrayList<>(); + public Object moonRiseSet = new Object(); public List airQualities = new ArrayList<>(); public ForecastResponse(final WeatherSpec weatherSpec, final int days) { + final int actualDays = Math.min(weatherSpec.forecasts.size(), days - 1); // leave one slot for the first day + pubTime = new Date(weatherSpec.timestamp * 1000L); final Calendar calendar = GregorianCalendar.getInstance(); - calendar.setTime(new Date(weatherSpec.timestamp * 1000L)); + calendar.setTime(pubTime); - // TODO: We should send sunrise on the same location as the weather - final SimpleDateFormat sunRiseSetSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT); final Location lastKnownLocation = new CurrentPosition().getLastKnownLocation(); final GregorianCalendar sunriseDate = new GregorianCalendar(); sunriseDate.setTime(calendar.getTime()); - for (int i = 0; i < Math.min(weatherSpec.forecasts.size(), days); i++) { + // First one is for the current day + temperature.add(new Range(weatherSpec.todayMinTemp - 273, weatherSpec.todayMaxTemp - 273)); + final String currentWeatherCode = String.valueOf(HuamiWeatherConditions.mapToAmazfitBipWeatherCode(weatherSpec.currentConditionCode) & 0xff); + weather.add(new Range(currentWeatherCode, currentWeatherCode)); + sunRiseSet.add(getSunriseSunset(sunriseDate, lastKnownLocation)); + sunriseDate.add(Calendar.DAY_OF_MONTH, 1); + windDirection.add(new Range(0, 0)); + windSpeed.add(new Range(0, 0)); + + for (int i = 0; i < actualDays; i++) { final WeatherSpec.Forecast forecast = weatherSpec.forecasts.get(i); temperature.add(new Range(forecast.minTemp - 273, forecast.maxTemp - 273)); - final String weatherCode = String.valueOf(HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.conditionCode) & 0xff); // is it? + final String weatherCode = String.valueOf(HuamiWeatherConditions.mapToAmazfitBipWeatherCode(forecast.conditionCode) & 0xff); weather.add(new Range(weatherCode, weatherCode)); - final GregorianCalendar[] sunriseTransitSet = SPA.calculateSunriseTransitSet( - sunriseDate, - lastKnownLocation.getLatitude(), - lastKnownLocation.getLongitude(), - DeltaT.estimate(sunriseDate) - ); - - final String from = sunRiseSetSdf.format(sunriseTransitSet[0].getTime()); - final String to = sunRiseSetSdf.format(sunriseTransitSet[2].getTime()); - sunRiseSet.add(new Range(from, to)); - + sunRiseSet.add(getSunriseSunset(sunriseDate, lastKnownLocation)); sunriseDate.add(Calendar.DAY_OF_MONTH, 1); windDirection.add(new Range(0, 0)); windSpeed.add(new Range(0, 0)); } } + + private Range getSunriseSunset(final GregorianCalendar date, final Location location) { + // TODO: We should send sunrise on the same location as the weather + final SimpleDateFormat sunRiseSetSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT); + + final GregorianCalendar[] sunriseTransitSet = SPA.calculateSunriseTransitSet( + date, + location.getLatitude(), + location.getLongitude(), + DeltaT.estimate(date) + ); + + final String from = sunRiseSetSdf.format(sunriseTransitSet[0].getTime()); + final String to = sunRiseSetSdf.format(sunriseTransitSet[2].getTime()); + + return new Range(from, to); + } } private static class Range {