diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Weather.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Weather.java index 53866dfe8..757e6e1df 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Weather.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/packets/Weather.java @@ -16,6 +16,8 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets; +import java.util.List; + import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiTLV; @@ -202,6 +204,78 @@ public class Weather { } } + public static class WeatherForecastDataRequest extends HuaweiPacket { + public static final byte id = 0x08; + + public static class TimeData { + public int timestamp; + public byte icon; + public byte temperature; + } + + public static class DayData { + public int timestamp; + public byte icon; + public byte highTemperature; + public byte lowTemperature; + public int sunriseTime; + public int sunsetTime; + public int moonRiseTime; + public int moonSetTime; + public byte moonPhase; // TODO: probably enum + } + + public WeatherForecastDataRequest( + ParamsProvider paramsProvider, + List timeDataList, + List dayDataList + ) { + super(paramsProvider); + + this.serviceId = Weather.id; + this.commandId = id; + this.tlv = new HuaweiTLV(); + + if (timeDataList != null && !timeDataList.isEmpty()) { + HuaweiTLV timeDataTlv = new HuaweiTLV(); + for (TimeData timeData : timeDataList) { + // TODO: NULLs? + timeDataTlv.put(0x82, new HuaweiTLV() + .put(0x03, timeData.timestamp) + .put(0x04, timeData.icon) + .put(0x05, timeData.temperature) + ); + } + this.tlv.put(0x81, timeDataTlv); + } +// this.tlv.put(0x81); + + if (dayDataList != null && !dayDataList.isEmpty()) { + HuaweiTLV dayDataTlv = new HuaweiTLV(); + for (DayData dayData : dayDataList) { + // TODO: NULLs? + dayDataTlv.put(0x91, new HuaweiTLV() + .put(0x12, dayData.timestamp) + .put(0x13, dayData.icon) + .put(0x14, dayData.highTemperature) + .put(0x15, dayData.lowTemperature) + .put(0x16, dayData.sunriseTime) + .put(0x17, dayData.sunsetTime) + .put(0x1a, dayData.moonRiseTime) + .put(0x1b, dayData.moonSetTime) + .put(0x1e, dayData.moonPhase) + ); + } + this.tlv.put(0x90, dayDataTlv); + } +// this.tlv.put(0x90); + + this.isEncrypted = true; + this.isSliced = true; + this.complete = true; + } + } + public static class WeatherStart { public static final byte id = 0x09; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java index 2323245d8..514bc4597 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java @@ -82,6 +82,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Send import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyHeartRateCapabilityRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendNotifyRestHeartRateCapabilityRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherExtendedSupportRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherForecastRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherStartRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherSunMoonSupportRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherSupportRequest; @@ -1656,6 +1657,15 @@ public class HuaweiSupportProvider { weatherSettings, weatherSpec ); + + if (getHuaweiCoordinator().supportsWeatherForecasts()) { + SendWeatherForecastRequest sendWeatherForecastRequest = new SendWeatherForecastRequest( + this, + weatherSpec + ); + sendWeatherCurrentRequest.nextRequest(sendWeatherForecastRequest); + } + sendWeatherCurrentRequest.doPerform(); } catch (IOException e) { // TODO: Use translatable string @@ -1680,35 +1690,32 @@ public class HuaweiSupportProvider { }; SendWeatherStartRequest weatherStartRequest = new SendWeatherStartRequest(this); - weatherStartRequest.setFinalizeReq(requestCallback); Request lastRequest = weatherStartRequest; if (getHuaweiCoordinator().supportsWeatherUnit()) { SendWeatherUnitRequest weatherUnitRequest = new SendWeatherUnitRequest(this); - weatherUnitRequest.setFinalizeReq(requestCallback); lastRequest.nextRequest(weatherUnitRequest); lastRequest = weatherUnitRequest; } SendWeatherSupportRequest weatherSupportRequest = new SendWeatherSupportRequest(this, weatherSettings); - weatherSupportRequest.setFinalizeReq(requestCallback); lastRequest.nextRequest(weatherSupportRequest); lastRequest = weatherSupportRequest; if (getHuaweiCoordinator().supportsWeatherExtended()) { SendWeatherExtendedSupportRequest weatherExtendedSupportRequest = new SendWeatherExtendedSupportRequest(this, weatherSettings); - weatherExtendedSupportRequest.setFinalizeReq(requestCallback); lastRequest.nextRequest(weatherExtendedSupportRequest); lastRequest = weatherExtendedSupportRequest; } if (getHuaweiCoordinator().supportsWeatherMoonRiseSet()) { SendWeatherSunMoonSupportRequest weatherSunMoonSupportRequest = new SendWeatherSunMoonSupportRequest(this, weatherSettings); - weatherSunMoonSupportRequest.setFinalizeReq(requestCallback); lastRequest.nextRequest(weatherSunMoonSupportRequest); -// lastRequest = weatherSunMoonSupportRequest; + lastRequest = weatherSunMoonSupportRequest; } + lastRequest.setFinalizeReq(requestCallback); + try { weatherStartRequest.doPerform(); } catch (IOException e) { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherForecastRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherForecastRequest.java new file mode 100644 index 000000000..fb58a373a --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherForecastRequest.java @@ -0,0 +1,94 @@ +/* Copyright (C) 2024 Martin.JM + + This file is part of Gadgetbridge. + + Gadgetbridge is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Gadgetbridge is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests; + +import java.util.ArrayList; +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather; +import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather.WeatherForecastDataRequest; + +public class SendWeatherForecastRequest extends Request { + WeatherSpec weatherSpec; + + public SendWeatherForecastRequest(HuaweiSupportProvider support, WeatherSpec weatherSpec) { + super(support); + this.serviceId = Weather.id; + this.commandId = Weather.WeatherForecastDataRequest.id; + this.weatherSpec = weatherSpec; + } + + @Override + protected List createRequest() throws RequestCreationException { + // TODO: Weather settings + ArrayList timeDataArrayList = new ArrayList<>( + this.weatherSpec.hourly.size() // TODO: wrong size + ); + ArrayList dayDataArrayList = new ArrayList<>( + this.weatherSpec.forecasts.size() // TODO: wrong size + ); + // for (WeatherSpec.Hourly hourly : weatherSpec.hourly) { + for (int i = 0; i < Math.min(weatherSpec.hourly.size(), 24); i++) { // TODO: min? + WeatherSpec.Hourly hourly = weatherSpec.hourly.get(i); + WeatherForecastDataRequest.TimeData timeData = new WeatherForecastDataRequest.TimeData(); + timeData.timestamp = hourly.timestamp; + timeData.icon = 1; // TODO: hourly.conditionCode conversion + timeData.temperature = (byte) (hourly.temp - 273); + timeDataArrayList.add(timeData); + } + + // Add today as well + WeatherForecastDataRequest.DayData today = new WeatherForecastDataRequest.DayData(); + today.timestamp = weatherSpec.sunRise; + today.icon = 1; // TODO + today.highTemperature = (byte) (weatherSpec.todayMaxTemp - 273); + today.lowTemperature = (byte) (weatherSpec.todayMinTemp - 273); + today.sunriseTime = weatherSpec.sunRise; + today.sunsetTime = weatherSpec.sunSet; + today.moonRiseTime = weatherSpec.moonRise; + today.moonSetTime = weatherSpec.moonSet; + today.moonPhase = (byte) 4; // weatherSpec.moonPhase; // TODO: check + dayDataArrayList.add(today); + + for (int i = 0; i < Math.min(weatherSpec.forecasts.size(), 7); i++) { // TODO: min? + WeatherSpec.Daily daily = weatherSpec.forecasts.get(i); + WeatherForecastDataRequest.DayData dayData = new WeatherForecastDataRequest.DayData(); + dayData.timestamp = daily.sunRise; + dayData.icon = 1; // TODO: daily.conditionCode conversion + dayData.highTemperature = (byte) (daily.maxTemp - 273); + dayData.lowTemperature = (byte) (daily.minTemp - 273); + dayData.sunriseTime = daily.sunRise; + dayData.sunsetTime = daily.sunSet; + dayData.moonRiseTime = daily.moonRise; + dayData.moonSetTime = daily.moonSet; + dayData.moonPhase = (byte) 4; // daily.moonPhase; // TODO: check + dayDataArrayList.add(dayData); + } + try { + return new WeatherForecastDataRequest( + this.paramsProvider, + timeDataArrayList, + dayDataArrayList + ).serialize(); + } catch (HuaweiPacket.CryptoException e) { + throw new RequestCreationException(e); + } + } +}