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.
This commit is contained in:
Martin.JM 2024-11-24 11:26:33 +01:00
parent 9a40190e5f
commit c5a5cd1649
4 changed files with 137 additions and 1 deletions

View File

@ -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);
}

View File

@ -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;
}
}
}
}

View File

@ -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<WeatherSpec> 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;
}

View File

@ -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 <https://www.gnu.org/licenses/>. */
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<byte[]> 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);
}
}
}