From c5a5cd164981f6bcdc99a2275c47246413cd5bd4 Mon Sep 17 00:00:00 2001 From: "Martin.JM" Date: Sun, 24 Nov 2024 11:26:33 +0100 Subject: [PATCH] Huawei: Send weather error if there is no data This will hopefully reduce the number of requests from the watches if there is no weather data available. --- .../devices/huawei/HuaweiCoordinator.java | 8 +++ .../devices/huawei/packets/Weather.java | 57 +++++++++++++++++ .../devices/huawei/HuaweiWeatherManager.java | 11 +++- .../requests/SendWeatherErrorRequest.java | 62 +++++++++++++++++++ 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherErrorRequest.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java index cd762dab8..65a314d92 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huawei/HuaweiCoordinator.java @@ -541,6 +541,10 @@ public class HuaweiCoordinator { return supportsCommandForService(0x0f, 0x06); } + public boolean supportsWeatherErrorSimple() { + return supportsCommandForService(0x0f, 0x07); + } + public boolean supportsWeatherForecasts() { return supportsCommandForService(0x0f, 0x08); } @@ -553,6 +557,10 @@ public class HuaweiCoordinator { return supportsCommandForService(0x0f, 0x0b); } + public boolean supportsWeatherErrorExtended() { + return supportsCommandForService(0x0f, 0x0c); + } + public boolean supportsWeatherUvIndex() { return supportsExpandCapability(0x2f); } 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 34f7d0877..e1fe67d66 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 @@ -344,6 +344,24 @@ public class Weather { } } + public enum ErrorCode { + NETWORK_ERROR, + GPS_PERMISSION_ERROR, + WEATHER_DISABLED + } + + private static byte errorCodeToByte(ErrorCode errorCode) { + switch (errorCode) { + case NETWORK_ERROR: + return 0; + case GPS_PERMISSION_ERROR: + return 1; + case WEATHER_DISABLED: + return 2; + } + throw new RuntimeException(); // Shouldn't happen + } + public static class CurrentWeatherRequest extends HuaweiPacket { public static final byte id = 0x01; @@ -543,6 +561,22 @@ public class Weather { } } + public static class WeatherErrorSimple { + public static final byte id = 0x07; + + public static class Request extends HuaweiPacket { + public Request(ParamsProvider paramsProvider, ErrorCode errorCode) { + super(paramsProvider); + + this.serviceId = Weather.id; + this.commandId = id; + this.tlv = new HuaweiTLV().put(0x01, errorCodeToByte(errorCode)); + this.isEncrypted = true; + this.complete = true; + } + } + } + public static class WeatherForecastData { public static final byte id = 0x08; @@ -765,4 +799,27 @@ public class Weather { } } } + + public static class WeatherErrorExtended { + public static final byte id = 0x0c; + + public static class Request extends HuaweiPacket { + public Request(ParamsProvider paramsProvider, ErrorCode errorCode, boolean serverError) { + super(paramsProvider); + + this.serviceId = Weather.id; + this.commandId = id; + + HuaweiTLV innerTlv = new HuaweiTLV(); + innerTlv.put(0x02, errorCodeToByte(errorCode)); + if (errorCode == ErrorCode.NETWORK_ERROR && serverError) + innerTlv.put(0x03, (byte) 0x01); + + this.tlv = new HuaweiTLV().put(0x81, innerTlv); + + this.isEncrypted = true; + this.complete = true; + } + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWeatherManager.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWeatherManager.java index 0a40b78fc..ecf258a0c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWeatherManager.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiWeatherManager.java @@ -32,6 +32,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Requ import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendGpsAndTimeToDeviceRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherCurrentRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherDeviceRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.SendWeatherErrorRequest; 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; @@ -277,7 +278,15 @@ public class HuaweiWeatherManager { if (response.getTlv().getInteger(0x7f, -1) == 0x000186AA) { // Send weather final ArrayList specs = new ArrayList<>(nodomain.freeyourgadget.gadgetbridge.model.Weather.getInstance().getWeatherSpecs()); - // TODO: could be empty, not really an issue but we need to check what to send back in that case + if (specs.isEmpty()) { + LOG.debug("Weather specs empty, returning that weather is disabled."); + try { + new SendWeatherErrorRequest(supportProvider, Weather.ErrorCode.WEATHER_DISABLED).doPerform(); + } catch (IOException e) { + LOG.error("Could not send weather error request.", e); + } + return; + } this.sendWeather(specs.get(0)); return; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherErrorRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherErrorRequest.java new file mode 100644 index 000000000..9537138bd --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/requests/SendWeatherErrorRequest.java @@ -0,0 +1,62 @@ +/* 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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket; +import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Weather; +import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.HuaweiSupportProvider; + +public class SendWeatherErrorRequest extends Request { + private static final Logger LOG = LoggerFactory.getLogger(SendWeatherErrorRequest.class); + + private final Weather.ErrorCode errorCode; + + @Override + protected boolean requestSupported() { + return supportProvider.getHuaweiCoordinator().supportsWeatherErrorSimple() || supportProvider.getHuaweiCoordinator().supportsWeatherErrorExtended(); + } + + public SendWeatherErrorRequest(HuaweiSupportProvider support, Weather.ErrorCode errorCode) { + super(support); + this.serviceId = Weather.id; + if (supportProvider.getHuaweiCoordinator().supportsWeatherErrorExtended()) + this.commandId = Weather.WeatherErrorExtended.id; + else + this.commandId = Weather.WeatherErrorSimple.id; + this.errorCode = errorCode; + } + + @Override + protected List createRequest() throws RequestCreationException { + try { + if (supportProvider.getHuaweiCoordinator().supportsWeatherErrorExtended()) { + Weather.WeatherErrorExtended.Request request = new Weather.WeatherErrorExtended.Request(paramsProvider, errorCode, false); + return request.serialize(); + } else { + Weather.WeatherErrorSimple.Request request = new Weather.WeatherErrorSimple.Request(paramsProvider, errorCode); + return request.serialize(); + } + } catch (HuaweiPacket.CryptoException e) { + throw new RequestCreationException(e); + } + } +}